Skip to content

Commit

Permalink
implement the proposed gas changes for bls / eip-2537:
Browse files Browse the repository at this point in the history
https://github.com/ethereum/EIPs/pull/9097/files
https://github.com/ethereum/EIPs/pull/9098/files
https://github.com/ethereum/EIPs/pull/9116/files

Signed-off-by: garyschulte <[email protected]>

adjust unit test gas costs, fix offset-by-one bug in the discount table

Signed-off-by: garyschulte <[email protected]>

implement bump in gas cost for bls map functions according to ethereum/EIPs@92c94cf

Signed-off-by: garyschulte <[email protected]>

using Pawel's suggested discount table from ethereum/EIPs#9116 (comment)

Signed-off-by: garyschulte <[email protected]>

use bls pairing costs from https://github.com/ethereum/EIPs/pull/9098/files

Signed-off-by: garyschulte <[email protected]>

remove MUL per ethereum/EIPs#8945

Signed-off-by: garyschulte <[email protected]>

fix g1 msm max discount case, add g2 msm max discount case

Signed-off-by: garyschulte <[email protected]>

remove bls mul ops from benchmark subcommand

Signed-off-by: garyschulte <[email protected]>

use besu-native 1.1.1

Signed-off-by: garyschulte <[email protected]>
  • Loading branch information
garyschulte authored and siladu committed Dec 20, 2024
1 parent c5e564c commit 9480fe4
Show file tree
Hide file tree
Showing 26 changed files with 818 additions and 930 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void readGenesisFromObjectNode() {
final var configNode = mapper.createObjectNode();
configNode.put("londonBlock", 1);
final var allocNode = mapper.createObjectNode();
allocNode.put(Address.BLS12_G2MUL.toUnprefixedHexString(), generateAllocation(Wei.ONE));
allocNode.put(Address.BLS12_G2MULTIEXP.toUnprefixedHexString(), generateAllocation(Wei.ONE));
final var rootNode = mapper.createObjectNode();
rootNode.put("chainId", 12);
rootNode.put(CONFIG_FIELD, configNode);
Expand All @@ -52,15 +52,16 @@ public void readGenesisFromObjectNode() {
assertThat(genesisReader.getRoot().has(ALLOCATION_FIELD)).isFalse();
assertThat(genesisReader.getConfig().get("londonblock").asInt()).isEqualTo(1);
assertThat(genesisReader.streamAllocations())
.containsExactly(new GenesisAccount(Address.BLS12_G2MUL, 0, Wei.ONE, null, Map.of(), null));
.containsExactly(
new GenesisAccount(Address.BLS12_G2MULTIEXP, 0, Wei.ONE, null, Map.of(), null));
}

@Test
public void readGenesisFromObjectDoesNotModifyObjectNodeArg() {
final var configNode = mapper.createObjectNode();
configNode.put("londonBlock", 1);
final var allocNode = mapper.createObjectNode();
allocNode.put(Address.BLS12_G2MUL.toUnprefixedHexString(), generateAllocation(Wei.ONE));
allocNode.put(Address.BLS12_G2MULTIEXP.toUnprefixedHexString(), generateAllocation(Wei.ONE));
final var rootNode = mapper.createObjectNode();
rootNode.put("chainId", 12);
rootNode.put(CONFIG_FIELD, configNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,29 +72,23 @@ public class Address extends DelegatingBytes {
/** The constant BLS12_G1ADD. */
public static final Address BLS12_G1ADD = Address.precompiled(0xB);

/** The constant BLS12_G1MUL. */
public static final Address BLS12_G1MUL = Address.precompiled(0xC);

/** The constant BLS12_G1MULTIEXP. */
public static final Address BLS12_G1MULTIEXP = Address.precompiled(0xD);
public static final Address BLS12_G1MULTIEXP = Address.precompiled(0xC);

/** The constant BLS12_G2ADD. */
public static final Address BLS12_G2ADD = Address.precompiled(0xE);

/** The constant BLS12_G2MUL. */
public static final Address BLS12_G2MUL = Address.precompiled(0xF);
public static final Address BLS12_G2ADD = Address.precompiled(0xD);

/** The constant BLS12_G2MULTIEXP. */
public static final Address BLS12_G2MULTIEXP = Address.precompiled(0x10);
public static final Address BLS12_G2MULTIEXP = Address.precompiled(0xE);

/** The constant BLS12_PAIRING. */
public static final Address BLS12_PAIRING = Address.precompiled(0x11);
public static final Address BLS12_PAIRING = Address.precompiled(0xF);

/** The constant BLS12_MAP_FP_TO_G1. */
public static final Address BLS12_MAP_FP_TO_G1 = Address.precompiled(0x12);
public static final Address BLS12_MAP_FP_TO_G1 = Address.precompiled(0x10);

/** The constant BLS12_MAP_FP2_TO_G2. */
public static final Address BLS12_MAP_FP2_TO_G2 = Address.precompiled(0x13);
public static final Address BLS12_MAP_FP2_TO_G2 = Address.precompiled(0x11);

/** The constant ZERO. */
public static final Address ZERO = Address.fromHexString("0x0");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@
import org.hyperledger.besu.evm.EvmSpecVersion;
import org.hyperledger.besu.evm.precompile.AbstractBLS12PrecompiledContract;
import org.hyperledger.besu.evm.precompile.BLS12G1AddPrecompiledContract;
import org.hyperledger.besu.evm.precompile.BLS12G1MulPrecompiledContract;
import org.hyperledger.besu.evm.precompile.BLS12G1MultiExpPrecompiledContract;
import org.hyperledger.besu.evm.precompile.BLS12G2AddPrecompiledContract;
import org.hyperledger.besu.evm.precompile.BLS12G2MulPrecompiledContract;
import org.hyperledger.besu.evm.precompile.BLS12G2MultiExpPrecompiledContract;
import org.hyperledger.besu.evm.precompile.BLS12MapFp2ToG2PrecompiledContract;
import org.hyperledger.besu.evm.precompile.BLS12MapFpToG1PrecompiledContract;
Expand Down Expand Up @@ -166,11 +164,9 @@ public void runBenchmark(
}

benchmarkG1Add(output);
benchmarkG1Mul(output);
benchmarkG1MultiExp32Pairs(output);
benchmarkMapFpToG1(output);
benchmarkG2Add(output);
benchmarkG2Mul(output);
benchmarkG2MultiExp32Pairs(output);
benchmarkMapFp2ToG2(output);
benchmarkBlsPairing(output);
Expand Down Expand Up @@ -198,28 +194,6 @@ private void benchmarkG1Add(final PrintStream output) {
gasCost, execTime * 1_000_000, gasCost / execTime / 1_000_000);
}

private void benchmarkG1Mul(final PrintStream output) {
final Map<String, Bytes> testCases = new LinkedHashMap<>();
for (int i = 0; i < g1PointPairs.length; i++) {
testCases.put("G1 Mul " + i, Bytes.fromHexString(g1PointPairs[i] + scalars[i]));
}

BLS12G1MulPrecompiledContract g1addContract = new BLS12G1MulPrecompiledContract();
warmup = MATH_WARMUP / testCases.size();
iterations = MATH_ITERATIONS / testCases.size();
double execTime = Double.MIN_VALUE; // a way to dodge divide by zero
long gasCost = 0;
for (final Map.Entry<String, Bytes> testCase : testCases.entrySet()) {
execTime += runPrecompileBenchmark(testCase.getValue(), g1addContract);
gasCost += g1addContract.gasRequirement(testCase.getValue());
}
execTime /= testCases.size();
gasCost /= testCases.size();
output.printf(
"Bls12 G1 Mul %,6d avg gas @%,7.1f µs /%,8.1f MGps%n",
gasCost, execTime * 1_000_000, gasCost / execTime / 1_000_000);
}

private void benchmarkG1MultiExp32Pairs(final PrintStream output) {
final Map<String, Bytes> testCases = new LinkedHashMap<>();

Expand Down Expand Up @@ -290,28 +264,6 @@ private void benchmarkG2Add(final PrintStream output) {
gasCost, execTime * 1_000_000, gasCost / execTime / 1_000_000);
}

private void benchmarkG2Mul(final PrintStream output) {
final Map<String, Bytes> testCases = new LinkedHashMap<>();
for (int i = 0; i < g2PointPairs.length; i++) {
testCases.put("G2 Mul " + i, Bytes.fromHexString(g2PointPairs[i] + scalars[i]));
}

BLS12G2MulPrecompiledContract g1addContract = new BLS12G2MulPrecompiledContract();
warmup = MATH_WARMUP / testCases.size();
iterations = MATH_ITERATIONS / testCases.size();
double execTime = Double.MIN_VALUE; // a way to dodge divide by zero
long gasCost = 0;
for (final Map.Entry<String, Bytes> testCase : testCases.entrySet()) {
execTime += runPrecompileBenchmark(testCase.getValue(), g1addContract);
gasCost += g1addContract.gasRequirement(testCase.getValue());
}
execTime /= testCases.size();
gasCost /= testCases.size();
output.printf(
"Bls12 G2 Mul %,6d avg gas @%,7.1f µs /%,8.1f MGps%n",
gasCost, execTime * 1_000_000, gasCost / execTime / 1_000_000);
}

private void benchmarkG2MultiExp32Pairs(final PrintStream output) {
final Map<String, Bytes> testCases = new LinkedHashMap<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,40 @@ public abstract class AbstractBLS12PrecompiledContract implements PrecompiledCon

private static final Logger LOG = LoggerFactory.getLogger(AbstractBLS12PrecompiledContract.class);

static {
// set parallel 1 for testing. Remove this for prod code (or set a rational limit)
// LibGnarkEIP2537.setDegreeOfMSMParallelism(1);
}

/** The Discount table. */
static final int[] DISCOUNT_TABLE =
static final int[] G1_DISCOUNT_TABLE =
new int[] {
-1, 1000, 949, 848, 797, 764, 750, 738, 728, 719, 712, 705, 698, 692, 687, 682, 677, 673,
669, 665, 661, 658, 654, 651, 648, 645, 642, 640, 637, 635, 632, 630, 627, 625, 623, 621,
619, 617, 615, 613, 611, 609, 608, 606, 604, 603, 601, 599, 598, 596, 595, 593, 592, 591,
589, 588, 586, 585, 584, 582, 581, 580, 579, 577, 576, 575, 574, 573, 572, 570, 569, 568,
567, 566, 565, 564, 563, 562, 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, 551, 550,
549, 548, 547, 547, 546, 545, 544, 543, 542, 541, 540, 540, 539, 538, 537, 536, 536, 535,
534, 533, 532, 532, 531, 530, 529, 528, 528, 527, 526, 525, 525, 524, 523, 522, 522, 521,
520, 520, 519
};

static final int[] G2_DISCOUNT_TABLE =
new int[] {
-1, 1_200, 888, 764, 641, 594, 547, 500, 453, 438, 423, 408, 394, 379, 364, 349,
334, 330, 326, 322, 318, 314, 310, 306, 302, 298, 294, 289, 285, 281, 277, 273,
269, 268, 266, 265, 263, 262, 260, 259, 257, 256, 254, 253, 251, 250, 248, 247,
245, 244, 242, 241, 239, 238, 236, 235, 233, 232, 231, 229, 228, 226, 225, 223,
222, 221, 220, 219, 219, 218, 217, 216, 216, 215, 214, 213, 213, 212, 211, 211,
210, 209, 208, 208, 207, 206, 205, 205, 204, 203, 202, 202, 201, 200, 199, 199,
198, 197, 196, 196, 195, 194, 193, 193, 192, 191, 191, 190, 189, 188, 188, 187,
186, 185, 185, 184, 183, 182, 182, 181, 180, 179, 179, 178, 177, 176, 176, 175,
174
-1, 1000, 1000, 923, 884, 855, 832, 812, 796, 782, 770, 759, 749, 740, 732, 724, 717, 711,
704, 699, 693, 688, 683, 679, 674, 670, 666, 663, 659, 655, 652, 649, 646, 643, 640, 637,
634, 632, 629, 627, 624, 622, 620, 618, 615, 613, 611, 609, 607, 606, 604, 602, 600, 598,
597, 595, 593, 592, 590, 589, 587, 586, 584, 583, 582, 580, 579, 578, 576, 575, 574, 573,
571, 570, 569, 568, 567, 566, 565, 563, 562, 561, 560, 559, 558, 557, 556, 555, 554, 553,
552, 552, 551, 550, 549, 548, 547, 546, 545, 545, 544, 543, 542, 541, 541, 540, 539, 538,
537, 537, 536, 535, 535, 534, 533, 532, 532, 531, 530, 530, 529, 528, 528, 527, 526, 526,
525, 524, 524
};

/** The Max discount. */
static final int MAX_DISCOUNT = 174;
static final int G1_MAX_DISCOUNT = 519;

static final int G2_MAX_DISCOUNT = 524;

private final String name;
private final byte operationId;
Expand Down Expand Up @@ -121,21 +139,40 @@ public PrecompileContractResult computePrecompile(
}

/**
* Gets discount.
* Gets G1 MSM discount.
*
* @param k the k
* @return the discount
*/
protected int getG1Discount(final int k) {
// `k * multiplication_cost * discount / multiplier` where `multiplier = 1000`
// multiplication_cost and multiplier are folded into one constant as a long and placed first to
// prevent int32 overflow
// there was a table prepared for discount in case of k <= 128 points in the multiexponentiation
// with a discount cup max_discount for k > 128.

if (k >= G1_DISCOUNT_TABLE.length) {
return G1_MAX_DISCOUNT;
}
return G1_DISCOUNT_TABLE[k];
}

/**
* Gets G2 MSM discount.
*
* @param k the k
* @return the discount
*/
protected int getDiscount(final int k) {
protected int getG2Discount(final int k) {
// `k * multiplication_cost * discount / multiplier` where `multiplier = 1000`
// multiplication_cost and multiplier are folded into one constant as a long and placed first to
// prevent int32 overflow
// there was a table prepared for discount in case of k <= 128 points in the multiexponentiation
// with a discount cup max_discount for k > 128.

if (k >= DISCOUNT_TABLE.length) {
return MAX_DISCOUNT;
if (k >= G2_DISCOUNT_TABLE.length) {
return G2_MAX_DISCOUNT;
}
return DISCOUNT_TABLE[k];
return G2_DISCOUNT_TABLE[k];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ public BLS12G1AddPrecompiledContract() {

@Override
public long gasRequirement(final Bytes input) {
return 500L;
return 375L;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ public BLS12G1MultiExpPrecompiledContract() {
@Override
public long gasRequirement(final Bytes input) {
final int k = input.size() / PARAMETER_LENGTH;
return 12L * k * getDiscount(k);
return 12L * k * getG1Discount(k);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ public BLS12G2AddPrecompiledContract() {

@Override
public long gasRequirement(final Bytes input) {
return 800L;
return 600L;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ public BLS12G2MultiExpPrecompiledContract() {
@Override
public long gasRequirement(final Bytes input) {
final int k = input.size() / PARAMETER_LENGTH;
return 45L * k * getDiscount(k);
return 22_500L * k * getG2Discount(k) / 1000L;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public BLS12MapFp2ToG2PrecompiledContract() {

@Override
public long gasRequirement(final Bytes input) {
return 75_000L;
return 23_800L;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public BLS12MapFpToG1PrecompiledContract() {

@Override
public long gasRequirement(final Bytes input) {
return 5_500L;
return 5_500;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ public BLS12PairingPrecompiledContract() {
@Override
public long gasRequirement(final Bytes input) {
final int k = input.size() / PARAMETER_LENGTH;
return 43_000L * k + 65_000L;
return 32_600L * k + 37_700L;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,8 @@ static void populateForPrague(

// EIP-2537 - BLS12-381 curve operations
registry.put(Address.BLS12_G1ADD, new BLS12G1AddPrecompiledContract());
registry.put(Address.BLS12_G1MUL, new BLS12G1MulPrecompiledContract());
registry.put(Address.BLS12_G1MULTIEXP, new BLS12G1MultiExpPrecompiledContract());
registry.put(Address.BLS12_G2ADD, new BLS12G2AddPrecompiledContract());
registry.put(Address.BLS12_G2MUL, new BLS12G2MulPrecompiledContract());
registry.put(Address.BLS12_G2MULTIEXP, new BLS12G2MultiExpPrecompiledContract());
registry.put(Address.BLS12_PAIRING, new BLS12PairingPrecompiledContract());
registry.put(Address.BLS12_MAP_FP_TO_G1, new BLS12MapFpToG1PrecompiledContract());
Expand Down
Loading

0 comments on commit 9480fe4

Please sign in to comment.