Skip to content

Commit

Permalink
Merge branch 'main' into feat/196-validate-natspec
Browse files Browse the repository at this point in the history
  • Loading branch information
thedarkjester authored Oct 18, 2024
2 parents 2fd5665 + 74529e6 commit 2f5ed90
Show file tree
Hide file tree
Showing 26 changed files with 968 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class ProofToFinalizeJsonResponseTest {
val jsonParser = jsonNode.traverse()
while (!jsonParser.isClosed) {
if (jsonParser.nextToken() == JsonToken.FIELD_NAME) {
keys.add(jsonParser.currentName)
keys.add(jsonParser.currentName())
}
}
return keys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@ package net.consensys.zkevm.ethereum.submission

import org.apache.logging.log4j.Logger

private const val insufficientGasFeeRegexStr =
"(max fee per (blob )?gas less than block (blob gas|base) fee:" +
" address 0x[a-fA-F0-9]{40},? (blobGasFeeCap|maxFeePerGas): [0-9]+," +
" (blobBaseFee|baseFee): [0-9]+ \\(supplied gas [0-9]+\\))"

private val insufficientGasFeeRegex = Regex(insufficientGasFeeRegexStr)
private val maxFeePerBlobGasRegex = Regex("max fee per blob gas|blobGasFeeCap")

private fun rewriteInsufficientGasFeeErrorMessage(errorMessage: String): String? {
return insufficientGasFeeRegex.find(errorMessage)?.groupValues?.first()
?.replace("max fee per gas", "maxFeePerGas")
?.replace(maxFeePerBlobGasRegex, "maxFeePerBlobGas")
}

fun logUnhandledError(
log: Logger,
errorOrigin: String,
Expand Down Expand Up @@ -30,13 +44,32 @@ fun logSubmissionError(
error: Throwable,
isEthCall: Boolean = false
) {
var matchedInsufficientGasFeeRegex = false
val ethMethod = if (isEthCall) "eth_call" else "eth_sendRawTransaction"
val errorMessage = if (isEthCall) {
error.message?.let {
rewriteInsufficientGasFeeErrorMessage(it)?.also {
matchedInsufficientGasFeeRegex = true
}
} ?: error.message
} else {
error.message
}

log.error(
logMessage,
ethMethod,
intervalString,
error.message,
error
)
if (matchedInsufficientGasFeeRegex) {
log.info(
logMessage,
ethMethod,
intervalString,
errorMessage
)
} else {
log.error(
logMessage,
ethMethod,
intervalString,
errorMessage,
error
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package net.consensys.zkevm.ethereum.submission

import org.apache.logging.log4j.Logger
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.mockito.Mockito.mock
import org.mockito.kotlin.eq
import org.mockito.kotlin.verify

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class LoggingHelperTest {
private lateinit var logger: Logger

private val blobSubmissionFailedLogMsg = "{} for blob submission failed: blob={} errorMessage={}"
private val blobSubmissionFailedIntervalStr = "[4025752..4031499]5748"
private val insufficientMaxFeePerBlobGasErrMsg = "org.web3j.tx.exceptions.ContractCallException:" +
" Contract Call has been reverted by the EVM with the reason:" +
" 'err: max fee per blob gas less than block blob gas fee:" +
" address 0x47C63d1E391FcB3dCdC40C4d7fA58ADb172f8c38 blobGasFeeCap: 1875810596," +
" blobBaseFee: 1962046498 (supplied gas 1000000)'. revertReason=UNKNOWN errorData=null"

private val insufficientMaxFeePerGasErrMsg = "org.web3j.tx.exceptions.ContractCallException:" +
" Contract Call has been reverted by the EVM with the reason:" +
" 'err: max fee per gas less than block base fee:" +
" address 0x47C63d1E391FcB3dCdC40C4d7fA58ADb172f8c38, maxFeePerGas: 300000000000," +
" baseFee: 302246075616 (supplied gas 1000000)'. revertReason=UNKNOWN errorData=null"

private val unknownErrMsg = "org.web3j.tx.exceptions.ContractCallException:" +
" Contract Call has been reverted by the EVM with the reason:" +
" 'err: unknown error:" +
" address 0x47C63d1E391FcB3dCdC40C4d7fA58ADb172f8c38'. revertReason=UNKNOWN errorData=null"

@BeforeEach
fun setUp() {
logger = mock()
}

@Test
fun `insufficient max fee per gas with isEthCall is true triggers rewrite info message`() {
val error = RuntimeException(insufficientMaxFeePerGasErrMsg)
logSubmissionError(
log = logger,
logMessage = blobSubmissionFailedLogMsg,
intervalString = blobSubmissionFailedIntervalStr,
error = error,
isEthCall = true
)
val expectedErrorMessage =
"maxFeePerGas less than block base fee:" +
" address 0x47C63d1E391FcB3dCdC40C4d7fA58ADb172f8c38, maxFeePerGas: 300000000000," +
" baseFee: 302246075616 (supplied gas 1000000)"

verify(logger).info(
eq(blobSubmissionFailedLogMsg),
eq("eth_call"),
eq(blobSubmissionFailedIntervalStr),
eq(expectedErrorMessage)
)
}

@Test
fun `insufficient max fee per blob gas with isEthCall is true triggers rewrite info message`() {
val error = RuntimeException(insufficientMaxFeePerBlobGasErrMsg)
logSubmissionError(
log = logger,
logMessage = blobSubmissionFailedLogMsg,
intervalString = blobSubmissionFailedIntervalStr,
error = error,
isEthCall = true
)
val expectedErrorMessage =
"maxFeePerBlobGas less than block blob gas fee:" +
" address 0x47C63d1E391FcB3dCdC40C4d7fA58ADb172f8c38 maxFeePerBlobGas: 1875810596," +
" blobBaseFee: 1962046498 (supplied gas 1000000)"

verify(logger).info(
eq(blobSubmissionFailedLogMsg),
eq("eth_call"),
eq(blobSubmissionFailedIntervalStr),
eq(expectedErrorMessage)
)
}

@Test
fun `insufficient max fee per gas with isEthCall is false do not trigger rewrite error message`() {
val error = RuntimeException(insufficientMaxFeePerGasErrMsg)
logSubmissionError(
log = logger,
logMessage = blobSubmissionFailedLogMsg,
intervalString = blobSubmissionFailedIntervalStr,
error = error,
isEthCall = false
)

verify(logger).error(
eq(blobSubmissionFailedLogMsg),
eq("eth_sendRawTransaction"),
eq(blobSubmissionFailedIntervalStr),
eq(insufficientMaxFeePerGasErrMsg),
eq(error)
)
}

@Test
fun `insufficient max fee per blob gas with isEthCall is false do not trigger rewrite error message`() {
val error = RuntimeException(insufficientMaxFeePerBlobGasErrMsg)
logSubmissionError(
log = logger,
logMessage = blobSubmissionFailedLogMsg,
intervalString = blobSubmissionFailedIntervalStr,
error = error,
isEthCall = false
)

verify(logger).error(
eq(blobSubmissionFailedLogMsg),
eq("eth_sendRawTransaction"),
eq(blobSubmissionFailedIntervalStr),
eq(insufficientMaxFeePerBlobGasErrMsg),
eq(error)
)
}

@Test
fun `Other error with isEthCall is true do not trigger rewrite error message`() {
val error = RuntimeException(unknownErrMsg)
logSubmissionError(
log = logger,
logMessage = blobSubmissionFailedLogMsg,
intervalString = blobSubmissionFailedIntervalStr,
error = error,
isEthCall = true
)

verify(logger).error(
eq(blobSubmissionFailedLogMsg),
eq("eth_call"),
eq(blobSubmissionFailedIntervalStr),
eq(unknownErrMsg),
eq(error)
)
}
}
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jreleaser = {id = "org.jreleaser", version = "1.13.1"}
besu = "22.4.2"
caffeine = "3.1.6"
hoplite = "2.7.5"
jackson = "2.14.2"
jackson = "2.18.0"
jna = "5.14.0"
junit = "5.10.1"
kotlinxDatetime = "0.4.0"
Expand All @@ -23,5 +23,6 @@ tuweni = "2.3.1"
vertx = "4.5.0"
web3j = "4.12.0"
wiremock = "3.0.1"
jsonUnit = "3.4.1"
blobCompressor = "0.0.4"
blobShnarfCalculator = "0.0.4"
13 changes: 13 additions & 0 deletions jvm-libs/generic/serialization/jackson/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
plugins {
id 'net.consensys.zkevm.kotlin-library-conventions'
}

dependencies {
implementation(project(':jvm-libs:kotlin-extensions'))
api "com.fasterxml.jackson.core:jackson-annotations:${libs.versions.jackson.get()}"
api "com.fasterxml.jackson.core:jackson-databind:${libs.versions.jackson.get()}"
api "com.fasterxml.jackson.module:jackson-module-kotlin:${libs.versions.jackson.get()}"
api "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${libs.versions.jackson.get()}"

testImplementation "net.javacrumbs.json-unit:json-unit-assertj:${libs.versions.jsonUnit.get()}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package build.linea.s11n.jackson

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import java.util.HexFormat

private val hexFormatter = HexFormat.of()

object ByteArrayToHexSerializer : JsonSerializer<ByteArray>() {
override fun serialize(value: ByteArray, gen: JsonGenerator, serializers: SerializerProvider?) {
gen.writeString("0x" + hexFormatter.formatHex(value))
}

override fun handledType(): Class<ByteArray> {
return ByteArray::class.java
}
}

object ByteToHexSerializer : JsonSerializer<Byte>() {
override fun serialize(value: Byte, gen: JsonGenerator, serializers: SerializerProvider?) {
gen.writeString("0x" + hexFormatter.toHexDigits(value))
}
}

object UByteToHexSerializer : JsonSerializer<UByte>() {
override fun serialize(value: UByte, gen: JsonGenerator, serializers: SerializerProvider?) {
gen.writeString("0x" + hexFormatter.toHexDigits(value.toByte()))
}
}

object ByteArrayToHexDeserializer : JsonDeserializer<ByteArray>() {
override fun deserialize(parser: JsonParser, contex: DeserializationContext): ByteArray {
return hexFormatter.parseHex(parser.text.removePrefix("0x"))
}
}

object ByteToHexDeserializer : JsonDeserializer<Byte>() {
override fun deserialize(parser: JsonParser, contex: DeserializationContext): Byte {
return hexFormatter.parseHex(parser.text.removePrefix("0x"))[0]
}
}

object UByteToHexDeserializer : JsonDeserializer<UByte>() {
override fun deserialize(parser: JsonParser, contex: DeserializationContext): UByte {
return hexFormatter.parseHex(parser.text.removePrefix("0x"))[0].toUByte()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package build.linea.s11n.jackson

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import kotlinx.datetime.Instant

object InstantISO8601Serializer : JsonSerializer<Instant>() {
override fun serialize(value: Instant, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeString(value.toString())
}
}

// To uncomment and add the tests when necessary
object InstantISO8601Deserializer : JsonDeserializer<Instant>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Instant {
return Instant.parse(p.text)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package build.linea.s11n.jackson

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import java.math.BigInteger

internal fun Number.toHex(): String = "0x" + BigInteger(toString()).toString(16)
internal fun ULong.toHex(): String = "0x" + BigInteger(toString()).toString(16)

object IntToHexSerializer : JsonSerializer<Int>() {
override fun serialize(value: Int, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeString(value.toHex())
}
}

@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
object JIntegerToHexSerializer : JsonSerializer<Integer>() {
override fun serialize(value: Integer, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeString(value.toHex())
}
}

object LongToHexSerializer : JsonSerializer<Long>() {
override fun serialize(value: Long, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeString(value.toHex())
}
}

@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
object JLongToHexSerializer : JsonSerializer<java.lang.Long>() {
override fun serialize(value: java.lang.Long, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeString(value.toHex())
}
}

object ULongToHexSerializer : JsonSerializer<ULong>() {
override fun serialize(value: ULong, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeString(value.toHex())
}
}

object BigIntegerToHexSerializer : JsonSerializer<BigInteger>() {
override fun serialize(value: BigInteger, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeString(value.toHex())
}
}
Loading

0 comments on commit 2f5ed90

Please sign in to comment.