Skip to content

Commit

Permalink
Coordinator: Shared State Manager Client (#233)
Browse files Browse the repository at this point in the history
* add state-manager client (C&P) from coordinator one for now
  • Loading branch information
jpnovais authored Oct 23, 2024
1 parent 9c6497f commit baffb9c
Show file tree
Hide file tree
Showing 6 changed files with 434 additions and 1 deletion.
1 change: 0 additions & 1 deletion jvm-libs/linea/blob-decompressor/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ task cleanResources(type: Delete) {
.filter {
it.name.endsWith(".so") || it.name.endsWith(".dll") || it.name.endsWith(".dylib")
}.each {
println("Deleting: ${it}")
delete it
}
}
Expand Down
22 changes: 22 additions & 0 deletions jvm-libs/linea/clients/linea-state-manager/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
plugins {
id 'net.consensys.zkevm.kotlin-library-conventions'
}

dependencies {
api project(':jvm-libs:linea:core:domain-models')
api project(':jvm-libs:linea:core:metrics')
api project(':jvm-libs:linea:core:client-interface')
api project(':jvm-libs:generic:json-rpc')
api project(':jvm-libs:generic:errors')
api project(':jvm-libs:generic:extensions:futures')
api project(':jvm-libs:generic:extensions:kotlin')
api "io.tmio:tuweni-bytes:${libs.versions.tuweni.get()}"

implementation "com.fasterxml.jackson.core:jackson-annotations:${libs.versions.jackson.get()}"
implementation "com.fasterxml.jackson.core:jackson-databind:${libs.versions.jackson.get()}"
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:${libs.versions.jackson.get()}"

testImplementation(project(":jvm-libs:linea:testing:file-system"))
testImplementation "io.vertx:vertx-junit5"
testImplementation "com.github.tomakehurst:wiremock-jre8:${libs.versions.wiremock.get()}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package build.linea.clients

import build.linea.domain.BlockInterval
import com.fasterxml.jackson.databind.node.ArrayNode
import com.github.michaelbull.result.Result
import net.consensys.encodeHex
import net.consensys.linea.errors.ErrorResponse
import tech.pegasys.teku.infrastructure.async.SafeFuture

enum class StateManagerErrorType : ClientError {
UNKNOWN,
UNSUPPORTED_VERSION,
BLOCK_MISSING_IN_CHAIN
}

sealed interface StateManagerRequest
sealed class GetChainHeadRequest() : StateManagerRequest
data class GetStateMerkleProofRequest(
val blockInterval: BlockInterval
) : StateManagerRequest, BlockInterval by blockInterval

sealed interface StateManagerResponse

data class GetZkEVMStateMerkleProofResponse(
val zkStateMerkleProof: ArrayNode,
val zkParentStateRootHash: ByteArray,
val zkEndStateRootHash: ByteArray,
val zkStateManagerVersion: String
) : StateManagerResponse {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as GetZkEVMStateMerkleProofResponse

if (zkStateMerkleProof != other.zkStateMerkleProof) return false
if (!zkParentStateRootHash.contentEquals(other.zkParentStateRootHash)) return false
if (!zkEndStateRootHash.contentEquals(other.zkEndStateRootHash)) return false
if (zkStateManagerVersion != other.zkStateManagerVersion) return false

return true
}

override fun hashCode(): Int {
var result = zkStateMerkleProof.hashCode()
result = 31 * result + zkParentStateRootHash.contentHashCode()
result = 31 * result + zkEndStateRootHash.contentHashCode()
result = 31 * result + zkStateManagerVersion.hashCode()
return result
}

override fun toString(): String {
return "GetZkEVMStateMerkleProofResponse(" +
"zkStateMerkleProof=$zkStateMerkleProof, zkParentStateRootHash=${zkParentStateRootHash.encodeHex()}, " +
"zkEndStateRootHash=${zkEndStateRootHash.encodeHex()}, " +
"zkStateManagerVersion='$zkStateManagerVersion')"
}
}

// Type alias dedicated for each method
typealias StateManagerClientToGetStateMerkleProofV0 =
AsyncClient<GetStateMerkleProofRequest, GetZkEVMStateMerkleProofResponse>

typealias StateManagerClientToGetChainHeadV1 =
AsyncClient<GetChainHeadRequest, ULong>

interface StateManagerClientV1 {
/**
* Get the head block number of the chain.
* @return GetZkEVMStateMerkleProofResponse
* @throws ClientException with errorType StateManagerErrorType when know error occurs
*/
fun rollupGetStateMerkleProof(
blockInterval: BlockInterval
): SafeFuture<GetZkEVMStateMerkleProofResponse> = rollupGetStateMerkleProofWithTypedError(blockInterval)
.unwrapResultMonad()

/**
* This is for backward compatibility with the old version in the coordinator side.
* This error typing is not really usefull anymore
*/
fun rollupGetStateMerkleProofWithTypedError(
blockInterval: BlockInterval
): SafeFuture<Result<GetZkEVMStateMerkleProofResponse, ErrorResponse<StateManagerErrorType>>>

fun rollupGetHeadBlockNumber(): SafeFuture<ULong>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package build.linea.clients

import build.linea.domain.BlockInterval
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.node.ArrayNode
import com.github.michaelbull.result.Err
import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.Result
import io.vertx.core.json.JsonObject
import net.consensys.decodeHex
import net.consensys.fromHexString
import net.consensys.linea.errors.ErrorResponse
import net.consensys.linea.jsonrpc.JsonRpcErrorResponseException
import net.consensys.linea.jsonrpc.client.JsonRpcV2Client
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import tech.pegasys.teku.infrastructure.async.SafeFuture

class StateManagerV1JsonRpcClient(
private val rpcClient: JsonRpcV2Client,
private val zkStateManagerVersion: String
) : StateManagerClientV1 {
private val log: Logger = LogManager.getLogger(this::class.java)

override fun rollupGetHeadBlockNumber(): SafeFuture<ULong> {
return rpcClient
.makeRequest(
method = "rollup_getZkEVMBlockNumber",
params = emptyList<Unit>(),
shallRetryRequestPredicate = { it is Err },
resultMapper = { ULong.fromHexString(it as String) }
)
}

override fun rollupGetStateMerkleProof(blockInterval: BlockInterval): SafeFuture<GetZkEVMStateMerkleProofResponse> {
val params = listOf(
JsonObject.of(
"startBlockNumber",
blockInterval.startBlockNumber.toLong(),
"endBlockNumber",
blockInterval.endBlockNumber.toLong(),
"zkStateManagerVersion",
zkStateManagerVersion
)
)

return rpcClient
.makeRequest(
method = "rollup_getZkEVMStateMerkleProofV0",
params = params,
shallRetryRequestPredicate = { it is Err },
resultMapper = { it as JsonNode; parseZkEVMStateMerkleProofResponse(it) }
)
}

override fun rollupGetStateMerkleProofWithTypedError(
blockInterval: BlockInterval
): SafeFuture<Result<GetZkEVMStateMerkleProofResponse, ErrorResponse<StateManagerErrorType>>> {
return rollupGetStateMerkleProof(blockInterval)
.handleComposed { result, th ->
if (th != null) {
if (th is JsonRpcErrorResponseException) {
SafeFuture.completedFuture(Err(mapErrorResponse(th)))
} else {
SafeFuture.failedFuture(th)
}
} else {
SafeFuture.completedFuture(Ok(result))
}
}
}

private fun mapErrorResponse(
jsonRpcErrorResponse: JsonRpcErrorResponseException
): ErrorResponse<StateManagerErrorType> {
val errorType =
try {
StateManagerErrorType.valueOf(
jsonRpcErrorResponse.rpcErrorMessage.substringBefore('-').trim()
)
} catch (_: Exception) {
log.error(
"State manager found unrecognised JSON-RPC response error: {}",
jsonRpcErrorResponse.rpcErrorMessage
)
StateManagerErrorType.UNKNOWN
}

return ErrorResponse(
errorType,
listOfNotNull(
jsonRpcErrorResponse.rpcErrorMessage,
jsonRpcErrorResponse.rpcErrorData?.toString()
)
.joinToString(": ")
)
}

private fun parseZkEVMStateMerkleProofResponse(
result: JsonNode
): GetZkEVMStateMerkleProofResponse {
return GetZkEVMStateMerkleProofResponse(
zkStateManagerVersion = result.get("zkStateManagerVersion").asText(),
zkStateMerkleProof = result.get("zkStateMerkleProof") as ArrayNode,
zkParentStateRootHash = result.get("zkParentStateRootHash").asText().decodeHex(),
zkEndStateRootHash = result.get("zkEndStateRootHash").asText().decodeHex()
)
}
}
Loading

0 comments on commit baffb9c

Please sign in to comment.