From fd1d312ba84edeacc9b95b03f23e26c58bd71efe Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 30 Jan 2017 05:35:05 -0500 Subject: [PATCH 01/16] Create bigint_modexp.md --- EIPS/bigint_modexp.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 EIPS/bigint_modexp.md diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md new file mode 100644 index 0000000000000..d117791c4f8d9 --- /dev/null +++ b/EIPS/bigint_modexp.md @@ -0,0 +1,29 @@ +### Parameters + +* `GQUADDIVISOR: 20` + +### Specification + +At address 0x00......05, add a precompile that expects input in the following format: + + + +Where every length is a 32-byte left-padded integer representing the number of bytes to be taken up by the next value. Consumes `floor(length(MODULUS)**2 * length(EXPONENT) / GQUADDIVISOR)` gas. If there is enough gas, returns an output as a byte array with the same length as the modulus. + +Example: + + 000000000000000000000000000000000000000000000000000000000000000103 + 0000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e + 0000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f + +Represents the exponent 3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977). By Fermat's little theorem, this equals 1, so the result is: + + 0000000000000000000000000000000000000000000000000000000000000001 + +Returned as 32 bytes because the modulus length was 32 bytes. The gas cost would be 32**2 * 32 / 20 = 1638 gas (note that this roughly equals the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost 256**2 * 256 / 20 = 838860 gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 3276 or 6553, respectively. + +### Rationale + +This allows for efficient RSA verification inside of the EVM, as well as other forms of number theory-based cryptography. Note that adding precompiles for addition and subtraction is not required, as the in-EVM algorithm is efficient enough, and multiplication can be done through this precompile via `a * b = ((a + b)**2 - (a - b)**2) / 4`. + + From 22b92a05323b5d7810b9eda026c80960f4355720 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 30 Jan 2017 05:36:25 -0500 Subject: [PATCH 02/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index d117791c4f8d9..ba498fe0a1769 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -16,11 +16,11 @@ Example: 0000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e 0000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f -Represents the exponent 3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977). By Fermat's little theorem, this equals 1, so the result is: +Represents the exponent `3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977)`. By Fermat's little theorem, this equals 1, so the result is: 0000000000000000000000000000000000000000000000000000000000000001 -Returned as 32 bytes because the modulus length was 32 bytes. The gas cost would be 32**2 * 32 / 20 = 1638 gas (note that this roughly equals the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost 256**2 * 256 / 20 = 838860 gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 3276 or 6553, respectively. +Returned as 32 bytes because the modulus length was 32 bytes. The gas cost would be `32**2 * 32 / 20 = 1638` gas (note that this roughly equals the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `256**2 * 256 / 20 = 838860` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 3276 or 6553, respectively. ### Rationale From 61145e3250c85a621dbfbb4621c91440867667a7 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 30 Jan 2017 05:40:04 -0500 Subject: [PATCH 03/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index ba498fe0a1769..f2697e79bc43c 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -10,11 +10,14 @@ At address 0x00......05, add a precompile that expects input in the following fo Where every length is a 32-byte left-padded integer representing the number of bytes to be taken up by the next value. Consumes `floor(length(MODULUS)**2 * length(EXPONENT) / GQUADDIVISOR)` gas. If there is enough gas, returns an output as a byte array with the same length as the modulus. -Example: +For example, the input data: - 000000000000000000000000000000000000000000000000000000000000000103 - 0000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e - 0000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f + 0000000000000000000000000000000000000000000000000000000000000001 + 03 + 0000000000000000000000000000000000000000000000000000000000000020 + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e + 0000000000000000000000000000000000000000000000000000000000000020 + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f Represents the exponent `3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977)`. By Fermat's little theorem, this equals 1, so the result is: From c4a771ed3421b1840c3a9d77fbac05b8b58ad2c4 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Wed, 1 Feb 2017 21:27:45 -0500 Subject: [PATCH 04/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index f2697e79bc43c..f314280ee49cf 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -8,7 +8,7 @@ At address 0x00......05, add a precompile that expects input in the following fo -Where every length is a 32-byte left-padded integer representing the number of bytes to be taken up by the next value. Consumes `floor(length(MODULUS)**2 * length(EXPONENT) / GQUADDIVISOR)` gas. If there is enough gas, returns an output as a byte array with the same length as the modulus. +Where every length is a 32-byte left-padded integer representing the number of bytes to be taken up by the next value. If the input cannot be fully parsed in this way (ie. attempting to parse it in this way either tries to consume more call data than is given or leaves some call data unused), then it throws an exception. Also, throws if `BASE >= MODULUS`. Otherwise, consumes `floor(length(MODULUS)**2 * length(EXPONENT) / 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. For example, the input data: @@ -25,6 +25,16 @@ Represents the exponent `3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977)`. By Returned as 32 bytes because the modulus length was 32 bytes. The gas cost would be `32**2 * 32 / 20 = 1638` gas (note that this roughly equals the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `256**2 * 256 / 20 = 838860` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 3276 or 6553, respectively. +This input data: + + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000020 + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e + 0000000000000000000000000000000000000000000000000000000000000020 + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f + +Would + ### Rationale This allows for efficient RSA verification inside of the EVM, as well as other forms of number theory-based cryptography. Note that adding precompiles for addition and subtraction is not required, as the in-EVM algorithm is efficient enough, and multiplication can be done through this precompile via `a * b = ((a + b)**2 - (a - b)**2) / 4`. From 1c3ee1378baf207adc5a1726767ecc00e7552237 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Wed, 1 Feb 2017 21:34:02 -0500 Subject: [PATCH 05/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index f314280ee49cf..20cd9f1263408 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -33,7 +33,29 @@ This input data: 0000000000000000000000000000000000000000000000000000000000000020 fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f -Would +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 BASE_LENGTH is 0, then it does not interpret _any_ data as the base, instead immediately interpreting the next 32 bytes as EXPONENT_LENGTH. + +This input data: + + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000020 + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd + +Would parse as a base of 0, an exponent of `2**256 - 1`, but then it would see an exponent length of `2**256 - 2`, notice that there are not enough bytes in the exponent to cover that length, and so it would throw. + +This input data: + + 0000000000000000000000000000000000000000000000000000000000000001 + 03 + 0000000000000000000000000000000000000000000000000000000000000002 + ffff + 0000000000000000000000000000000000000000000000000000000000000020 + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 00 + +Would parse as a base of 3, an exponent of 65535, and a modulus of `2**256 - 1`, but then there is an extra zero byte left over, which would cause it to throw. ### Rationale From 60fe6515378aca6c9d1acb4f84d2f0b2a180abe8 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Thu, 2 Feb 2017 21:17:56 -0500 Subject: [PATCH 06/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index 20cd9f1263408..c6dec83806667 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -6,17 +6,17 @@ At address 0x00......05, add a precompile that expects input in the following format: - + -Where every length is a 32-byte left-padded integer representing the number of bytes to be taken up by the next value. If the input cannot be fully parsed in this way (ie. attempting to parse it in this way either tries to consume more call data than is given or leaves some call data unused), then it throws an exception. Also, throws if `BASE >= MODULUS`. Otherwise, consumes `floor(length(MODULUS)**2 * length(EXPONENT) / 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. +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. For example, the input data: 0000000000000000000000000000000000000000000000000000000000000001 - 03 0000000000000000000000000000000000000000000000000000000000000020 - fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e 0000000000000000000000000000000000000000000000000000000000000020 + 03 + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f Represents the exponent `3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977)`. By Fermat's little theorem, this equals 1, so the result is: @@ -29,11 +29,11 @@ This input data: 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000020 - fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e 0000000000000000000000000000000000000000000000000000000000000020 + 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 BASE_LENGTH is 0, then it does not interpret _any_ data as the base, instead immediately interpreting the next 32 bytes as EXPONENT_LENGTH. +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. This input data: @@ -43,19 +43,30 @@ This input data: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd -Would parse as a base of 0, an exponent of `2**256 - 1`, but then it would see an exponent length of `2**256 - 2`, notice that there are not enough bytes in the exponent to cover that length, and so it would throw. +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. This input data: 0000000000000000000000000000000000000000000000000000000000000001 - 03 0000000000000000000000000000000000000000000000000000000000000002 - ffff 0000000000000000000000000000000000000000000000000000000000000020 - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 00 + 03 + ffff + 8000000000000000000000000000000000000000000000000000000000000000 + 07 + +Would parse as a base of 3, an exponent of 65535, and a modulus of `2**255`, and it would ignore the remaining 0x07 byte. -Would parse as a base of 3, an exponent of 65535, and a modulus of `2**256 - 1`, but then there is an extra zero byte left over, which would cause it to throw. +This input data: + + 0000000000000000000000000000000000000000000000000000000000000001 + 0000000000000000000000000000000000000000000000000000000000000002 + 0000000000000000000000000000000000000000000000000000000000000020 + 03 + ffff + 80 + +Would also parse as a base of 3, an exponent of 65535 and a modulus of `2**255`, as it attempts to grab 32 bytes for the modulus starting from 0x80, but then there is no further data so it right pads it with 31 zeroes. ### Rationale From 7138d542c43d1ff6305d79ea6ef19e6c6a61db15 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Wed, 24 May 2017 07:21:59 -0400 Subject: [PATCH 07/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index c6dec83806667..f3f2f8a53e6f9 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -1,6 +1,6 @@ ### Parameters -* `GQUADDIVISOR: 20` +* `GQUADDIVISOR: 100` ### Specification @@ -8,7 +8,13 @@ At address 0x00......05, add a precompile that expects input in the following fo -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. +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(ADJUSTED_EXPONENT_LENGTH, 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. + +`ADJUSTED_EXPONENT_LENGTH` is defined as follows. + +* If `length_of_EXPONENT <= 256`, and all bits in `EXPONENT` are 0, return 0 +* If `length_of_EXPONENT <= 256`, then return the index of the highest bit in `EXPONENT` (eg. 1 -> 0, 2 -> 1, 3 -> 1, 255 -> 7, 256 -> 8) +* If `length_of_EXPONENT > 256`, then return `8 * (length_of_EXPONENT - 32)` plus the index of the highest bit in the first 32 bytes of `EXPONENT` (eg. if `EXPONENT = \x00\x00\x01\x00.....\x00`, with one hundred bytes, then the result is 8 * (100 - 32) + 253 = 797) For example, the input data: @@ -23,7 +29,7 @@ Represents the exponent `3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977)`. By 0000000000000000000000000000000000000000000000000000000000000001 -Returned as 32 bytes because the modulus length was 32 bytes. The gas cost would be `32**2 * 32 / 20 = 1638` gas (note that this roughly equals the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `256**2 * 256 / 20 = 838860` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 3276 or 6553, respectively. +Returned as 32 bytes because the modulus length was 32 bytes. The `ADJUSTED_EXPONENT_LENGTH` would be 255, and the gas cost would be `32**2 * 255 / 100 = 2611` gas (note that this is ~five thirds of the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `512**2 * 4095 / 100 = 10734796` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 2621 or 41943, respectively. This input data: @@ -72,4 +78,6 @@ Would also parse as a base of 3, an exponent of 65535 and a modulus of `2**255`, This allows for efficient RSA verification inside of the EVM, as well as other forms of number theory-based cryptography. Note that adding precompiles for addition and subtraction is not required, as the in-EVM algorithm is efficient enough, and multiplication can be done through this precompile via `a * b = ((a + b)**2 - (a - b)**2) / 4`. +The bit-based exponent calculation is done specifically to fairly charge for the often-used exponents of 2 (for multiplication) and 3 and 65537 (for RSA verification). + From ed73b62030fc794ee9c3eb8dcc2808fd0751159e Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 29 May 2017 09:12:30 -0400 Subject: [PATCH 08/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index f3f2f8a53e6f9..0a654c8074ffb 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -13,8 +13,8 @@ Where every length is a 32-byte left-padded integer representing the number of b `ADJUSTED_EXPONENT_LENGTH` is defined as follows. * If `length_of_EXPONENT <= 256`, and all bits in `EXPONENT` are 0, return 0 -* If `length_of_EXPONENT <= 256`, then return the index of the highest bit in `EXPONENT` (eg. 1 -> 0, 2 -> 1, 3 -> 1, 255 -> 7, 256 -> 8) -* If `length_of_EXPONENT > 256`, then return `8 * (length_of_EXPONENT - 32)` plus the index of the highest bit in the first 32 bytes of `EXPONENT` (eg. if `EXPONENT = \x00\x00\x01\x00.....\x00`, with one hundred bytes, then the result is 8 * (100 - 32) + 253 = 797) +* If `length_of_EXPONENT <= 256`, then return the index of the highest bit in `EXPONENT` (eg. 1 -> 0, 2 -> 1, 3 -> 1, 255 -> 7, 256 -> 8). The "index of the highest bit in 0" is assumed to +* If `length_of_EXPONENT > 256`, then return `8 * (length_of_EXPONENT - 32)` plus the index of the highest bit in the first 32 bytes of `EXPONENT` (eg. if `EXPONENT = \x00\x00\x01\x00.....\x00`, with one hundred bytes, then the result is 8 * (100 - 32) + 253 = 797). If all of the first 32 bytes of `EXPONENT` are zero, return exactly `8 * (length_of_EXPONENT - 32)`. For example, the input data: From deee02aa7e7a68f13bb3c3405f6c576be15a4e34 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Fri, 2 Jun 2017 17:15:15 +0300 Subject: [PATCH 09/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index 0a654c8074ffb..700b35979ae13 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -12,9 +12,9 @@ Where every length is a 32-byte left-padded integer representing the number of b `ADJUSTED_EXPONENT_LENGTH` is defined as follows. -* If `length_of_EXPONENT <= 256`, and all bits in `EXPONENT` are 0, return 0 -* If `length_of_EXPONENT <= 256`, then return the index of the highest bit in `EXPONENT` (eg. 1 -> 0, 2 -> 1, 3 -> 1, 255 -> 7, 256 -> 8). The "index of the highest bit in 0" is assumed to -* If `length_of_EXPONENT > 256`, then return `8 * (length_of_EXPONENT - 32)` plus the index of the highest bit in the first 32 bytes of `EXPONENT` (eg. if `EXPONENT = \x00\x00\x01\x00.....\x00`, with one hundred bytes, then the result is 8 * (100 - 32) + 253 = 797). If all of the first 32 bytes of `EXPONENT` are zero, return exactly `8 * (length_of_EXPONENT - 32)`. +* If `length_of_EXPONENT <= 32`, and all bits in `EXPONENT` are 0, return 0 +* If `length_of_EXPONENT <= 32`, then return the index of the highest bit in `EXPONENT` (eg. 1 -> 0, 2 -> 1, 3 -> 1, 255 -> 7, 256 -> 8). The "index of the highest bit in 0" is assumed to +* If `length_of_EXPONENT > 32`, then return `8 * (length_of_EXPONENT - 32)` plus the index of the highest bit in the first 32 bytes of `EXPONENT` (eg. if `EXPONENT = \x00\x00\x01\x00.....\x00`, with one hundred bytes, then the result is 8 * (100 - 32) + 253 = 797). If all of the first 32 bytes of `EXPONENT` are zero, return exactly `8 * (length_of_EXPONENT - 32)`. For example, the input data: From dafe13c071463c54830e1ae06fb80f6d87721e89 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Fri, 2 Jun 2017 17:20:16 +0300 Subject: [PATCH 10/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index 700b35979ae13..44bc31df68e32 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -13,7 +13,7 @@ Where every length is a 32-byte left-padded integer representing the number of b `ADJUSTED_EXPONENT_LENGTH` is defined as follows. * If `length_of_EXPONENT <= 32`, and all bits in `EXPONENT` are 0, return 0 -* If `length_of_EXPONENT <= 32`, then return the index of the highest bit in `EXPONENT` (eg. 1 -> 0, 2 -> 1, 3 -> 1, 255 -> 7, 256 -> 8). The "index of the highest bit in 0" is assumed to +* If `length_of_EXPONENT <= 32`, then return the index of the highest bit in `EXPONENT` (eg. 1 -> 0, 2 -> 1, 3 -> 1, 255 -> 7, 256 -> 8). * If `length_of_EXPONENT > 32`, then return `8 * (length_of_EXPONENT - 32)` plus the index of the highest bit in the first 32 bytes of `EXPONENT` (eg. if `EXPONENT = \x00\x00\x01\x00.....\x00`, with one hundred bytes, then the result is 8 * (100 - 32) + 253 = 797). If all of the first 32 bytes of `EXPONENT` are zero, return exactly `8 * (length_of_EXPONENT - 32)`. For example, the input data: From 4d4d8fb75eedeacc6456b804d9fb58c1778f1c76 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Sat, 22 Jul 2017 14:19:39 -0400 Subject: [PATCH 11/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index 44bc31df68e32..ec3c31e99269d 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -8,7 +8,7 @@ At address 0x00......05, add a precompile that expects input in the following fo -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(ADJUSTED_EXPONENT_LENGTH, 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. +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(mult_complexity(max(length_of_MODULUS, length_of_BASE)) * max(ADJUSTED_EXPONENT_LENGTH, 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. `ADJUSTED_EXPONENT_LENGTH` is defined as follows. @@ -16,6 +16,15 @@ Where every length is a 32-byte left-padded integer representing the number of b * If `length_of_EXPONENT <= 32`, then return the index of the highest bit in `EXPONENT` (eg. 1 -> 0, 2 -> 1, 3 -> 1, 255 -> 7, 256 -> 8). * If `length_of_EXPONENT > 32`, then return `8 * (length_of_EXPONENT - 32)` plus the index of the highest bit in the first 32 bytes of `EXPONENT` (eg. if `EXPONENT = \x00\x00\x01\x00.....\x00`, with one hundred bytes, then the result is 8 * (100 - 32) + 253 = 797). If all of the first 32 bytes of `EXPONENT` are zero, return exactly `8 * (length_of_EXPONENT - 32)`. +`mult_complexity` is a function intended to approximate the difficulty of Karatsuba multiplication (used in all major bigint libraries) and is defined as follows. + +``` +def mult_complexity(x): + if x <= 64: return x ** 2 + elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 + else: return x ** 2 // 16 + 480 * x - 199680 +``` + For example, the input data: 0000000000000000000000000000000000000000000000000000000000000001 From 85f690772cac151469024f9e457e698ddecd8992 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 14 Aug 2017 22:07:47 -0500 Subject: [PATCH 12/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index ec3c31e99269d..0d6b9d9468a4d 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -38,7 +38,7 @@ Represents the exponent `3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977)`. By 0000000000000000000000000000000000000000000000000000000000000001 -Returned as 32 bytes because the modulus length was 32 bytes. The `ADJUSTED_EXPONENT_LENGTH` would be 255, and the gas cost would be `32**2 * 255 / 100 = 2611` gas (note that this is ~five thirds of the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `512**2 * 4095 / 100 = 10734796` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 2621 or 41943, respectively. +Returned as 32 bytes because the modulus length was 32 bytes. The `ADJUSTED_EXPONENT_LENGTH` would be 255, and the gas cost would be `mult_complexity(32) * 255 / 100 = 2611` gas (note that this is ~five thirds of the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `mult_complexity(512) * 4095 / 100 = 4570675` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 1116 or 17858, respectively. This input data: From 30055644acd6966806371f24bc9fd9ebd3b56a57 Mon Sep 17 00:00:00 2001 From: vbuterin Date: Mon, 11 Sep 2017 05:50:04 -0400 Subject: [PATCH 13/16] Update bigint_modexp.md --- EIPS/bigint_modexp.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index 0d6b9d9468a4d..3cec75664d21f 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -1,6 +1,6 @@ ### Parameters -* `GQUADDIVISOR: 100` +* `GQUADDIVISOR: 20` ### Specification @@ -38,7 +38,7 @@ Represents the exponent `3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977)`. By 0000000000000000000000000000000000000000000000000000000000000001 -Returned as 32 bytes because the modulus length was 32 bytes. The `ADJUSTED_EXPONENT_LENGTH` would be 255, and the gas cost would be `mult_complexity(32) * 255 / 100 = 2611` gas (note that this is ~five thirds of the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `mult_complexity(512) * 4095 / 100 = 4570675` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 1116 or 17858, respectively. +Returned as 32 bytes because the modulus length was 32 bytes. The `ADJUSTED_EXPONENT_LENGTH` would be 255, and the gas cost would be `mult_complexity(32) * 255 / 20 = 13056` gas (note that this is ~8 times the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `mult_complexity(512) * 4095 / 100 = 22853376` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 5580 or 89292, respectively. This input data: From ca82cd9e4203095889a99037ab0f550a968ba849 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 30 Nov 2017 16:13:13 +0100 Subject: [PATCH 14/16] Fixing an example after the specification change https://github.com/ethereum/EIPs/pull/198/files#r106236783 --- EIPS/bigint_modexp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index 3cec75664d21f..fe8656a6f6e2b 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -48,7 +48,7 @@ This input data: 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. +Would be parsed as a base of 0, exponent of `2**256 - 2**32 - 978` and modulus of `2**256 - 2**32 - 977`, 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 EXPONENT. This input data: From f4179980751f7a3434928181c8950184ab357cf5 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 1 Dec 2017 12:51:57 +0100 Subject: [PATCH 15/16] Fix one example after a format change https://github.com/ethereum/EIPs/pull/198/files#r109660742 --- EIPS/bigint_modexp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/bigint_modexp.md b/EIPS/bigint_modexp.md index fe8656a6f6e2b..7fa1bed080ddd 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/bigint_modexp.md @@ -58,7 +58,7 @@ This input data: 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. +Would parse a base length of 0, a exponent length of 32, and an exponent length of `2**256 - 1`, where the base is empty, the exponent is `2**256 - 2` and the modulus 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. This input data: From 9504333fc9b8b49731b4d874c82de7d5ce9fb4a7 Mon Sep 17 00:00:00 2001 From: Nick Johnson Date: Sun, 25 Mar 2018 17:56:07 +0100 Subject: [PATCH 16/16] Rename bigint_modexp.md to eip-198.md, add new prologue and copyright notice. --- EIPS/{bigint_modexp.md => eip-198.md} | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) rename EIPS/{bigint_modexp.md => eip-198.md} (95%) diff --git a/EIPS/bigint_modexp.md b/EIPS/eip-198.md similarity index 95% rename from EIPS/bigint_modexp.md rename to EIPS/eip-198.md index 7fa1bed080ddd..c0c053454ff14 100644 --- a/EIPS/bigint_modexp.md +++ b/EIPS/eip-198.md @@ -1,8 +1,18 @@ -### Parameters +--- +eip: 198 +title: Big integer modular exponentiation +author: Vitalik Buterin +status: Final +type: Standards Track +category: Core +created: 2017-01-30 +--- + +# Parameters * `GQUADDIVISOR: 20` -### Specification +# Specification At address 0x00......05, add a precompile that expects input in the following format: @@ -83,10 +93,12 @@ This input data: Would also parse as a base of 3, an exponent of 65535 and a modulus of `2**255`, as it attempts to grab 32 bytes for the modulus starting from 0x80, but then there is no further data so it right pads it with 31 zeroes. -### Rationale +# Rationale This allows for efficient RSA verification inside of the EVM, as well as other forms of number theory-based cryptography. Note that adding precompiles for addition and subtraction is not required, as the in-EVM algorithm is efficient enough, and multiplication can be done through this precompile via `a * b = ((a + b)**2 - (a - b)**2) / 4`. The bit-based exponent calculation is done specifically to fairly charge for the often-used exponents of 2 (for multiplication) and 3 and 65537 (for RSA verification). - +# Copyright + +Copyright and related rights waived via CC0.