mirror of
https://github.com/vacp2p/linea-monorepo.git
synced 2026-01-09 04:08:01 -05:00
Feat: integrate ZkCounter into the Sequencer (#1101)
* Support limitless ZkCounter Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> * Fixes Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> * Extend ATs to cover the ZkCounter Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> --------- Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
This commit is contained in:
@@ -21,7 +21,6 @@ import linea.plugin.acc.test.tests.web3j.generated.EcAdd;
|
||||
import linea.plugin.acc.test.tests.web3j.generated.EcMul;
|
||||
import linea.plugin.acc.test.tests.web3j.generated.EcPairing;
|
||||
import linea.plugin.acc.test.tests.web3j.generated.EcRecover;
|
||||
import net.consensys.linea.config.LineaTracerConfiguration;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
@@ -138,8 +137,7 @@ public class EcDataLimitsTest extends LineaPluginTestBase {
|
||||
|
||||
private static Stream<Arguments> ecPairingLimitsTestSource() {
|
||||
Map<String, Integer> moduleLimits =
|
||||
ModuleLineCountValidator.createLimitModules(
|
||||
new LineaTracerConfiguration(getResourcePath("/moduleLimits.toml")));
|
||||
ModuleLineCountValidator.createLimitModules(getResourcePath("/moduleLimits.toml"));
|
||||
final int PRECOMPILE_ECPAIRING_FINAL_EXPONENTIATIONS =
|
||||
moduleLimits.get("PRECOMPILE_ECPAIRING_FINAL_EXPONENTIATIONS");
|
||||
final int PRECOMPILE_ECPAIRING_MILLER_LOOPS =
|
||||
@@ -291,8 +289,7 @@ public class EcDataLimitsTest extends LineaPluginTestBase {
|
||||
@Test
|
||||
public void ecAddLimitTest() throws Exception {
|
||||
Map<String, Integer> moduleLimits =
|
||||
ModuleLineCountValidator.createLimitModules(
|
||||
new LineaTracerConfiguration(getResourcePath("/moduleLimits.toml")));
|
||||
ModuleLineCountValidator.createLimitModules(getResourcePath("/moduleLimits.toml"));
|
||||
final int PRECOMPILE_ECADD_EFFECTIVE_CALLS =
|
||||
moduleLimits.get("PRECOMPILE_ECADD_EFFECTIVE_CALLS");
|
||||
|
||||
@@ -384,8 +381,7 @@ public class EcDataLimitsTest extends LineaPluginTestBase {
|
||||
@Test
|
||||
public void ecMulLimitTest() throws Exception {
|
||||
Map<String, Integer> moduleLimits =
|
||||
ModuleLineCountValidator.createLimitModules(
|
||||
new LineaTracerConfiguration(getResourcePath("/moduleLimits.toml")));
|
||||
ModuleLineCountValidator.createLimitModules(getResourcePath("/moduleLimits.toml"));
|
||||
final int PRECOMPILE_ECMUL_EFFECTIVE_CALLS =
|
||||
moduleLimits.get("PRECOMPILE_ECMUL_EFFECTIVE_CALLS");
|
||||
|
||||
@@ -473,8 +469,7 @@ public class EcDataLimitsTest extends LineaPluginTestBase {
|
||||
@Test
|
||||
public void ecRecoverLimitTest() throws Exception {
|
||||
Map<String, Integer> moduleLimits =
|
||||
ModuleLineCountValidator.createLimitModules(
|
||||
new LineaTracerConfiguration(getResourcePath("/moduleLimits.toml")));
|
||||
ModuleLineCountValidator.createLimitModules(getResourcePath("/moduleLimits.toml"));
|
||||
final int PRECOMPILE_ECRECOVER_EFFECTIVE_CALLS =
|
||||
moduleLimits.get("PRECOMPILE_ECRECOVER_EFFECTIVE_CALLS");
|
||||
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright Consensys Software Inc.
|
||||
*
|
||||
* This file is dual-licensed under either the MIT license or Apache License 2.0.
|
||||
* See the LICENSE-MIT and LICENSE-APACHE files in the repository root for details.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*/
|
||||
package linea.plugin.acc.test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import linea.plugin.acc.test.tests.web3j.generated.ExcludedPrecompiles;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.web3j.abi.datatypes.generated.Bytes8;
|
||||
import org.web3j.crypto.Credentials;
|
||||
import org.web3j.crypto.Hash;
|
||||
import org.web3j.crypto.RawTransaction;
|
||||
import org.web3j.crypto.TransactionEncoder;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.methods.response.EthSendTransaction;
|
||||
import org.web3j.tx.gas.DefaultGasProvider;
|
||||
import org.web3j.utils.Numeric;
|
||||
|
||||
public class ExcludedPrecompilesLimitlessTest extends LineaPluginTestBase {
|
||||
private static final BigInteger GAS_LIMIT = DefaultGasProvider.GAS_LIMIT;
|
||||
private static final BigInteger GAS_PRICE = DefaultGasProvider.GAS_PRICE;
|
||||
|
||||
@Override
|
||||
public List<String> getTestCliOptions() {
|
||||
return new TestCommandLineOptionsBuilder()
|
||||
// disable line count validation to accept excluded precompile txs in the txpool
|
||||
.set("--plugin-linea-tx-pool-simulation-check-api-enabled=", "false")
|
||||
// set the module limits file
|
||||
.set(
|
||||
"--plugin-linea-module-limit-file-path=",
|
||||
getResourcePath("/moduleLimitsLimitless.toml"))
|
||||
// enabled the ZkCounter
|
||||
.set("--plugin-linea-limitless-enabled=", "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionsWithExcludedPrecompilesAreNotAccepted() throws Exception {
|
||||
final ExcludedPrecompiles excludedPrecompiles = deployExcludedPrecompiles();
|
||||
final Web3j web3j = minerNode.nodeRequests().eth();
|
||||
final String contractAddress = excludedPrecompiles.getContractAddress();
|
||||
|
||||
// fund a new account
|
||||
final var recipient = accounts.createAccount("recipient");
|
||||
final var txHashFundRecipient =
|
||||
accountTransactions
|
||||
.createTransfer(accounts.getPrimaryBenefactor(), recipient, 10, BigInteger.valueOf(1))
|
||||
.execute(minerNode.nodeRequests());
|
||||
minerNode.verify(eth.expectSuccessfulTransactionReceipt(txHashFundRecipient.toHexString()));
|
||||
|
||||
record InvalidCall(
|
||||
String senderPrivateKey, int nonce, String encodedContractCall, String expectedTraceLog) {}
|
||||
|
||||
final InvalidCall[] invalidCalls = {
|
||||
new InvalidCall(
|
||||
Accounts.GENESIS_ACCOUNT_ONE_PRIVATE_KEY,
|
||||
2,
|
||||
excludedPrecompiles
|
||||
.callRIPEMD160("I am not allowed here".getBytes(StandardCharsets.UTF_8))
|
||||
.encodeFunctionCall(),
|
||||
"Tx 0xe4648fd59d4289e59b112bf60931336440d306c85c2aac5a8b0c64ab35bc55b7 line count per module: [RIP=2147483647/2147483647/1,BLAKE=0/0/1,BLOCK_L1_SIZE=235/365/1000000,MODEXP=0/0/1,BLOCK_L2_L1_LOGS=0/0/16"),
|
||||
new InvalidCall(
|
||||
Accounts.GENESIS_ACCOUNT_TWO_PRIVATE_KEY,
|
||||
0,
|
||||
encodedCallBlake2F(excludedPrecompiles),
|
||||
"Tx 0x9f457b1b5244b03c54234f7f9e8225d4253135dd3c99a46dc527d115e7ea5dac line count per module: [RIP=0/0/1,BLAKE=2147483647/2147483647/1,BLOCK_L1_SIZE=462/592/1000000,MODEXP=0/0/1,BLOCK_L2_L1_LOGS=0/0/16]")
|
||||
};
|
||||
|
||||
final var invalidTxHashes =
|
||||
Arrays.stream(invalidCalls)
|
||||
.map(
|
||||
invalidCall -> {
|
||||
// this tx must not be accepted but not mined
|
||||
final RawTransaction txInvalid =
|
||||
RawTransaction.createTransaction(
|
||||
CHAIN_ID,
|
||||
BigInteger.valueOf(invalidCall.nonce),
|
||||
GAS_LIMIT.divide(BigInteger.TEN),
|
||||
contractAddress,
|
||||
BigInteger.ZERO,
|
||||
invalidCall.encodedContractCall,
|
||||
GAS_PRICE,
|
||||
GAS_PRICE);
|
||||
|
||||
final byte[] signedTxInvalid =
|
||||
TransactionEncoder.signMessage(
|
||||
txInvalid, Credentials.create(invalidCall.senderPrivateKey));
|
||||
|
||||
final EthSendTransaction signedTxInvalidResp;
|
||||
try {
|
||||
signedTxInvalidResp =
|
||||
web3j.ethSendRawTransaction(Numeric.toHexString(signedTxInvalid)).send();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
assertThat(signedTxInvalidResp.hasError()).isFalse();
|
||||
return signedTxInvalidResp.getTransactionHash();
|
||||
})
|
||||
.toList();
|
||||
|
||||
assertThat(getTxPoolContent()).hasSize(invalidTxHashes.size());
|
||||
|
||||
// transfer used as sentry to ensure a new block is mined without the invalid txs
|
||||
final var transferTxHash1 =
|
||||
accountTransactions
|
||||
.createTransfer(recipient, accounts.getSecondaryBenefactor(), 1)
|
||||
.execute(minerNode.nodeRequests());
|
||||
|
||||
// first sentry is mined and no tx of the bundle is mined
|
||||
minerNode.verify(eth.expectSuccessfulTransactionReceipt(transferTxHash1.toHexString()));
|
||||
Arrays.stream(invalidCalls)
|
||||
.forEach(
|
||||
invalidCall ->
|
||||
minerNode.verify(
|
||||
eth.expectNoTransactionReceipt(Hash.sha3(invalidCall.encodedContractCall))));
|
||||
|
||||
final String log = getLog();
|
||||
// verify trace log contains the exclusion cause
|
||||
Arrays.stream(invalidCalls)
|
||||
.forEach(invalidCall -> assertThat(log).contains(invalidCall.expectedTraceLog));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidModExpCallsAreNotMined() throws Exception {
|
||||
final var modExp = deployModExp();
|
||||
|
||||
final var modExpSenders = new Account[3];
|
||||
final var foundTxHashes = new String[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
modExpSenders[i] = accounts.createAccount("sender" + i);
|
||||
foundTxHashes[i] =
|
||||
accountTransactions
|
||||
.createTransfer(
|
||||
accounts.getSecondaryBenefactor(), modExpSenders[i], 1, BigInteger.valueOf(i))
|
||||
.execute(minerNode.nodeRequests())
|
||||
.toHexString();
|
||||
}
|
||||
Arrays.stream(foundTxHashes)
|
||||
.forEach(
|
||||
fundTxHash -> minerNode.verify(eth.expectSuccessfulTransactionReceipt(fundTxHash)));
|
||||
|
||||
final Bytes[][] invalidInputs = {
|
||||
{Bytes.fromHexString("0000000000000000000000000000000000000000000000000000000000000201")},
|
||||
{
|
||||
Bytes.fromHexString("00000000000000000000000000000000000000000000000000000000000003"),
|
||||
Bytes.fromHexString("ff")
|
||||
},
|
||||
{
|
||||
Bytes.fromHexString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
Bytes.fromHexString("00000000000000000000000000000000000000000000000000000000000003"),
|
||||
Bytes.fromHexString("ff")
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < invalidInputs.length; i++) {
|
||||
final var invalidCallTxHashes = new String[invalidInputs[i].length];
|
||||
for (int j = 0; j < invalidInputs[i].length; j++) {
|
||||
|
||||
// use always the same nonce since we expect this tx not to be mined
|
||||
final var mulmodOverflow =
|
||||
encodedCallModExp(modExp, modExpSenders[j], 0, invalidInputs[i][j]);
|
||||
|
||||
final Web3j web3j = minerNode.nodeRequests().eth();
|
||||
final EthSendTransaction resp =
|
||||
web3j.ethSendRawTransaction(Numeric.toHexString(mulmodOverflow)).send();
|
||||
invalidCallTxHashes[j] = resp.getTransactionHash();
|
||||
}
|
||||
|
||||
// transfer used as sentry to ensure a new block is mined without the invalid modexp call
|
||||
final var transferTxHash =
|
||||
accountTransactions
|
||||
.createTransfer(
|
||||
accounts.getPrimaryBenefactor(),
|
||||
accounts.getSecondaryBenefactor(),
|
||||
1,
|
||||
BigInteger.valueOf(i + 1))
|
||||
.execute(minerNode.nodeRequests());
|
||||
|
||||
// sentry is mined and the invalid modexp txs are not
|
||||
minerNode.verify(eth.expectSuccessfulTransactionReceipt(transferTxHash.toHexString()));
|
||||
final var blockLog = getAndResetLog();
|
||||
Arrays.stream(invalidCallTxHashes)
|
||||
.forEach(
|
||||
invalidCallTxHash -> {
|
||||
minerNode.verify(eth.expectNoTransactionReceipt(invalidCallTxHash));
|
||||
assertThat(blockLog)
|
||||
.contains(
|
||||
"Tx "
|
||||
+ invalidCallTxHash
|
||||
+ " line count for module MODEXP=2147483647 is above the limit 1, removing from the txpool");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private String encodedCallBlake2F(final ExcludedPrecompiles excludedPrecompiles) {
|
||||
return excludedPrecompiles
|
||||
.callBlake2f(
|
||||
BigInteger.valueOf(12),
|
||||
List.of(
|
||||
Bytes32.fromHexString(
|
||||
"0x48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5")
|
||||
.toArrayUnsafe(),
|
||||
Bytes32.fromHexString(
|
||||
"0xd182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b")
|
||||
.toArrayUnsafe()),
|
||||
List.of(
|
||||
Bytes32.fromHexString(
|
||||
"0x6162630000000000000000000000000000000000000000000000000000000000")
|
||||
.toArrayUnsafe(),
|
||||
Bytes32.ZERO.toArrayUnsafe(),
|
||||
Bytes32.ZERO.toArrayUnsafe(),
|
||||
Bytes32.ZERO.toArrayUnsafe()),
|
||||
List.of(Bytes8.DEFAULT.getValue(), Bytes8.DEFAULT.getValue()),
|
||||
true)
|
||||
.encodeFunctionCall();
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*/
|
||||
package linea.plugin.acc.test.rpc.linea;
|
||||
package linea.plugin.acc.test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -14,10 +14,7 @@ import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import linea.plugin.acc.test.LineaPluginTestBase;
|
||||
import linea.plugin.acc.test.TestCommandLineOptionsBuilder;
|
||||
import linea.plugin.acc.test.tests.web3j.generated.ModExp;
|
||||
import net.consensys.linea.config.LineaTracerConfiguration;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
@@ -46,8 +43,7 @@ public class ModExpLimitsTest extends LineaPluginTestBase {
|
||||
@Test
|
||||
public void modExpLimitTest() throws Exception {
|
||||
Map<String, Integer> moduleLimits =
|
||||
ModuleLineCountValidator.createLimitModules(
|
||||
new LineaTracerConfiguration(getResourcePath("/moduleLimits.toml")));
|
||||
ModuleLineCountValidator.createLimitModules(getResourcePath("/moduleLimits.toml"));
|
||||
final int PRECOMPILE_MODEXP_EFFECTIVE_CALLS =
|
||||
moduleLimits.get("PRECOMPILE_MODEXP_EFFECTIVE_CALLS");
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright Consensys Software Inc.
|
||||
*
|
||||
* This file is dual-licensed under either the MIT license or Apache License 2.0.
|
||||
* See the LICENSE-MIT and LICENSE-APACHE files in the repository root for details.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*/
|
||||
package linea.plugin.acc.test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.web3j.crypto.Credentials;
|
||||
import org.web3j.crypto.RawTransaction;
|
||||
import org.web3j.crypto.TransactionEncoder;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.methods.response.EthSendTransaction;
|
||||
import org.web3j.tx.gas.DefaultGasProvider;
|
||||
import org.web3j.utils.Numeric;
|
||||
|
||||
public class TransactionTraceLimitLimitlessTest extends LineaPluginTestBase {
|
||||
|
||||
private static final BigInteger GAS_LIMIT = DefaultGasProvider.GAS_LIMIT;
|
||||
private static final BigInteger VALUE = BigInteger.ZERO;
|
||||
private static final BigInteger GAS_PRICE = BigInteger.TEN.pow(9);
|
||||
|
||||
@Override
|
||||
public List<String> getTestCliOptions() {
|
||||
return new TestCommandLineOptionsBuilder()
|
||||
// set the module limits file
|
||||
.set(
|
||||
"--plugin-linea-module-limit-file-path=",
|
||||
getResourcePath("/strictModuleLimitsLimitless.toml"))
|
||||
// enabled the ZkCounter
|
||||
.set("--plugin-linea-limitless-enabled=", "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionsMinedInSeparateBlocksTest() throws Exception {
|
||||
final Web3j web3j = minerNode.nodeRequests().eth();
|
||||
final Credentials credentials = Credentials.create(Accounts.GENESIS_ACCOUNT_ONE_PRIVATE_KEY);
|
||||
|
||||
final String txData = Bytes.repeat((byte) 3, 1000).toUnprefixedHexString();
|
||||
|
||||
// send txs that when encoded to RLP are bigger than 1000 byte, so only one should fit in a
|
||||
// block, since the
|
||||
// block size limit is 2000 byte
|
||||
final ArrayList<String> hashes = new ArrayList<>(5);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final RawTransaction transaction =
|
||||
RawTransaction.createTransaction(
|
||||
CHAIN_ID,
|
||||
BigInteger.valueOf(i),
|
||||
GAS_LIMIT,
|
||||
accounts.getSecondaryBenefactor().getAddress(),
|
||||
VALUE,
|
||||
txData,
|
||||
GAS_PRICE,
|
||||
GAS_PRICE.multiply(BigInteger.TEN));
|
||||
final byte[] signedTransaction = TransactionEncoder.signMessage(transaction, credentials);
|
||||
final EthSendTransaction response =
|
||||
web3j.ethSendRawTransaction(Numeric.toHexString(signedTransaction)).send();
|
||||
hashes.add(response.getTransactionHash());
|
||||
}
|
||||
|
||||
// make sure that there are no more than one transaction per block, because the BLOCK_L1_SIZE
|
||||
// limit only allows for one of these transactions.
|
||||
assertTransactionsMinedInSeparateBlocks(web3j, hashes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright Consensys Software Inc.
|
||||
*
|
||||
* This file is dual-licensed under either the MIT license or Apache License 2.0.
|
||||
* See the LICENSE-MIT and LICENSE-APACHE files in the repository root for details.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*/
|
||||
package linea.plugin.acc.test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.web3j.crypto.Credentials;
|
||||
import org.web3j.crypto.RawTransaction;
|
||||
import org.web3j.crypto.TransactionEncoder;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.methods.response.EthSendTransaction;
|
||||
import org.web3j.tx.gas.DefaultGasProvider;
|
||||
import org.web3j.utils.Numeric;
|
||||
|
||||
public class TransactionTraceLimitOverflowLimitlessTest extends LineaPluginTestBase {
|
||||
|
||||
private static final BigInteger GAS_LIMIT = DefaultGasProvider.GAS_LIMIT;
|
||||
private static final BigInteger VALUE = BigInteger.ZERO;
|
||||
private static final BigInteger GAS_PRICE = BigInteger.TEN.pow(11);
|
||||
|
||||
@Override
|
||||
public List<String> getTestCliOptions() {
|
||||
return new TestCommandLineOptionsBuilder()
|
||||
// set the module limits file
|
||||
.set(
|
||||
"--plugin-linea-module-limit-file-path=",
|
||||
getResourcePath("/strictModuleLimitsLimitless.toml"))
|
||||
// enabled the ZkCounter
|
||||
.set("--plugin-linea-limitless-enabled=", "true")
|
||||
.set("--plugin-linea-tx-pool-simulation-check-api-enabled=", "false")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionOverModuleLineCountRemoved() throws Exception {
|
||||
final Web3j web3j = minerNode.nodeRequests().eth();
|
||||
final String txData = Bytes.repeat((byte) 3, 2000).toUnprefixedHexString();
|
||||
|
||||
// this tx will not be selected since it goes above the max block size,
|
||||
// but selection should go on and select the next one
|
||||
final RawTransaction txModuleLineCountTooBig =
|
||||
RawTransaction.createTransaction(
|
||||
CHAIN_ID,
|
||||
BigInteger.ZERO,
|
||||
GAS_LIMIT.divide(BigInteger.TEN),
|
||||
accounts.getPrimaryBenefactor().getAddress(),
|
||||
VALUE,
|
||||
txData,
|
||||
GAS_PRICE,
|
||||
GAS_PRICE.multiply(BigInteger.TEN).add(BigInteger.ONE));
|
||||
final byte[] signedTxContractInteraction =
|
||||
TransactionEncoder.signMessage(
|
||||
txModuleLineCountTooBig, Credentials.create(Accounts.GENESIS_ACCOUNT_ONE_PRIVATE_KEY));
|
||||
final EthSendTransaction signedTxContractInteractionResp =
|
||||
web3j.ethSendRawTransaction(Numeric.toHexString(signedTxContractInteraction)).send();
|
||||
|
||||
// these are under the block size limit and should be selected
|
||||
final Account fewLinesSender = accounts.getSecondaryBenefactor();
|
||||
final Account recipient = accounts.createAccount("recipient");
|
||||
final List<Hash> expectedConfirmedTxs = new ArrayList<>(4);
|
||||
|
||||
expectedConfirmedTxs.addAll(
|
||||
minerNode.execute(
|
||||
accountTransactions.createIncrementalTransfers(fewLinesSender, recipient, 4)));
|
||||
|
||||
expectedConfirmedTxs.stream()
|
||||
.map(Hash::toHexString)
|
||||
.forEach(hash -> minerNode.verify(eth.expectSuccessfulTransactionReceipt(hash)));
|
||||
|
||||
// assert that tx over line count limit is not confirmed and is removed from the pool
|
||||
minerNode.verify(
|
||||
eth.expectNoTransactionReceipt(signedTxContractInteractionResp.getTransactionHash()));
|
||||
assertTransactionNotInThePool(signedTxContractInteractionResp.getTransactionHash());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright Consensys Software Inc.
|
||||
*
|
||||
* This file is dual-licensed under either the MIT license or Apache License 2.0.
|
||||
* See the LICENSE-MIT and LICENSE-APACHE files in the repository root for details.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*/
|
||||
package linea.plugin.acc.test.rpc.linea;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import linea.plugin.acc.test.LineaPluginTestBase;
|
||||
import linea.plugin.acc.test.TestCommandLineOptionsBuilder;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.web3j.tx.gas.DefaultGasProvider;
|
||||
|
||||
public class EstimateGasModuleLimitOverflowLimitlessTest extends LineaPluginTestBase {
|
||||
@Override
|
||||
public List<String> getTestCliOptions() {
|
||||
return new TestCommandLineOptionsBuilder()
|
||||
// set the module limits file
|
||||
.set(
|
||||
"--plugin-linea-module-limit-file-path=",
|
||||
getResourcePath("/moduleLimitsLimitless.toml"))
|
||||
// enabled the ZkCounter
|
||||
.set("--plugin-linea-limitless-enabled=", "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void estimateGasFailsForExceedingModuleLineCountTest() throws Exception {
|
||||
final var modExp = deployModExp();
|
||||
|
||||
final Bytes[] invalidInputs = {
|
||||
Bytes.fromHexString("0000000000000000000000000000000000000000000000000000000000000201"),
|
||||
Bytes.fromHexString("00000000000000000000000000000000000000000000000000000000000003"),
|
||||
Bytes.fromHexString("ff"),
|
||||
Bytes.fromHexString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
||||
};
|
||||
|
||||
for (int i = 0; i < invalidInputs.length; i++) {
|
||||
final var modExpCalldata =
|
||||
modExp.callModExp(invalidInputs[i].toArrayUnsafe()).encodeFunctionCall();
|
||||
|
||||
final EstimateGasTest.CallParams callParams =
|
||||
new EstimateGasTest.CallParams(
|
||||
null,
|
||||
accounts.getSecondaryBenefactor().getAddress(),
|
||||
null,
|
||||
modExp.getContractAddress(),
|
||||
null,
|
||||
modExpCalldata,
|
||||
"0",
|
||||
DefaultGasProvider.GAS_PRICE.toString(),
|
||||
null,
|
||||
null);
|
||||
|
||||
final var reqLinea = new EstimateGasTest.BadLineaEstimateGasRequest(callParams);
|
||||
final var respLinea = reqLinea.execute(minerNode.nodeRequests());
|
||||
assertThat(respLinea.getCode()).isEqualTo(-32000);
|
||||
assertThat(respLinea.getMessage())
|
||||
.isEqualTo("Transaction line count for module MODEXP=2147483647 is above the limit 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright Consensys Software Inc.
|
||||
*
|
||||
* This file is dual-licensed under either the MIT license or Apache License 2.0.
|
||||
* See the LICENSE-MIT and LICENSE-APACHE files in the repository root for details.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*/
|
||||
package linea.plugin.acc.test.rpc.linea;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
import linea.plugin.acc.test.LineaPluginTestBase;
|
||||
import linea.plugin.acc.test.TestCommandLineOptionsBuilder;
|
||||
import linea.plugin.acc.test.tests.web3j.generated.ExcludedPrecompiles;
|
||||
import linea.plugin.acc.test.tests.web3j.generated.RevertExample;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts;
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransactionSet;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.web3j.abi.datatypes.generated.Bytes8;
|
||||
import org.web3j.crypto.Credentials;
|
||||
import org.web3j.crypto.RawTransaction;
|
||||
import org.web3j.crypto.TransactionEncoder;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.methods.response.EthSendTransaction;
|
||||
import org.web3j.tx.gas.DefaultGasProvider;
|
||||
import org.web3j.utils.Numeric;
|
||||
|
||||
public class EthSendRawTransactionSimulationCheckLimitlessTest extends LineaPluginTestBase {
|
||||
private static final BigInteger GAS_LIMIT = DefaultGasProvider.GAS_LIMIT;
|
||||
private static final BigInteger VALUE = BigInteger.ZERO;
|
||||
private static final BigInteger GAS_PRICE = BigInteger.TEN.pow(9);
|
||||
|
||||
@Override
|
||||
public List<String> getTestCliOptions() {
|
||||
return new TestCommandLineOptionsBuilder()
|
||||
// set the module limits file
|
||||
.set(
|
||||
"--plugin-linea-module-limit-file-path=",
|
||||
getResourcePath("/moduleLimitsLimitless.toml"))
|
||||
// enabled the ZkCounter
|
||||
.set("--plugin-linea-limitless-enabled=", "true")
|
||||
.set("--plugin-linea-tx-pool-simulation-check-api-enabled=", "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validTransactionsAreAccepted() {
|
||||
// these are under the line count limit and should be accepted and selected
|
||||
final Account recipient = accounts.createAccount("recipient");
|
||||
final List<Hash> expectedConfirmedTxs = new ArrayList<>(4);
|
||||
|
||||
final var transfers =
|
||||
IntStream.range(0, 4)
|
||||
.mapToObj(
|
||||
i ->
|
||||
accountTransactions.createTransfer(
|
||||
accounts.getSecondaryBenefactor(), recipient, i + 1, BigInteger.valueOf(i)))
|
||||
.toList()
|
||||
.reversed();
|
||||
// reversed, so we are sure no tx is selected before all are sent due to the nonce gap,
|
||||
// otherwise a block can be built with some txs before we can check the txpool content
|
||||
|
||||
expectedConfirmedTxs.addAll(minerNode.execute(new TransferTransactionSet(transfers)));
|
||||
|
||||
final var txPoolContentByHash = getTxPoolContent().stream().map(e -> e.get("hash")).toList();
|
||||
assertThat(txPoolContentByHash)
|
||||
.containsExactlyInAnyOrderElementsOf(
|
||||
expectedConfirmedTxs.stream().map(Hash::toHexString).toList());
|
||||
|
||||
expectedConfirmedTxs.stream()
|
||||
.map(Hash::toHexString)
|
||||
.forEach(hash -> minerNode.verify(eth.expectSuccessfulTransactionReceipt(hash)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionsThatRevertAreAccepted() throws Exception {
|
||||
final RevertExample revertExample = deployRevertExample();
|
||||
final Web3j web3j = minerNode.nodeRequests().eth();
|
||||
final String contractAddress = revertExample.getContractAddress();
|
||||
final String txData = revertExample.setValue(BigInteger.ZERO).encodeFunctionCall();
|
||||
|
||||
// this tx reverts but nevertheless it is accepted in the pool
|
||||
final RawTransaction txThatReverts =
|
||||
RawTransaction.createTransaction(
|
||||
CHAIN_ID,
|
||||
BigInteger.ZERO,
|
||||
GAS_LIMIT.divide(BigInteger.TEN),
|
||||
contractAddress,
|
||||
VALUE,
|
||||
txData,
|
||||
GAS_PRICE,
|
||||
GAS_PRICE.multiply(BigInteger.TEN).add(BigInteger.ONE));
|
||||
final byte[] signedTxContractInteraction =
|
||||
TransactionEncoder.signMessage(
|
||||
txThatReverts, Credentials.create(Accounts.GENESIS_ACCOUNT_TWO_PRIVATE_KEY));
|
||||
|
||||
final EthSendTransaction signedTxContractInteractionResp =
|
||||
web3j.ethSendRawTransaction(Numeric.toHexString(signedTxContractInteraction)).send();
|
||||
|
||||
assertThat(signedTxContractInteractionResp.hasError()).isFalse();
|
||||
|
||||
final var expectedConfirmedTxHash = signedTxContractInteractionResp.getTransactionHash();
|
||||
|
||||
minerNode.verify(eth.expectSuccessfulTransactionReceipt(expectedConfirmedTxHash));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionsWithExcludedPrecompilesAreNotAccepted() throws Exception {
|
||||
final ExcludedPrecompiles excludedPrecompiles = deployExcludedPrecompiles();
|
||||
final Web3j web3j = minerNode.nodeRequests().eth();
|
||||
final String contractAddress = excludedPrecompiles.getContractAddress();
|
||||
|
||||
record InvalidCall(String encodedContractCall, String expectedErrorMessage) {}
|
||||
|
||||
final InvalidCall[] invalidCalls = {
|
||||
new InvalidCall(
|
||||
excludedPrecompiles
|
||||
.callRIPEMD160("I am not allowed here".getBytes(StandardCharsets.UTF_8))
|
||||
.encodeFunctionCall(),
|
||||
"Transaction 0x35451c83b480b45df19105a30f22704df8750b7e328e1ebc646e6442f2f426f9 line count for module RIP=2147483647 is above the limit 1"),
|
||||
new InvalidCall(
|
||||
encodedCallBlake2F(excludedPrecompiles),
|
||||
"Transaction 0xfd447b2b688f7448c875f68d9c85ffcb976e1cc722b70dae53e4f2e30d871be8 line count for module BLAKE=2147483647 is above the limit 1")
|
||||
};
|
||||
|
||||
Arrays.stream(invalidCalls)
|
||||
.forEach(
|
||||
invalidCall -> {
|
||||
// this tx must not be accepted
|
||||
final RawTransaction txInvalid =
|
||||
RawTransaction.createTransaction(
|
||||
CHAIN_ID,
|
||||
BigInteger.ZERO,
|
||||
GAS_LIMIT.divide(BigInteger.TEN),
|
||||
contractAddress,
|
||||
VALUE,
|
||||
invalidCall.encodedContractCall,
|
||||
GAS_PRICE,
|
||||
GAS_PRICE.multiply(BigInteger.TEN).add(BigInteger.ONE));
|
||||
|
||||
final byte[] signedTxInvalid =
|
||||
TransactionEncoder.signMessage(
|
||||
txInvalid, Credentials.create(Accounts.GENESIS_ACCOUNT_TWO_PRIVATE_KEY));
|
||||
|
||||
final EthSendTransaction signedTxContractInteractionResp;
|
||||
try {
|
||||
signedTxContractInteractionResp =
|
||||
web3j.ethSendRawTransaction(Numeric.toHexString(signedTxInvalid)).send();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
assertThat(signedTxContractInteractionResp.hasError()).isTrue();
|
||||
assertThat(signedTxContractInteractionResp.getError().getMessage())
|
||||
.isEqualTo(invalidCall.expectedErrorMessage);
|
||||
});
|
||||
assertThat(getTxPoolContent()).isEmpty();
|
||||
}
|
||||
|
||||
private String encodedCallBlake2F(final ExcludedPrecompiles excludedPrecompiles) {
|
||||
return excludedPrecompiles
|
||||
.callBlake2f(
|
||||
BigInteger.valueOf(12),
|
||||
List.of(
|
||||
Bytes32.fromHexString(
|
||||
"0x48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5")
|
||||
.toArrayUnsafe(),
|
||||
Bytes32.fromHexString(
|
||||
"0xd182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b")
|
||||
.toArrayUnsafe()),
|
||||
List.of(
|
||||
Bytes32.fromHexString(
|
||||
"0x6162630000000000000000000000000000000000000000000000000000000000")
|
||||
.toArrayUnsafe(),
|
||||
Bytes32.ZERO.toArrayUnsafe(),
|
||||
Bytes32.ZERO.toArrayUnsafe(),
|
||||
Bytes32.ZERO.toArrayUnsafe()),
|
||||
List.of(Bytes8.DEFAULT.getValue(), Bytes8.DEFAULT.getValue()),
|
||||
true)
|
||||
.encodeFunctionCall();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright Consensys Software Inc.
|
||||
*
|
||||
* This file is dual-licensed under either the MIT license or Apache License 2.0.
|
||||
* See the LICENSE-MIT and LICENSE-APACHE files in the repository root for details.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*/
|
||||
package linea.plugin.acc.test.rpc.linea;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.web3j.crypto.Hash.sha3;
|
||||
|
||||
import java.util.List;
|
||||
import linea.plugin.acc.test.LineaPluginTestBase;
|
||||
import linea.plugin.acc.test.TestCommandLineOptionsBuilder;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.methods.response.EthSendTransaction;
|
||||
import org.web3j.utils.Numeric;
|
||||
|
||||
public class EthSendRawTransactionSimulationModExpLimitlessTest extends LineaPluginTestBase {
|
||||
|
||||
@Override
|
||||
public List<String> getTestCliOptions() {
|
||||
return new TestCommandLineOptionsBuilder()
|
||||
// set the module limits file
|
||||
.set(
|
||||
"--plugin-linea-module-limit-file-path=",
|
||||
getResourcePath("/moduleLimitsLimitless.toml"))
|
||||
// enabled the ZkCounter
|
||||
.set("--plugin-linea-limitless-enabled=", "true")
|
||||
.set("--plugin-linea-tx-pool-simulation-check-api-enabled=", "true")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validModExpCallsAreAccepted() throws Exception {
|
||||
final var modExp = deployModExp();
|
||||
|
||||
final Bytes[] validInputs = {
|
||||
Bytes.EMPTY,
|
||||
Bytes.fromHexString("0000000000000000000000000000000000000000000000000000000000000000"),
|
||||
Bytes.fromHexString("000000000000000000000000000000000000000000000000000000000000013f"),
|
||||
Bytes.fromHexString("0000000000000000000000000000000000000000000000000000000000000200"),
|
||||
Bytes.fromHexString("00000000000000000000000000000000000000000000000000000000000002")
|
||||
};
|
||||
|
||||
for (int i = 0; i < validInputs.length; i++) {
|
||||
|
||||
final var mulmodOverflow =
|
||||
encodedCallModExp(modExp, accounts.getSecondaryBenefactor(), i, validInputs[i]);
|
||||
|
||||
final Web3j web3j = minerNode.nodeRequests().eth();
|
||||
final EthSendTransaction resp =
|
||||
web3j.ethSendRawTransaction(Numeric.toHexString(mulmodOverflow)).send();
|
||||
assertThat(resp.hasError()).isFalse();
|
||||
|
||||
minerNode.verify(eth.expectSuccessfulTransactionReceipt(resp.getTransactionHash()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidModExpCallsAreRejected() throws Exception {
|
||||
final var modExp = deployModExp();
|
||||
|
||||
final Bytes[] invalidInputs = {
|
||||
Bytes.fromHexString("0000000000000000000000000000000000000000000000000000000000000201"),
|
||||
Bytes.fromHexString("00000000000000000000000000000000000000000000000000000000000003"),
|
||||
Bytes.fromHexString("ff"),
|
||||
Bytes.fromHexString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
||||
};
|
||||
|
||||
for (int i = 0; i < invalidInputs.length; i++) {
|
||||
|
||||
final var mulmodOverflow =
|
||||
encodedCallModExp(modExp, accounts.getSecondaryBenefactor(), i, invalidInputs[i]);
|
||||
|
||||
final Web3j web3j = minerNode.nodeRequests().eth();
|
||||
final EthSendTransaction resp =
|
||||
web3j.ethSendRawTransaction(Numeric.toHexString(mulmodOverflow)).send();
|
||||
|
||||
assertThat(resp.hasError()).isTrue();
|
||||
assertThat(resp.getError().getMessage())
|
||||
.isEqualTo(
|
||||
"Transaction "
|
||||
+ Numeric.toHexString(sha3(mulmodOverflow))
|
||||
+ " line count for module MODEXP=2147483647 is above the limit 1");
|
||||
|
||||
assertThat(getTxPoolContent()).isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,22 +4,61 @@
|
||||
<Property name="root.log.level">TRACE</Property>
|
||||
</Properties>
|
||||
<Appenders>
|
||||
<Console name="Console">
|
||||
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZZZ} | %t | %-5level | %c{1} | %msg%n" />
|
||||
</Console>
|
||||
<Memory name="Memory">
|
||||
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZZZ} | %t | %-5level | %c{1} | %msg%n" />
|
||||
</Memory>
|
||||
<Console name="Console">
|
||||
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZZZ} | %t | %-5level | %c{1} | %msg%n" />
|
||||
</Console>
|
||||
<Memory name="Memory">
|
||||
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZZZ} | %t | %-5level | %c{1} | %msg%n" />
|
||||
</Memory>
|
||||
<Console name="ConsoleBLC" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern='{"blockNumber":%X{blockNumber},"blockHash":"%X{blockHash}","traceCounts":{%X{traceCounts}}}%n'/>
|
||||
</Console>
|
||||
<Memory name="MemoryBLC">
|
||||
<PatternLayout pattern='{"blockNumber":%X{blockNumber},"blockHash":"%X{blockHash}","traceCounts":{%X{traceCounts}}}%n'/>
|
||||
</Memory>
|
||||
<Console name="ConsoleITR" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="Invalid tx removed:%X{txlog}, reason:%X{reason}; RLP={%X{txrlp}}}%n"/>
|
||||
</Console>
|
||||
<Memory name="MemoryITR">
|
||||
<PatternLayout pattern="Invalid tx removed:%X{txlog}, reason:%X{reason}; RLP={%X{txrlp}}}%n"/>
|
||||
</Memory>
|
||||
|
||||
<Async name="Main">
|
||||
<AppenderRef ref="Console" />
|
||||
<AppenderRef ref="Memory" />
|
||||
</Async>
|
||||
<Routing name="Router">
|
||||
<Routes pattern="$${event:Marker}">
|
||||
<Route key="BLOCK_LINE_COUNT">
|
||||
<Async name="BLC">
|
||||
<AppenderRef ref="ConsoleBLC" />
|
||||
<AppenderRef ref="MemoryBLC" />
|
||||
</Async>
|
||||
</Route>
|
||||
<Route key="INVALID_TX_REMOVED">
|
||||
<Async name="ITR">
|
||||
<AppenderRef ref="ConsoleITR" />
|
||||
<AppenderRef ref="MemoryITR" />
|
||||
</Async>
|
||||
</Route>
|
||||
<Route ref="Main" />
|
||||
</Routes>
|
||||
</Routing>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Logger name="net.consensys.linea.sequencer.txselection.selectors.TraceLineLimitTransactionSelector" level="${sys:root.log.level}" additivity="false">
|
||||
<AppenderRef ref="Router" />
|
||||
</Logger>
|
||||
<Logger name="org.hyperledger.besu.ethereum.eth.transactions" level="${sys:root.log.level}" additivity="false">
|
||||
<AppenderRef ref="Router"/>
|
||||
</Logger>
|
||||
<Logger level="INFO" name="io.vertx" />
|
||||
<Logger level="INFO" name="io.netty" />
|
||||
<Logger level="INFO" name="org.web3j.protocol.http.HttpService" />
|
||||
<Logger level="INFO" name="org.hyperledger.besu.ethereum.p2p.network.DefaultP2PNetwork" />
|
||||
<Logger level="INFO" name="org.hyperledger.besu.ethereum.eth.manager.EthPeers" />
|
||||
<Root level="${sys:root.log.level}">
|
||||
<AppenderRef ref="Console" />
|
||||
<AppenderRef ref="Memory" />
|
||||
<AppenderRef ref="Main" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
##
|
||||
# This file specifies prover limit by each EVM module
|
||||
# WARN: The prover/arithmetization team has the owneship of this.
|
||||
# Changing this values may compromise the system.
|
||||
# issue: https://github.com/Consensys/zkevm-monorepo/issues/525
|
||||
##
|
||||
|
||||
[traces-limits]
|
||||
MODEXP = 1
|
||||
RIP = 1
|
||||
BLAKE = 1
|
||||
|
||||
#
|
||||
# Block-specific limits
|
||||
#
|
||||
BLOCK_L1_SIZE = 1000000
|
||||
BLOCK_L2_L1_LOGS = 16
|
||||
@@ -0,0 +1,17 @@
|
||||
##
|
||||
# This file specifies prover limit by each EVM module
|
||||
# WARN: The prover/arithmetization team has the owneship of this.
|
||||
# Changing this values may compromise the system.
|
||||
# issue: https://github.com/Consensys/zkevm-monorepo/issues/525
|
||||
##
|
||||
|
||||
[traces-limits]
|
||||
MODEXP = 1
|
||||
RIP = 1
|
||||
BLAKE = 1
|
||||
|
||||
#
|
||||
# Block-specific limits
|
||||
#
|
||||
BLOCK_L1_SIZE = 2000
|
||||
BLOCK_L2_L1_LOGS = 16
|
||||
@@ -10,6 +10,7 @@ package net.consensys.linea.config;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import net.consensys.linea.plugins.LineaCliOptions;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator;
|
||||
import picocli.CommandLine;
|
||||
|
||||
public class LineaTracerCliOptions implements LineaCliOptions {
|
||||
@@ -17,6 +18,8 @@ public class LineaTracerCliOptions implements LineaCliOptions {
|
||||
|
||||
public static final String MODULE_LIMIT_FILE_PATH = "--plugin-linea-module-limit-file-path";
|
||||
public static final String DEFAULT_MODULE_LIMIT_FILE_PATH = "moduleLimitFile.toml";
|
||||
public static final String LIMITLESS_ENABLED = "--plugin-linea-limitless-enabled";
|
||||
public static final boolean DEFAULT_LIMITLESS_ENABLED = false;
|
||||
|
||||
@CommandLine.Option(
|
||||
names = {MODULE_LIMIT_FILE_PATH},
|
||||
@@ -26,6 +29,14 @@ public class LineaTracerCliOptions implements LineaCliOptions {
|
||||
"Path to the toml file containing the module limits (default: ${DEFAULT-VALUE})")
|
||||
private String moduleLimitFilePath = DEFAULT_MODULE_LIMIT_FILE_PATH;
|
||||
|
||||
@CommandLine.Option(
|
||||
names = {LIMITLESS_ENABLED},
|
||||
hidden = true,
|
||||
paramLabel = "<BOOLEAN>",
|
||||
description =
|
||||
"If the sequencer needs to use or not the limitless prover (default: ${DEFAULT-VALUE})")
|
||||
private boolean limitlessEnabled = DEFAULT_LIMITLESS_ENABLED;
|
||||
|
||||
private LineaTracerCliOptions() {}
|
||||
|
||||
/**
|
||||
@@ -46,6 +57,7 @@ public class LineaTracerCliOptions implements LineaCliOptions {
|
||||
public static LineaTracerCliOptions fromConfig(final LineaTracerConfiguration config) {
|
||||
final LineaTracerCliOptions options = create();
|
||||
options.moduleLimitFilePath = config.moduleLimitsFilePath();
|
||||
options.limitlessEnabled = config.isLimitless();
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -56,13 +68,18 @@ public class LineaTracerCliOptions implements LineaCliOptions {
|
||||
*/
|
||||
@Override
|
||||
public LineaTracerConfiguration toDomainObject() {
|
||||
return LineaTracerConfiguration.builder().moduleLimitsFilePath(moduleLimitFilePath).build();
|
||||
return LineaTracerConfiguration.builder()
|
||||
.moduleLimitsFilePath(moduleLimitFilePath)
|
||||
.moduleLimitsMap(ModuleLineCountValidator.createLimitModules(moduleLimitFilePath))
|
||||
.isLimitless(limitlessEnabled)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add(MODULE_LIMIT_FILE_PATH, moduleLimitFilePath)
|
||||
.add(LIMITLESS_ENABLED, limitlessEnabled)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
|
||||
package net.consensys.linea.config;
|
||||
|
||||
import java.util.Map;
|
||||
import lombok.Builder;
|
||||
import net.consensys.linea.plugins.LineaOptionsConfiguration;
|
||||
|
||||
/** The Linea tracer configuration. */
|
||||
@Builder(toBuilder = true)
|
||||
public record LineaTracerConfiguration(String moduleLimitsFilePath)
|
||||
public record LineaTracerConfiguration(
|
||||
String moduleLimitsFilePath, Map<String, Integer> moduleLimitsMap, boolean isLimitless)
|
||||
implements LineaOptionsConfiguration {}
|
||||
|
||||
@@ -19,17 +19,19 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.consensys.linea.bl.TransactionProfitabilityCalculator;
|
||||
import net.consensys.linea.config.LineaProfitabilityConfiguration;
|
||||
import net.consensys.linea.config.LineaRpcConfiguration;
|
||||
import net.consensys.linea.config.LineaTracerConfiguration;
|
||||
import net.consensys.linea.config.LineaTransactionPoolValidatorConfiguration;
|
||||
import net.consensys.linea.plugins.config.LineaL1L2BridgeSharedConfiguration;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLimitsValidationResult;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator;
|
||||
import net.consensys.linea.zktracer.LineCountingTracer;
|
||||
import net.consensys.linea.zktracer.ZkCounter;
|
||||
import net.consensys.linea.zktracer.ZkTracer;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
||||
@@ -86,6 +88,7 @@ public class LineaEstimateGas {
|
||||
private LineaProfitabilityConfiguration profitabilityConf;
|
||||
private TransactionProfitabilityCalculator txProfitabilityCalculator;
|
||||
private LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration;
|
||||
private LineaTracerConfiguration tracerConfiguration;
|
||||
private ModuleLineCountValidator moduleLineCountValidator;
|
||||
|
||||
public LineaEstimateGas(
|
||||
@@ -103,14 +106,16 @@ public class LineaEstimateGas {
|
||||
final LineaRpcConfiguration rpcConfiguration,
|
||||
final LineaTransactionPoolValidatorConfiguration transactionValidatorConfiguration,
|
||||
final LineaProfitabilityConfiguration profitabilityConf,
|
||||
final Map<String, Integer> limitsMap,
|
||||
final LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration) {
|
||||
final LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration,
|
||||
final LineaTracerConfiguration tracerConfiguration) {
|
||||
this.rpcConfiguration = rpcConfiguration;
|
||||
this.txValidatorConf = transactionValidatorConfiguration;
|
||||
this.profitabilityConf = profitabilityConf;
|
||||
this.txProfitabilityCalculator = new TransactionProfitabilityCalculator(profitabilityConf);
|
||||
this.l1L2BridgeConfiguration = l1L2BridgeConfiguration;
|
||||
this.moduleLineCountValidator = new ModuleLineCountValidator(limitsMap);
|
||||
this.tracerConfiguration = tracerConfiguration;
|
||||
this.moduleLineCountValidator =
|
||||
new ModuleLineCountValidator(tracerConfiguration.moduleLimitsMap());
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
@@ -230,14 +235,15 @@ public class LineaEstimateGas {
|
||||
final long logId) {
|
||||
|
||||
final var pendingBlockHeader = transactionSimulationService.simulatePendingBlockHeader();
|
||||
final var zkTracer = createZkTracer(pendingBlockHeader, blockchainService.getChainId().get());
|
||||
final var lineCountingTracer =
|
||||
createLineCountingTracer(pendingBlockHeader, blockchainService.getChainId().get());
|
||||
|
||||
final var maybeSimulationResults =
|
||||
transactionSimulationService.simulate(
|
||||
transaction, maybeStateOverrides, pendingBlockHeader, zkTracer, false, true);
|
||||
transaction, maybeStateOverrides, pendingBlockHeader, lineCountingTracer, false, true);
|
||||
|
||||
ModuleLimitsValidationResult moduleLimit =
|
||||
moduleLineCountValidator.validate(zkTracer.getModulesLineCount());
|
||||
moduleLineCountValidator.validate(lineCountingTracer.getModulesLineCount());
|
||||
|
||||
if (moduleLimit.getResult() != ModuleLineCountValidator.ModuleLineCountResult.VALID) {
|
||||
handleModuleOverLimit(moduleLimit);
|
||||
@@ -395,12 +401,15 @@ public class LineaEstimateGas {
|
||||
.orElse(0L);
|
||||
}
|
||||
|
||||
private ZkTracer createZkTracer(
|
||||
private LineCountingTracer createLineCountingTracer(
|
||||
final ProcessableBlockHeader pendingBlockHeader, final BigInteger chainId) {
|
||||
var zkTracer = new ZkTracer(LONDON, l1L2BridgeConfiguration, chainId);
|
||||
zkTracer.traceStartConflation(1L);
|
||||
zkTracer.traceStartBlock(pendingBlockHeader, pendingBlockHeader.getCoinbase());
|
||||
return zkTracer;
|
||||
final var lineCountingTracer =
|
||||
tracerConfiguration.isLimitless()
|
||||
? new ZkCounter(l1L2BridgeConfiguration)
|
||||
: new ZkTracer(LONDON, l1L2BridgeConfiguration, chainId);
|
||||
lineCountingTracer.traceStartConflation(1L);
|
||||
lineCountingTracer.traceStartBlock(pendingBlockHeader, pendingBlockHeader.getCoinbase());
|
||||
return lineCountingTracer;
|
||||
}
|
||||
|
||||
private void handleModuleOverLimit(ModuleLimitsValidationResult moduleLimitResult) {
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
package net.consensys.linea.rpc.services;
|
||||
|
||||
import static net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator.createLimitModules;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.consensys.linea.AbstractLineaRequiredPlugin;
|
||||
@@ -60,8 +58,8 @@ public class LineaEstimateGasEndpointPlugin extends AbstractLineaRequiredPlugin
|
||||
lineaRpcConfiguration(),
|
||||
transactionPoolValidatorConfiguration(),
|
||||
profitabilityConfiguration(),
|
||||
createLimitModules(tracerConfiguration()),
|
||||
l1L2BridgeSharedConfiguration());
|
||||
l1L2BridgeSharedConfiguration(),
|
||||
tracerConfiguration());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,7 +16,6 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.consensys.linea.config.LineaTracerConfiguration;
|
||||
import org.apache.tuweni.toml.Toml;
|
||||
import org.apache.tuweni.toml.TomlParseResult;
|
||||
import org.apache.tuweni.toml.TomlTable;
|
||||
@@ -118,10 +117,9 @@ public class ModuleLineCountValidator {
|
||||
INVALID_LINE_COUNT
|
||||
}
|
||||
|
||||
public static Map<String, Integer> createLimitModules(
|
||||
LineaTracerConfiguration lineaTracerConfiguration) {
|
||||
public static Map<String, Integer> createLimitModules(String moduleLimitsFilePath) {
|
||||
try {
|
||||
URL url = new File(lineaTracerConfiguration.moduleLimitsFilePath()).toURI().toURL();
|
||||
URL url = new File(moduleLimitsFilePath).toURI().toURL();
|
||||
final String tomlString = Resources.toString(url, StandardCharsets.UTF_8);
|
||||
TomlParseResult result = Toml.parse(tomlString);
|
||||
final TomlTable table = result.getTable("traces-limits");
|
||||
@@ -135,7 +133,7 @@ public class ModuleLineCountValidator {
|
||||
} catch (final Exception e) {
|
||||
final String errorMsg =
|
||||
"Problem reading the toml file containing the limits for the modules: "
|
||||
+ lineaTracerConfiguration.moduleLimitsFilePath();
|
||||
+ moduleLimitsFilePath;
|
||||
log.error(errorMsg);
|
||||
throw new RuntimeException(errorMsg, e);
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
package net.consensys.linea.sequencer.txpoolvalidation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import net.consensys.linea.config.LineaProfitabilityConfiguration;
|
||||
import net.consensys.linea.config.LineaTracerConfiguration;
|
||||
import net.consensys.linea.config.LineaTransactionPoolValidatorConfiguration;
|
||||
import net.consensys.linea.jsonrpc.JsonRpcManager;
|
||||
import net.consensys.linea.plugins.config.LineaL1L2BridgeSharedConfiguration;
|
||||
@@ -38,8 +38,8 @@ public class LineaTransactionPoolValidatorFactory implements PluginTransactionPo
|
||||
private final LineaTransactionPoolValidatorConfiguration txPoolValidatorConf;
|
||||
private final LineaProfitabilityConfiguration profitabilityConf;
|
||||
private final Set<Address> denied;
|
||||
private final Map<String, Integer> moduleLineLimitsMap;
|
||||
private final LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration;
|
||||
private final LineaTracerConfiguration tracerConfiguration;
|
||||
private final Optional<JsonRpcManager> rejectedTxJsonRpcManager;
|
||||
|
||||
public LineaTransactionPoolValidatorFactory(
|
||||
@@ -49,7 +49,7 @@ public class LineaTransactionPoolValidatorFactory implements PluginTransactionPo
|
||||
final LineaTransactionPoolValidatorConfiguration txPoolValidatorConf,
|
||||
final LineaProfitabilityConfiguration profitabilityConf,
|
||||
final Set<Address> deniedAddresses,
|
||||
final Map<String, Integer> moduleLineLimitsMap,
|
||||
final LineaTracerConfiguration tracerConfiguration,
|
||||
final LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration,
|
||||
final Optional<JsonRpcManager> rejectedTxJsonRpcManager) {
|
||||
this.besuConfiguration = besuConfiguration;
|
||||
@@ -58,7 +58,7 @@ public class LineaTransactionPoolValidatorFactory implements PluginTransactionPo
|
||||
this.txPoolValidatorConf = txPoolValidatorConf;
|
||||
this.profitabilityConf = profitabilityConf;
|
||||
this.denied = deniedAddresses;
|
||||
this.moduleLineLimitsMap = moduleLineLimitsMap;
|
||||
this.tracerConfiguration = tracerConfiguration;
|
||||
this.l1L2BridgeConfiguration = l1L2BridgeConfiguration;
|
||||
this.rejectedTxJsonRpcManager = rejectedTxJsonRpcManager;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ public class LineaTransactionPoolValidatorFactory implements PluginTransactionPo
|
||||
blockchainService,
|
||||
transactionSimulationService,
|
||||
txPoolValidatorConf,
|
||||
moduleLineLimitsMap,
|
||||
tracerConfiguration,
|
||||
l1L2BridgeConfiguration,
|
||||
rejectedTxJsonRpcManager)
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
package net.consensys.linea.sequencer.txpoolvalidation;
|
||||
|
||||
import static net.consensys.linea.metrics.LineaMetricCategory.TX_POOL_PROFITABILITY;
|
||||
import static net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator.createLimitModules;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import java.io.File;
|
||||
@@ -104,7 +103,7 @@ public class LineaTransactionPoolValidatorPlugin extends AbstractLineaRequiredPl
|
||||
transactionPoolValidatorConfiguration(),
|
||||
profitabilityConfiguration(),
|
||||
deniedAddresses,
|
||||
createLimitModules(tracerConfiguration()),
|
||||
tracerConfiguration(),
|
||||
l1L2BridgeSharedConfiguration(),
|
||||
rejectedTxJsonRpcManager));
|
||||
|
||||
|
||||
@@ -15,15 +15,17 @@ import static net.consensys.linea.zktracer.Fork.LONDON;
|
||||
import java.math.BigInteger;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.consensys.linea.config.LineaTracerConfiguration;
|
||||
import net.consensys.linea.config.LineaTransactionPoolValidatorConfiguration;
|
||||
import net.consensys.linea.jsonrpc.JsonRpcManager;
|
||||
import net.consensys.linea.jsonrpc.JsonRpcRequestBuilder;
|
||||
import net.consensys.linea.plugins.config.LineaL1L2BridgeSharedConfiguration;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLimitsValidationResult;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator;
|
||||
import net.consensys.linea.zktracer.LineCountingTracer;
|
||||
import net.consensys.linea.zktracer.ZkCounter;
|
||||
import net.consensys.linea.zktracer.ZkTracer;
|
||||
import org.hyperledger.besu.datatypes.Transaction;
|
||||
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
|
||||
@@ -41,22 +43,22 @@ public class SimulationValidator implements PluginTransactionPoolValidator {
|
||||
private final BlockchainService blockchainService;
|
||||
private final TransactionSimulationService transactionSimulationService;
|
||||
private final LineaTransactionPoolValidatorConfiguration txPoolValidatorConf;
|
||||
private final Map<String, Integer> moduleLineLimitsMap;
|
||||
private final LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration;
|
||||
private final LineaTracerConfiguration tracerConfiguration;
|
||||
private final Optional<JsonRpcManager> rejectedTxJsonRpcManager;
|
||||
|
||||
public SimulationValidator(
|
||||
final BlockchainService blockchainService,
|
||||
final TransactionSimulationService transactionSimulationService,
|
||||
final LineaTransactionPoolValidatorConfiguration txPoolValidatorConf,
|
||||
final Map<String, Integer> moduleLineLimitsMap,
|
||||
final LineaTracerConfiguration tracerConfiguration,
|
||||
final LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration,
|
||||
final Optional<JsonRpcManager> rejectedTxJsonRpcManager) {
|
||||
this.blockchainService = blockchainService;
|
||||
this.transactionSimulationService = transactionSimulationService;
|
||||
this.txPoolValidatorConf = txPoolValidatorConf;
|
||||
this.moduleLineLimitsMap = moduleLineLimitsMap;
|
||||
this.l1L2BridgeConfiguration = l1L2BridgeConfiguration;
|
||||
this.tracerConfiguration = tracerConfiguration;
|
||||
this.rejectedTxJsonRpcManager = rejectedTxJsonRpcManager;
|
||||
}
|
||||
|
||||
@@ -78,16 +80,17 @@ public class SimulationValidator implements PluginTransactionPoolValidator {
|
||||
.log();
|
||||
|
||||
final ModuleLineCountValidator moduleLineCountValidator =
|
||||
new ModuleLineCountValidator(moduleLineLimitsMap);
|
||||
new ModuleLineCountValidator(tracerConfiguration.moduleLimitsMap());
|
||||
final var pendingBlockHeader = transactionSimulationService.simulatePendingBlockHeader();
|
||||
|
||||
final var zkTracer = createZkTracer(pendingBlockHeader, blockchainService.getChainId().get());
|
||||
final var lineCountingTracer =
|
||||
createLineCountingTracer(pendingBlockHeader, blockchainService.getChainId().get());
|
||||
final var maybeSimulationResults =
|
||||
transactionSimulationService.simulate(
|
||||
transaction, Optional.empty(), pendingBlockHeader, zkTracer, false, true);
|
||||
transaction, Optional.empty(), pendingBlockHeader, lineCountingTracer, false, true);
|
||||
|
||||
ModuleLimitsValidationResult moduleLimitResult =
|
||||
moduleLineCountValidator.validate(zkTracer.getModulesLineCount());
|
||||
moduleLineCountValidator.validate(lineCountingTracer.getModulesLineCount());
|
||||
|
||||
logSimulationResult(
|
||||
transaction, isLocal, hasPriority, maybeSimulationResults, moduleLimitResult);
|
||||
@@ -153,12 +156,15 @@ public class SimulationValidator implements PluginTransactionPoolValidator {
|
||||
.log();
|
||||
}
|
||||
|
||||
private ZkTracer createZkTracer(
|
||||
private LineCountingTracer createLineCountingTracer(
|
||||
final ProcessableBlockHeader pendingBlockHeader, BigInteger chainId) {
|
||||
var zkTracer = new ZkTracer(LONDON, l1L2BridgeConfiguration, chainId);
|
||||
zkTracer.traceStartConflation(1L);
|
||||
zkTracer.traceStartBlock(pendingBlockHeader, pendingBlockHeader.getCoinbase());
|
||||
return zkTracer;
|
||||
var lineCountingTracer =
|
||||
tracerConfiguration.isLimitless()
|
||||
? new ZkCounter(l1L2BridgeConfiguration)
|
||||
: new ZkTracer(LONDON, l1L2BridgeConfiguration, chainId);
|
||||
lineCountingTracer.traceStartConflation(1L);
|
||||
lineCountingTracer.traceStartBlock(pendingBlockHeader, pendingBlockHeader.getCoinbase());
|
||||
return lineCountingTracer;
|
||||
}
|
||||
|
||||
private String handleModuleOverLimit(
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
package net.consensys.linea.sequencer.txselection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -44,7 +43,6 @@ public class LineaTransactionSelectorFactory implements PluginTransactionSelecto
|
||||
private final LineaTracerConfiguration tracerConfiguration;
|
||||
private final Optional<HistogramMetrics> maybeProfitabilityMetrics;
|
||||
private final BundlePoolService bundlePoolService;
|
||||
private final Map<String, Integer> limitsMap;
|
||||
private final AtomicReference<LineaTransactionSelector> currSelector = new AtomicReference<>();
|
||||
|
||||
public LineaTransactionSelectorFactory(
|
||||
@@ -53,7 +51,6 @@ public class LineaTransactionSelectorFactory implements PluginTransactionSelecto
|
||||
final LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration,
|
||||
final LineaProfitabilityConfiguration profitabilityConfiguration,
|
||||
final LineaTracerConfiguration tracerConfiguration,
|
||||
final Map<String, Integer> limitsMap,
|
||||
final Optional<JsonRpcManager> rejectedTxJsonRpcManager,
|
||||
final Optional<HistogramMetrics> maybeProfitabilityMetrics,
|
||||
final BundlePoolService bundlePoolService) {
|
||||
@@ -62,7 +59,6 @@ public class LineaTransactionSelectorFactory implements PluginTransactionSelecto
|
||||
this.l1L2BridgeConfiguration = l1L2BridgeConfiguration;
|
||||
this.profitabilityConfiguration = profitabilityConfiguration;
|
||||
this.tracerConfiguration = tracerConfiguration;
|
||||
this.limitsMap = limitsMap;
|
||||
this.rejectedTxJsonRpcManager = rejectedTxJsonRpcManager;
|
||||
this.maybeProfitabilityMetrics = maybeProfitabilityMetrics;
|
||||
this.bundlePoolService = bundlePoolService;
|
||||
@@ -79,7 +75,6 @@ public class LineaTransactionSelectorFactory implements PluginTransactionSelecto
|
||||
profitabilityConfiguration,
|
||||
tracerConfiguration,
|
||||
bundlePoolService,
|
||||
limitsMap,
|
||||
rejectedTxJsonRpcManager,
|
||||
maybeProfitabilityMetrics);
|
||||
currSelector.set(selector);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
package net.consensys.linea.sequencer.txselection;
|
||||
|
||||
import static net.consensys.linea.metrics.LineaMetricCategory.SEQUENCER_PROFITABILITY;
|
||||
import static net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator.createLimitModules;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import java.util.Optional;
|
||||
@@ -90,7 +89,6 @@ public class LineaTransactionSelectorPlugin extends AbstractLineaRequiredPlugin
|
||||
l1L2BridgeSharedConfiguration(),
|
||||
profitabilityConfiguration(),
|
||||
tracerConfiguration(),
|
||||
createLimitModules(tracerConfiguration()),
|
||||
rejectedTxJsonRpcManager,
|
||||
maybeProfitabilityMetrics,
|
||||
bundlePoolService));
|
||||
|
||||
@@ -14,7 +14,6 @@ import static net.consensys.linea.sequencer.txselection.LineaTransactionSelectio
|
||||
import java.time.Instant;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -27,7 +26,7 @@ import net.consensys.linea.jsonrpc.JsonRpcManager;
|
||||
import net.consensys.linea.jsonrpc.JsonRpcRequestBuilder;
|
||||
import net.consensys.linea.metrics.HistogramMetrics;
|
||||
import net.consensys.linea.plugins.config.LineaL1L2BridgeSharedConfiguration;
|
||||
import net.consensys.linea.zktracer.ZkTracer;
|
||||
import net.consensys.linea.zktracer.LineCountingTracer;
|
||||
import org.hyperledger.besu.plugin.data.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
|
||||
import org.hyperledger.besu.plugin.services.BlockchainService;
|
||||
@@ -52,7 +51,6 @@ public class LineaTransactionSelector implements PluginTransactionSelector {
|
||||
final LineaProfitabilityConfiguration profitabilityConfiguration,
|
||||
final LineaTracerConfiguration tracerConfiguration,
|
||||
final BundlePoolService bundlePoolService,
|
||||
final Map<String, Integer> limitsMap,
|
||||
final Optional<JsonRpcManager> rejectedTxJsonRpcManager,
|
||||
final Optional<HistogramMetrics> maybeProfitabilityMetrics) {
|
||||
this.rejectedTxJsonRpcManager = rejectedTxJsonRpcManager;
|
||||
@@ -72,7 +70,6 @@ public class LineaTransactionSelector implements PluginTransactionSelector {
|
||||
profitabilityConfiguration,
|
||||
tracerConfiguration,
|
||||
bundlePoolService,
|
||||
limitsMap,
|
||||
maybeProfitabilityMetrics);
|
||||
}
|
||||
|
||||
@@ -97,14 +94,12 @@ public class LineaTransactionSelector implements PluginTransactionSelector {
|
||||
final LineaProfitabilityConfiguration profitabilityConfiguration,
|
||||
final LineaTracerConfiguration tracerConfiguration,
|
||||
final BundlePoolService bundlePoolService,
|
||||
final Map<String, Integer> limitsMap,
|
||||
final Optional<HistogramMetrics> maybeProfitabilityMetrics) {
|
||||
|
||||
traceLineLimitTransactionSelector =
|
||||
new TraceLineLimitTransactionSelector(
|
||||
selectorsStateManager,
|
||||
blockchainService.getChainId().get(),
|
||||
limitsMap,
|
||||
txSelectorConfiguration,
|
||||
l1L2BridgeConfiguration,
|
||||
tracerConfiguration);
|
||||
@@ -229,7 +224,7 @@ public class LineaTransactionSelector implements PluginTransactionSelector {
|
||||
* @return the operation tracer
|
||||
*/
|
||||
@Override
|
||||
public ZkTracer getOperationTracer() {
|
||||
public LineCountingTracer getOperationTracer() {
|
||||
return traceLineLimitTransactionSelector.getOperationTracer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,14 @@ import static net.consensys.linea.sequencer.txselection.LineaTransactionSelectio
|
||||
import static net.consensys.linea.sequencer.txselection.LineaTransactionSelectionResult.TX_MODULE_LINE_COUNT_OVERFLOW;
|
||||
import static net.consensys.linea.sequencer.txselection.LineaTransactionSelectionResult.TX_MODULE_LINE_COUNT_OVERFLOW_CACHED;
|
||||
import static net.consensys.linea.sequencer.txselection.LineaTransactionSelectionResult.TX_MODULE_LINE_INVALID_COUNT;
|
||||
import static net.consensys.linea.zktracer.Fork.LONDON;
|
||||
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.math.BigInteger;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -28,12 +29,24 @@ import net.consensys.linea.config.LineaTransactionSelectorConfiguration;
|
||||
import net.consensys.linea.plugins.config.LineaL1L2BridgeSharedConfiguration;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLimitsValidationResult;
|
||||
import net.consensys.linea.sequencer.modulelimit.ModuleLineCountValidator;
|
||||
import net.consensys.linea.zktracer.Fork;
|
||||
import net.consensys.linea.zktracer.LineCountingTracer;
|
||||
import net.consensys.linea.zktracer.ZkCounter;
|
||||
import net.consensys.linea.zktracer.ZkTracer;
|
||||
import net.consensys.linea.zktracer.container.module.Module;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Transaction;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||
import org.hyperledger.besu.evm.log.Log;
|
||||
import org.hyperledger.besu.evm.operation.Operation;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldView;
|
||||
import org.hyperledger.besu.plugin.data.BlockBody;
|
||||
import org.hyperledger.besu.plugin.data.BlockHeader;
|
||||
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
|
||||
import org.hyperledger.besu.plugin.data.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
|
||||
import org.hyperledger.besu.plugin.services.txselection.AbstractStatefulPluginTransactionSelector;
|
||||
@@ -52,39 +65,39 @@ public class TraceLineLimitTransactionSelector
|
||||
extends AbstractStatefulPluginTransactionSelector<Map<String, Integer>> {
|
||||
private static final Marker BLOCK_LINE_COUNT_MARKER = MarkerFactory.getMarker("BLOCK_LINE_COUNT");
|
||||
@VisibleForTesting protected static Set<Hash> overLineCountLimitCache = new LinkedHashSet<>();
|
||||
private final ZkTracer zkTracer;
|
||||
private final LineaTracerConfiguration tracerConfiguration;
|
||||
private final LineCountingTracer lineCountingTracer;
|
||||
private final BigInteger chainId;
|
||||
private final String limitFilePath;
|
||||
private final Map<String, Integer> moduleLimits;
|
||||
private final int overLimitCacheSize;
|
||||
private final ModuleLineCountValidator moduleLineCountValidator;
|
||||
|
||||
public TraceLineLimitTransactionSelector(
|
||||
final SelectorsStateManager stateManager,
|
||||
final BigInteger chainId,
|
||||
final Map<String, Integer> moduleLimits,
|
||||
final LineaTransactionSelectorConfiguration txSelectorConfiguration,
|
||||
final LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration,
|
||||
final LineaTracerConfiguration tracerConfiguration) {
|
||||
super(
|
||||
stateManager,
|
||||
moduleLimits.keySet().stream().collect(Collectors.toMap(Function.identity(), unused -> 0)),
|
||||
tracerConfiguration.moduleLimitsMap().keySet().stream()
|
||||
.collect(Collectors.toMap(Function.identity(), unused -> 0)),
|
||||
Map::copyOf);
|
||||
|
||||
this.chainId = chainId;
|
||||
this.moduleLimits = moduleLimits;
|
||||
this.limitFilePath = tracerConfiguration.moduleLimitsFilePath();
|
||||
this.tracerConfiguration = tracerConfiguration;
|
||||
this.overLimitCacheSize = txSelectorConfiguration.overLinesLimitCacheSize();
|
||||
|
||||
zkTracer = new ZkTracerWithLog(l1L2BridgeConfiguration);
|
||||
for (Module m : zkTracer.getHub().getModulesToCount()) {
|
||||
if (!moduleLimits.containsKey(m.moduleKey())) {
|
||||
lineCountingTracer =
|
||||
new LineCountingTracerWithLog(tracerConfiguration, l1L2BridgeConfiguration);
|
||||
for (Module m : lineCountingTracer.getModulesToCount()) {
|
||||
if (!tracerConfiguration.moduleLimitsMap().containsKey(m.moduleKey())) {
|
||||
throw new IllegalStateException(
|
||||
"Limit for module %s not defined in %s".formatted(m.moduleKey(), this.limitFilePath));
|
||||
"Limit for module %s not defined in %s"
|
||||
.formatted(m.moduleKey(), tracerConfiguration.moduleLimitsFilePath()));
|
||||
}
|
||||
}
|
||||
zkTracer.traceStartConflation(1L);
|
||||
moduleLineCountValidator = new ModuleLineCountValidator(moduleLimits);
|
||||
lineCountingTracer.traceStartConflation(1L);
|
||||
moduleLineCountValidator = new ModuleLineCountValidator(tracerConfiguration.moduleLimitsMap());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +138,7 @@ public class TraceLineLimitTransactionSelector
|
||||
final var prevCumulatedLineCountMap = getWorkingState();
|
||||
|
||||
// check that we are not exceeding line number for any module
|
||||
final var newCumulatedLineCountMap = zkTracer.getModulesLineCount();
|
||||
final var newCumulatedLineCountMap = lineCountingTracer.getModulesLineCount();
|
||||
final Transaction transaction = evaluationContext.getPendingTransaction().getTransaction();
|
||||
log.atTrace()
|
||||
.setMessage("Tx {} line count per module: {}")
|
||||
@@ -176,8 +189,8 @@ public class TraceLineLimitTransactionSelector
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZkTracer getOperationTracer() {
|
||||
return zkTracer;
|
||||
public LineCountingTracer getOperationTracer() {
|
||||
return lineCountingTracer;
|
||||
}
|
||||
|
||||
private void rememberOverLineCountLimitTransaction(final Transaction transaction) {
|
||||
@@ -208,18 +221,25 @@ public class TraceLineLimitTransactionSelector
|
||||
+ "/"
|
||||
+ e.getValue()
|
||||
+ "/"
|
||||
+ moduleLimits.get(e.getKey()))
|
||||
+ tracerConfiguration.moduleLimitsMap().get(e.getKey()))
|
||||
.collect(Collectors.joining(",", "[", "]"));
|
||||
}
|
||||
|
||||
private class ZkTracerWithLog extends ZkTracer {
|
||||
public ZkTracerWithLog(final LineaL1L2BridgeSharedConfiguration bridgeConfiguration) {
|
||||
super(LONDON, bridgeConfiguration, chainId);
|
||||
private class LineCountingTracerWithLog implements LineCountingTracer {
|
||||
private final LineCountingTracer delegate;
|
||||
|
||||
public LineCountingTracerWithLog(
|
||||
final LineaTracerConfiguration tracerConfiguration,
|
||||
final LineaL1L2BridgeSharedConfiguration bridgeConfiguration) {
|
||||
this.delegate =
|
||||
tracerConfiguration.isLimitless()
|
||||
? new ZkCounter(bridgeConfiguration)
|
||||
: new ZkTracer(Fork.LONDON, bridgeConfiguration, chainId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceEndBlock(final BlockHeader blockHeader, final BlockBody blockBody) {
|
||||
super.traceEndBlock(blockHeader, blockBody);
|
||||
delegate.traceEndBlock(blockHeader, blockBody);
|
||||
log.atDebug()
|
||||
.addMarker(BLOCK_LINE_COUNT_MARKER)
|
||||
.addKeyValue("blockNumber", blockHeader::getNumber)
|
||||
@@ -233,5 +253,120 @@ public class TraceLineLimitTransactionSelector
|
||||
.collect(Collectors.joining(",")))
|
||||
.log();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popTransactionBundle() {
|
||||
delegate.popTransactionBundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitTransactionBundle() {
|
||||
delegate.commitTransactionBundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> getModulesLineCount() {
|
||||
return delegate.getModulesLineCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Module> getModulesToCount() {
|
||||
return delegate.getModulesToCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceStartConflation(final long l) {
|
||||
delegate.traceStartConflation(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceEndConflation(final WorldView worldView) {
|
||||
delegate.traceEndConflation(worldView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceStartBlock(
|
||||
final BlockHeader blockHeader, final BlockBody blockBody, final Address miningBeneficiary) {
|
||||
delegate.traceStartBlock(blockHeader, blockBody, miningBeneficiary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceStartBlock(
|
||||
final ProcessableBlockHeader processableBlockHeader, final Address miningBeneficiary) {
|
||||
delegate.traceStartBlock(processableBlockHeader, miningBeneficiary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExtendedTracing() {
|
||||
return delegate.isExtendedTracing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tracePreExecution(final MessageFrame frame) {
|
||||
delegate.tracePreExecution(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tracePostExecution(
|
||||
final MessageFrame frame, final Operation.OperationResult operationResult) {
|
||||
delegate.tracePostExecution(frame, operationResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tracePrecompileCall(
|
||||
final MessageFrame frame, final long gasRequirement, final Bytes output) {
|
||||
delegate.tracePrecompileCall(frame, gasRequirement, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceAccountCreationResult(
|
||||
final MessageFrame frame, final Optional<ExceptionalHaltReason> haltReason) {
|
||||
delegate.traceAccountCreationResult(frame, haltReason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tracePrepareTransaction(final WorldView worldView, final Transaction transaction) {
|
||||
delegate.tracePrepareTransaction(worldView, transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceStartTransaction(final WorldView worldView, final Transaction transaction) {
|
||||
delegate.traceStartTransaction(worldView, transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceBeforeRewardTransaction(
|
||||
final WorldView worldView, final Transaction tx, final Wei miningReward) {
|
||||
delegate.traceBeforeRewardTransaction(worldView, tx, miningReward);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceEndTransaction(
|
||||
final WorldView worldView,
|
||||
final Transaction tx,
|
||||
final boolean status,
|
||||
final Bytes output,
|
||||
final List<Log> logs,
|
||||
final long gasUsed,
|
||||
final Set<Address> selfDestructs,
|
||||
final long timeNs) {
|
||||
delegate.traceEndTransaction(
|
||||
worldView, tx, status, output, logs, gasUsed, selfDestructs, timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceContextEnter(final MessageFrame frame) {
|
||||
delegate.traceContextEnter(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceContextReEnter(final MessageFrame frame) {
|
||||
delegate.traceContextReEnter(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traceContextExit(final MessageFrame frame) {
|
||||
delegate.traceContextExit(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -96,11 +95,10 @@ public class SimulationValidatorTest {
|
||||
curve.getN());
|
||||
}
|
||||
|
||||
private Map<String, Integer> lineCountLimits;
|
||||
|
||||
@Mock BlockchainService blockchainService;
|
||||
@Mock TransactionSimulationService transactionSimulationService;
|
||||
private JsonRpcManager jsonRpcManager;
|
||||
private LineaTracerConfiguration tracerConfiguration;
|
||||
@TempDir private Path tempDataDir;
|
||||
@TempDir static Path tempDir;
|
||||
static Path lineLimitsConfPath;
|
||||
@@ -116,11 +114,14 @@ public class SimulationValidatorTest {
|
||||
|
||||
@BeforeEach
|
||||
public void initialize(final WireMockRuntimeInfo wmInfo) throws MalformedURLException {
|
||||
final var tracerConf =
|
||||
tracerConfiguration =
|
||||
LineaTracerConfiguration.builder()
|
||||
.moduleLimitsFilePath(lineLimitsConfPath.toString())
|
||||
.moduleLimitsMap(
|
||||
new HashMap<>(
|
||||
ModuleLineCountValidator.createLimitModules(lineLimitsConfPath.toString())))
|
||||
.isLimitless(false)
|
||||
.build();
|
||||
lineCountLimits = new HashMap<>(ModuleLineCountValidator.createLimitModules(tracerConf));
|
||||
final var pendingBlockHeader = mock(BlockHeader.class);
|
||||
when(pendingBlockHeader.getBaseFee()).thenReturn(Optional.of(BASE_FEE));
|
||||
when(pendingBlockHeader.getCoinbase()).thenReturn(Address.ZERO);
|
||||
@@ -152,9 +153,7 @@ public class SimulationValidatorTest {
|
||||
}
|
||||
|
||||
private SimulationValidator createSimulationValidator(
|
||||
final Map<String, Integer> lineCountLimits,
|
||||
final boolean enableForApi,
|
||||
final boolean enableForP2p) {
|
||||
final boolean enableForApi, final boolean enableForP2p) {
|
||||
return new SimulationValidator(
|
||||
blockchainService,
|
||||
transactionSimulationService,
|
||||
@@ -162,7 +161,7 @@ public class SimulationValidatorTest {
|
||||
.txPoolSimulationCheckApiEnabled(enableForApi)
|
||||
.txPoolSimulationCheckP2pEnabled(enableForP2p)
|
||||
.build(),
|
||||
lineCountLimits,
|
||||
tracerConfiguration,
|
||||
LineaL1L2BridgeSharedConfiguration.builder()
|
||||
.contract(BRIDGE_CONTRACT)
|
||||
.topic(BRIDGE_LOG_TOPIC)
|
||||
@@ -172,7 +171,7 @@ public class SimulationValidatorTest {
|
||||
|
||||
@Test
|
||||
public void successfulTransactionIsValid() {
|
||||
final var simulationValidator = createSimulationValidator(lineCountLimits, true, false);
|
||||
final var simulationValidator = createSimulationValidator(true, false);
|
||||
final org.hyperledger.besu.ethereum.core.Transaction transaction =
|
||||
org.hyperledger.besu.ethereum.core.Transaction.builder()
|
||||
.sender(SENDER)
|
||||
@@ -188,8 +187,8 @@ public class SimulationValidatorTest {
|
||||
|
||||
@Test
|
||||
public void moduleLineCountOverflowTransactionIsInvalidAndReported() {
|
||||
lineCountLimits.put("EXT", 5);
|
||||
final var simulationValidator = createSimulationValidator(lineCountLimits, true, false);
|
||||
tracerConfiguration.moduleLimitsMap().put("EXT", 5);
|
||||
final var simulationValidator = createSimulationValidator(true, false);
|
||||
final org.hyperledger.besu.ethereum.core.Transaction transaction =
|
||||
org.hyperledger.besu.ethereum.core.Transaction.builder()
|
||||
.sender(SENDER)
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import net.consensys.linea.bundles.BundlePoolService;
|
||||
@@ -67,7 +66,6 @@ class LineaTransactionSelectorFactoryTest {
|
||||
private LineaTransactionSelectorConfiguration mockTxSelectorConfiguration;
|
||||
private LineaL1L2BridgeSharedConfiguration l1L2BridgeConfiguration;
|
||||
private LineaProfitabilityConfiguration mockProfitabilityConfiguration;
|
||||
private Map<String, Integer> lineCountLimits;
|
||||
private BesuEvents mockEvents;
|
||||
private LineaLimitedBundlePool bundlePool;
|
||||
private BundlePoolService mockBundlePool;
|
||||
@@ -92,9 +90,11 @@ class LineaTransactionSelectorFactoryTest {
|
||||
lineaTracerConfiguration =
|
||||
LineaTracerConfiguration.builder()
|
||||
.moduleLimitsFilePath(lineLimitsConfPath.toString())
|
||||
.moduleLimitsMap(
|
||||
new HashMap<>(
|
||||
ModuleLineCountValidator.createLimitModules(lineLimitsConfPath.toString())))
|
||||
.isLimitless(false)
|
||||
.build();
|
||||
lineCountLimits =
|
||||
new HashMap<>(ModuleLineCountValidator.createLimitModules(lineaTracerConfiguration));
|
||||
|
||||
mockBlockchainService = mock(BlockchainService.class);
|
||||
when(mockBlockchainService.getChainId()).thenReturn(Optional.of(BigInteger.ONE));
|
||||
@@ -113,7 +113,6 @@ class LineaTransactionSelectorFactoryTest {
|
||||
l1L2BridgeConfiguration,
|
||||
mockProfitabilityConfiguration,
|
||||
lineaTracerConfiguration,
|
||||
lineCountLimits,
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
bundlePool);
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.math.BigInteger;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import net.consensys.linea.config.LineaTracerConfiguration;
|
||||
import net.consensys.linea.config.LineaTransactionSelectorConfiguration;
|
||||
import net.consensys.linea.plugins.config.LineaL1L2BridgeSharedConfiguration;
|
||||
@@ -45,8 +44,7 @@ import org.junit.jupiter.api.io.TempDir;
|
||||
public class TraceLineLimitTransactionSelectorTest {
|
||||
private static final int OVER_LINE_COUNT_LIMIT_CACHE_SIZE = 2;
|
||||
private static final String MODULE_LINE_LIMITS_RESOURCE_NAME = "/sequencer/line-limits.toml";
|
||||
private Map<String, Integer> lineCountLimits;
|
||||
private LineaTracerConfiguration lineaTracerConfiguration;
|
||||
private LineaTracerConfiguration tracerConfiguration;
|
||||
private SelectorsStateManager selectorsStateManager;
|
||||
|
||||
@TempDir static Path tempDir;
|
||||
@@ -63,30 +61,27 @@ public class TraceLineLimitTransactionSelectorTest {
|
||||
|
||||
@BeforeEach
|
||||
public void initialize() {
|
||||
lineaTracerConfiguration =
|
||||
tracerConfiguration =
|
||||
LineaTracerConfiguration.builder()
|
||||
.moduleLimitsFilePath(lineLimitsConfPath.toString())
|
||||
.moduleLimitsMap(
|
||||
new HashMap<>(
|
||||
ModuleLineCountValidator.createLimitModules(lineLimitsConfPath.toString())))
|
||||
.build();
|
||||
lineCountLimits =
|
||||
new HashMap<>(ModuleLineCountValidator.createLimitModules(lineaTracerConfiguration));
|
||||
}
|
||||
|
||||
private TestableTraceLineLimitTransactionSelector newSelectorForNewBlock(
|
||||
final Map<String, Integer> lineCountLimits) {
|
||||
private TestableTraceLineLimitTransactionSelector newSelectorForNewBlock() {
|
||||
selectorsStateManager = new SelectorsStateManager();
|
||||
final var selector =
|
||||
new TestableTraceLineLimitTransactionSelector(
|
||||
selectorsStateManager,
|
||||
lineaTracerConfiguration,
|
||||
lineCountLimits,
|
||||
OVER_LINE_COUNT_LIMIT_CACHE_SIZE);
|
||||
selectorsStateManager, tracerConfiguration, OVER_LINE_COUNT_LIMIT_CACHE_SIZE);
|
||||
selectorsStateManager.blockSelectionStarted();
|
||||
return selector;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSelectWhenBelowLimits() {
|
||||
final var transactionSelector = newSelectorForNewBlock(lineCountLimits);
|
||||
final var transactionSelector = newSelectorForNewBlock();
|
||||
transactionSelector.resetCache();
|
||||
|
||||
final var evaluationContext =
|
||||
@@ -105,8 +100,8 @@ public class TraceLineLimitTransactionSelectorTest {
|
||||
|
||||
@Test
|
||||
public void shouldNotSelectWhenOverLimits() {
|
||||
lineCountLimits.put("EXT", 5);
|
||||
final var transactionSelector = newSelectorForNewBlock(lineCountLimits);
|
||||
tracerConfiguration.moduleLimitsMap().put("EXT", 5);
|
||||
final var transactionSelector = newSelectorForNewBlock();
|
||||
transactionSelector.resetCache();
|
||||
|
||||
final var evaluationContext =
|
||||
@@ -125,8 +120,8 @@ public class TraceLineLimitTransactionSelectorTest {
|
||||
|
||||
@Test
|
||||
public void shouldNotReprocessedWhenOverLimits() {
|
||||
lineCountLimits.put("EXT", 5);
|
||||
var transactionSelector = newSelectorForNewBlock(lineCountLimits);
|
||||
tracerConfiguration.moduleLimitsMap().put("EXT", 5);
|
||||
var transactionSelector = newSelectorForNewBlock();
|
||||
transactionSelector.resetCache();
|
||||
|
||||
var evaluationContext =
|
||||
@@ -142,7 +137,7 @@ public class TraceLineLimitTransactionSelectorTest {
|
||||
transactionSelector.isOverLineCountLimitTxCached(
|
||||
evaluationContext.getPendingTransaction().getTransaction().getHash()))
|
||||
.isTrue();
|
||||
transactionSelector = newSelectorForNewBlock(lineCountLimits);
|
||||
transactionSelector = newSelectorForNewBlock();
|
||||
assertThat(
|
||||
transactionSelector.isOverLineCountLimitTxCached(
|
||||
evaluationContext.getPendingTransaction().getTransaction().getHash()))
|
||||
@@ -162,8 +157,8 @@ public class TraceLineLimitTransactionSelectorTest {
|
||||
|
||||
@Test
|
||||
public void shouldEvictWhenCacheIsFull() {
|
||||
lineCountLimits.put("EXT", 5);
|
||||
final var transactionSelector = newSelectorForNewBlock(lineCountLimits);
|
||||
tracerConfiguration.moduleLimitsMap().put("EXT", 5);
|
||||
final var transactionSelector = newSelectorForNewBlock();
|
||||
transactionSelector.resetCache();
|
||||
|
||||
final TestTransactionEvaluationContext[] evaluationContexts =
|
||||
@@ -253,12 +248,10 @@ public class TraceLineLimitTransactionSelectorTest {
|
||||
TestableTraceLineLimitTransactionSelector(
|
||||
final SelectorsStateManager selectorsStateManager,
|
||||
final LineaTracerConfiguration lineaTracerConfiguration,
|
||||
final Map<String, Integer> moduleLimits,
|
||||
final int overLimitCacheSize) {
|
||||
super(
|
||||
selectorsStateManager,
|
||||
BigInteger.ONE,
|
||||
moduleLimits,
|
||||
LineaTransactionSelectorConfiguration.builder()
|
||||
.overLinesLimitCacheSize(overLimitCacheSize)
|
||||
.build(),
|
||||
|
||||
Reference in New Issue
Block a user