diff --git a/bindings/java-bindings/.gitignore b/bindings/java-bindings/.gitignore new file mode 100644 index 000000000..b63da4551 --- /dev/null +++ b/bindings/java-bindings/.gitignore @@ -0,0 +1,42 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/bindings/java-bindings/build.gradle b/bindings/java-bindings/build.gradle new file mode 100644 index 000000000..ed41e9463 --- /dev/null +++ b/bindings/java-bindings/build.gradle @@ -0,0 +1,27 @@ +plugins { + id 'java' +} + +group = 'me.grapebaba' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + +dependencies { + testImplementation platform(testLibs.junit.bom) + testImplementation testLibs.bundles.junit +} + +test { + useJUnitPlatform() +} + + diff --git a/bindings/java-bindings/gradle/wrapper/gradle-wrapper.jar b/bindings/java-bindings/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..249e5832f Binary files /dev/null and b/bindings/java-bindings/gradle/wrapper/gradle-wrapper.jar differ diff --git a/bindings/java-bindings/gradle/wrapper/gradle-wrapper.properties b/bindings/java-bindings/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..cf731511e --- /dev/null +++ b/bindings/java-bindings/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Jun 22 13:53:47 CST 2024 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/bindings/java-bindings/gradlew b/bindings/java-bindings/gradlew new file mode 100755 index 000000000..1b6c78733 --- /dev/null +++ b/bindings/java-bindings/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/bindings/java-bindings/gradlew.bat b/bindings/java-bindings/gradlew.bat new file mode 100644 index 000000000..ac1b06f93 --- /dev/null +++ b/bindings/java-bindings/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/bindings/java-bindings/settings.gradle b/bindings/java-bindings/settings.gradle new file mode 100644 index 000000000..fcf49f28b --- /dev/null +++ b/bindings/java-bindings/settings.gradle @@ -0,0 +1,34 @@ +rootProject.name = 'superchain-bindings' +include 'superchain-registry' +include 'superchain-primitives' + +dependencyResolutionManagement { + versionCatalogs { + libs{ + version('besu', '24.6.0') + version('jackson', '2.17.1') + version('tuweni', '2.4.2') + version('guava', '33.2.1-jre') + version('vertx', '4.5.8') + + library('besu-datatypes', 'org.hyperledger.besu', 'besu-datatypes').versionRef('besu') + library('jackson-datatype-jdk8', 'com.fasterxml.jackson.datatype', 'jackson-datatype-jdk8').versionRef('jackson') + library('jackson-dataformat-yaml', 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-yaml').versionRef('jackson') + library('jackson-dataformat-toml', 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-toml').versionRef('jackson') + library('tuweni-bytes', 'io.tmio', 'tuweni-bytes').versionRef('tuweni') + library('guava', 'com.google.guava', 'guava').versionRef('guava') + library('vertx-core', 'io.vertx', 'vertx-core').versionRef('vertx') + + bundle('jackson', ['jackson-datatype-jdk8', 'jackson-dataformat-yaml', 'jackson-dataformat-toml']) + } + + testLibs { + def junit5 = version('junit5', '5.10.0') + library('junit-bom', 'org.junit', 'junit-bom').versionRef(junit5) + library('junit-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef(junit5) + library('junit-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef(junit5) + + bundle('junit', ['junit-api', 'junit-engine']) + } + } +} diff --git a/bindings/java-bindings/superchain-primitives/build.gradle b/bindings/java-bindings/superchain-primitives/build.gradle new file mode 100644 index 000000000..6516c91a6 --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'java' +} + +group = 'me.grapebaba' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() + + maven { + url "https://hyperledger.jfrog.io/artifactory/besu-maven/" + } + +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + +dependencies { + implementation libs.besu.datatypes + implementation libs.bundles.jackson + implementation libs.tuweni.bytes + testImplementation platform(testLibs.junit.bom) + testImplementation testLibs.bundles.junit + implementation 'io.vertx:vertx-core:4.5.8' + +} + +test { + useJUnitPlatform() +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/AddressList.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/AddressList.java new file mode 100644 index 000000000..cc85c181b --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/AddressList.java @@ -0,0 +1,256 @@ +package io.optimism.superchain; + + +import org.hyperledger.besu.datatypes.Address; + +import java.util.Objects; +import java.util.Optional; + +/** + * AddressList is a POJO that represents the addresses of the contracts that are deployed on the + * Superchain. This class is used to deserialize the JSON file that contains the addresses of the + * contracts. + * + * @author grapebaba + * @since 0.1.0 + */ +public class AddressList { + private Address addressManager; + + private Address l1CrossDomainMessengerProxy; + + private Address l1ERC721BridgeProxy; + + private Address l1StandardBridgeProxy; + + private Optional
l2OutputOracleProxy= Optional.empty(); + + private Address optimismMintableERC20FactoryProxy; + + private Address optimismPortalProxy; + + private Address systemConfigProxy; + + private Address systemConfigOwner; + + private Address proxyAdmin; + + private Address proxyAdminOwner; + + private Address guardian; + + private Optional
challenger= Optional.empty(); + + // Fault Proof Contract Addresses + private Optional
anchorStateRegistryProxy = Optional.empty(); + + private Optional
delayedWETHProxy = Optional.empty(); + + private Optional
disputeGameFactoryProxy = Optional.empty(); + + private Optional
faultDisputeGame = Optional.empty(); + + private Optional
mips = Optional.empty(); + + private Optional
permissionedDisputeGame = Optional.empty(); + + private Optional
preimageOracle = Optional.empty(); + + public Address getAddressManager() { + return addressManager; + } + + public void setAddressManager(Address addressManager) { + this.addressManager = addressManager; + } + + public Address getL1CrossDomainMessengerProxy() { + return l1CrossDomainMessengerProxy; + } + + public void setL1CrossDomainMessengerProxy(Address l1CrossDomainMessengerProxy) { + this.l1CrossDomainMessengerProxy = l1CrossDomainMessengerProxy; + } + + public Address getL1ERC721BridgeProxy() { + return l1ERC721BridgeProxy; + } + + public void setL1ERC721BridgeProxy(Address l1ERC721BridgeProxy) { + this.l1ERC721BridgeProxy = l1ERC721BridgeProxy; + } + + public Address getL1StandardBridgeProxy() { + return l1StandardBridgeProxy; + } + + public void setL1StandardBridgeProxy(Address l1StandardBridgeProxy) { + this.l1StandardBridgeProxy = l1StandardBridgeProxy; + } + + public Optional
getL2OutputOracleProxy() { + return l2OutputOracleProxy; + } + + public void setL2OutputOracleProxy(Optional
l2OutputOracleProxy) { + this.l2OutputOracleProxy = l2OutputOracleProxy; + } + + public Address getOptimismMintableERC20FactoryProxy() { + return optimismMintableERC20FactoryProxy; + } + + public void setOptimismMintableERC20FactoryProxy(Address optimismMintableERC20FactoryProxy) { + this.optimismMintableERC20FactoryProxy = optimismMintableERC20FactoryProxy; + } + + public Address getOptimismPortalProxy() { + return optimismPortalProxy; + } + + public void setOptimismPortalProxy(Address optimismPortalProxy) { + this.optimismPortalProxy = optimismPortalProxy; + } + + public Address getSystemConfigProxy() { + return systemConfigProxy; + } + + public void setSystemConfigProxy(Address systemConfigProxy) { + this.systemConfigProxy = systemConfigProxy; + } + + public Address getSystemConfigOwner() { + return systemConfigOwner; + } + + public void setSystemConfigOwner(Address systemConfigOwner) { + this.systemConfigOwner = systemConfigOwner; + } + + public Address getProxyAdmin() { + return proxyAdmin; + } + + public void setProxyAdmin(Address proxyAdmin) { + this.proxyAdmin = proxyAdmin; + } + + public Address getProxyAdminOwner() { + return proxyAdminOwner; + } + + public void setProxyAdminOwner(Address proxyAdminOwner) { + this.proxyAdminOwner = proxyAdminOwner; + } + + public Address getGuardian() { + return guardian; + } + + public void setGuardian(Address guardian) { + this.guardian = guardian; + } + + public Optional
getChallenger() { + return challenger; + } + + public void setChallenger(Optional
challenger) { + this.challenger = challenger; + } + + public Optional
getAnchorStateRegistryProxy() { + return anchorStateRegistryProxy; + } + + public void setAnchorStateRegistryProxy(Optional
anchorStateRegistryProxy) { + this.anchorStateRegistryProxy = anchorStateRegistryProxy; + } + + public Optional
getDelayedWETHProxy() { + return delayedWETHProxy; + } + + public void setDelayedWETHProxy(Optional
delayedWETHProxy) { + this.delayedWETHProxy = delayedWETHProxy; + } + + public Optional
getDisputeGameFactoryProxy() { + return disputeGameFactoryProxy; + } + + public void setDisputeGameFactoryProxy(Optional
disputeGameFactoryProxy) { + this.disputeGameFactoryProxy = disputeGameFactoryProxy; + } + + public Optional
getFaultDisputeGame() { + return faultDisputeGame; + } + + public void setFaultDisputeGame(Optional
faultDisputeGame) { + this.faultDisputeGame = faultDisputeGame; + } + + public Optional
getMips() { + return mips; + } + + public void setMips(Optional
mips) { + this.mips = mips; + } + + public Optional
getPermissionedDisputeGame() { + return permissionedDisputeGame; + } + + public void setPermissionedDisputeGame(Optional
permissionedDisputeGame) { + this.permissionedDisputeGame = permissionedDisputeGame; + } + + public Optional
getPreimageOracle() { + return preimageOracle; + } + + public void setPreimageOracle(Optional
preimageOracle) { + this.preimageOracle = preimageOracle; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AddressList that)) return false; + return Objects.equals(getAddressManager(), that.getAddressManager()) && Objects.equals(getL1CrossDomainMessengerProxy(), that.getL1CrossDomainMessengerProxy()) && Objects.equals(getL1ERC721BridgeProxy(), that.getL1ERC721BridgeProxy()) && Objects.equals(getL1StandardBridgeProxy(), that.getL1StandardBridgeProxy()) && Objects.equals(getL2OutputOracleProxy(), that.getL2OutputOracleProxy()) && Objects.equals(getOptimismMintableERC20FactoryProxy(), that.getOptimismMintableERC20FactoryProxy()) && Objects.equals(getOptimismPortalProxy(), that.getOptimismPortalProxy()) && Objects.equals(getSystemConfigProxy(), that.getSystemConfigProxy()) && Objects.equals(getSystemConfigOwner(), that.getSystemConfigOwner()) && Objects.equals(getProxyAdmin(), that.getProxyAdmin()) && Objects.equals(getProxyAdminOwner(), that.getProxyAdminOwner()) && Objects.equals(getGuardian(), that.getGuardian()) && Objects.equals(getChallenger(), that.getChallenger()) && Objects.equals(getAnchorStateRegistryProxy(), that.getAnchorStateRegistryProxy()) && Objects.equals(getDelayedWETHProxy(), that.getDelayedWETHProxy()) && Objects.equals(getDisputeGameFactoryProxy(), that.getDisputeGameFactoryProxy()) && Objects.equals(getFaultDisputeGame(), that.getFaultDisputeGame()) && Objects.equals(getMips(), that.getMips()) && Objects.equals(getPermissionedDisputeGame(), that.getPermissionedDisputeGame()) && Objects.equals(getPreimageOracle(), that.getPreimageOracle()); + } + + @Override + public int hashCode() { + return Objects.hash(getAddressManager(), getL1CrossDomainMessengerProxy(), getL1ERC721BridgeProxy(), getL1StandardBridgeProxy(), getL2OutputOracleProxy(), getOptimismMintableERC20FactoryProxy(), getOptimismPortalProxy(), getSystemConfigProxy(), getSystemConfigOwner(), getProxyAdmin(), getProxyAdminOwner(), getGuardian(), getChallenger(), getAnchorStateRegistryProxy(), getDelayedWETHProxy(), getDisputeGameFactoryProxy(), getFaultDisputeGame(), getMips(), getPermissionedDisputeGame(), getPreimageOracle()); + } + + @Override + public String toString() { + return "AddressList{" + + "addressManager=" + addressManager + + ", l1CrossDomainMessengerProxy=" + l1CrossDomainMessengerProxy + + ", l1ERC721BridgeProxy=" + l1ERC721BridgeProxy + + ", l1StandardBridgeProxy=" + l1StandardBridgeProxy + + ", l2OutputOracleProxy=" + l2OutputOracleProxy + + ", optimismMintableERC20FactoryProxy=" + optimismMintableERC20FactoryProxy + + ", optimismPortalProxy=" + optimismPortalProxy + + ", systemConfigProxy=" + systemConfigProxy + + ", systemConfigOwner=" + systemConfigOwner + + ", proxyAdmin=" + proxyAdmin + + ", proxyAdminOwner=" + proxyAdminOwner + + ", guardian=" + guardian + + ", challenger=" + challenger + + ", anchorStateRegistryProxy=" + anchorStateRegistryProxy + + ", delayedWETHProxy=" + delayedWETHProxy + + ", disputeGameFactoryProxy=" + disputeGameFactoryProxy + + ", faultDisputeGame=" + faultDisputeGame + + ", mips=" + mips + + ", permissionedDisputeGame=" + permissionedDisputeGame + + ", preimageOracle=" + preimageOracle + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/BlockID.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/BlockID.java new file mode 100644 index 000000000..bc085ca5b --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/BlockID.java @@ -0,0 +1,50 @@ +package io.optimism.superchain; + + +import org.hyperledger.besu.datatypes.Hash; + +import java.math.BigInteger; +import java.util.Objects; + +public class BlockID { + + private Hash hash; + + private BigInteger number; + + public Hash getHash() { + return hash; + } + + public void setHash(Hash hash) { + this.hash = hash; + } + + public BigInteger getNumber() { + return number; + } + + public void setNumber(BigInteger number) { + this.number = number; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BlockID blockID)) return false; + return Objects.equals(getHash(), blockID.getHash()) && Objects.equals(getNumber(), blockID.getNumber()); + } + + @Override + public int hashCode() { + return Objects.hash(getHash(), getNumber()); + } + + @Override + public String toString() { + return "BlockID{" + + "hash=" + hash + + ", number=" + number + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ChainConfig.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ChainConfig.java new file mode 100644 index 000000000..a35238bdb --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ChainConfig.java @@ -0,0 +1,212 @@ +package io.optimism.superchain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import org.hyperledger.besu.datatypes.Address; + +import java.util.Objects; +import java.util.Optional; + +/** + * Represents the configuration of a chain. + * + * @author grapebaba + * @since 0.1.0 + */ +public class ChainConfig { + + private String name; + + private long chainId; + + private String publicRpc; + + private String sequencerRpc; + + private String explorer; + + private SuperchainLevel superchainLevel; + + private Optional superchainTime = Optional.empty(); + + private Address batchInboxAddr; + + private ChainGenesis genesis; + + @JsonProperty("superchain") + @JsonIgnore + private String superchain; + + @JsonProperty("chain") + @JsonIgnore + private String chain; + + @JsonProperty("hardfork_configuration") + @JsonUnwrapped + private HardForkConfiguration hardforkConfiguration; + + @JsonProperty("plasma") + private Optional plasma = Optional.empty(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getChainId() { + return chainId; + } + + public void setChainId(long chainId) { + this.chainId = chainId; + } + + public String getPublicRpc() { + return publicRpc; + } + + public void setPublicRpc(String publicRpc) { + this.publicRpc = publicRpc; + } + + public String getSequencerRpc() { + return sequencerRpc; + } + + public void setSequencerRpc(String sequencerRpc) { + this.sequencerRpc = sequencerRpc; + } + + public String getExplorer() { + return explorer; + } + + public void setExplorer(String explorer) { + this.explorer = explorer; + } + + public SuperchainLevel getSuperchainLevel() { + return superchainLevel; + } + + public void setSuperchainLevel(SuperchainLevel superchainLevel) { + this.superchainLevel = superchainLevel; + } + + public Optional getSuperchainTime() { + return superchainTime; + } + + public void setSuperchainTime(Optional superchainTime) { + this.superchainTime = superchainTime; + } + + public Address getBatchInboxAddr() { + return batchInboxAddr; + } + + public void setBatchInboxAddr(Address batchInboxAddr) { + this.batchInboxAddr = batchInboxAddr; + } + + public ChainGenesis getGenesis() { + return genesis; + } + + public void setGenesis(ChainGenesis genesis) { + this.genesis = genesis; + } + + public String getSuperchain() { + return superchain; + } + + public void setSuperchain(String superchain) { + this.superchain = superchain; + } + + public String getChain() { + return chain; + } + + public void setChain(String chain) { + this.chain = chain; + } + + public HardForkConfiguration getHardforkConfiguration() { + return hardforkConfiguration; + } + + public void setHardforkConfiguration(HardForkConfiguration hardforkConfiguration) { + this.hardforkConfiguration = hardforkConfiguration; + } + + public Optional getPlasma() { + return plasma; + } + + public void setPlasma(Optional plasma) { + this.plasma = plasma; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ChainConfig that)) return false; + return getChainId() == that.getChainId() && Objects.equals(getName(), that.getName()) && Objects.equals(getPublicRpc(), that.getPublicRpc()) && Objects.equals(getSequencerRpc(), that.getSequencerRpc()) && Objects.equals(getExplorer(), that.getExplorer()) && getSuperchainLevel() == that.getSuperchainLevel() && Objects.equals(getSuperchainTime(), that.getSuperchainTime()) && Objects.equals(getBatchInboxAddr(), that.getBatchInboxAddr()) && Objects.equals(getGenesis(), that.getGenesis()) && Objects.equals(getSuperchain(), that.getSuperchain()) && Objects.equals(getChain(), that.getChain()) && Objects.equals(getHardforkConfiguration(), that.getHardforkConfiguration()) && Objects.equals(getPlasma(), that.getPlasma()); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), getChainId(), getPublicRpc(), getSequencerRpc(), getExplorer(), getSuperchainLevel(), getSuperchainTime(), getBatchInboxAddr(), getGenesis(), getSuperchain(), getChain(), getHardforkConfiguration(), getPlasma()); + } + + @Override + public String toString() { + return "ChainConfig{" + + "name='" + name + '\'' + + ", chainId=" + chainId + + ", publicRpc='" + publicRpc + '\'' + + ", sequencerRpc='" + sequencerRpc + '\'' + + ", explorer='" + explorer + '\'' + + ", superchainLevel=" + superchainLevel + + ", superchainTime=" + superchainTime + + ", batchInboxAddr=" + batchInboxAddr + + ", genesis=" + genesis + + ", superchain='" + superchain + '\'' + + ", chain='" + chain + '\'' + + ", hardforkConfiguration=" + hardforkConfiguration + + ", plasma=" + plasma + + '}'; + } + + public void setMissingForkConfigs(HardForkConfiguration defaults) { + if (this.superchainTime.isEmpty()) { + return; + } + + long superchainTime = this.superchainTime.get(); + + HardForkConfiguration cfg = this.hardforkConfiguration; + + if (cfg.getCanyonTime().isPresent() && cfg.getCanyonTime().get() > superchainTime) { + cfg.setCanyonTime(defaults.getCanyonTime()); + } + + if (cfg.getDeltaTime().isPresent() && cfg.getDeltaTime().get() > superchainTime) { + cfg.setDeltaTime(defaults.getDeltaTime()); + } + + if (cfg.getEcotoneTime().isPresent() && cfg.getEcotoneTime().get() > superchainTime) { + cfg.setEcotoneTime(defaults.getEcotoneTime()); + } + + if (cfg.getFjordTime().isPresent() && cfg.getFjordTime().get() > superchainTime) { + cfg.setFjordTime(defaults.getFjordTime()); + } + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ChainGenesis.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ChainGenesis.java new file mode 100644 index 000000000..08a168eba --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ChainGenesis.java @@ -0,0 +1,136 @@ +package io.optimism.superchain; + +import java.util.Objects; +import java.util.Optional; + +/** + * Represents the genesis of a chain. + * + * @author grapebaba + * @since 0.1.0 + */ +public class ChainGenesis { + + private BlockID l1; + + private BlockID l2; + + private long l2Time; + + private Optional extraData = Optional.empty(); + + private Optional systemConfig = Optional.empty(); + + /** + * Gets l1. + * + * @return the l1 + */ + public BlockID getL1() { + return l1; + } + + /** + * Sets l1. + * + * @param l1 the l1 + */ + public void setL1(BlockID l1) { + this.l1 = l1; + } + + /** + * Gets l2. + * + * @return the l2 + */ + public BlockID getL2() { + return l2; + } + + /** + * Sets l2. + * + * @param l2 the l2 + */ + public void setL2(BlockID l2) { + this.l2 = l2; + } + + /** + * Gets l2 time. + * + * @return the l2 time + */ + public long getL2Time() { + return l2Time; + } + + /** + * Sets l2 time. + * + * @param l2Time the l2 time + */ + public void setL2Time(long l2Time) { + this.l2Time = l2Time; + } + + /** + * Gets extra data. + * + * @return the extra data + */ + public Optional getExtraData() { + return extraData; + } + + /** + * Sets extra data. + * + * @param extraData the extra data + */ + public void setExtraData(Optional extraData) { + this.extraData = extraData; + } + + /** + * Gets system config. + * + * @return the system config + */ + public Optional getSystemConfig() { + return systemConfig; + } + + /** + * Sets system config. + * + * @param systemConfig the system config + */ + public void setSystemConfig(Optional systemConfig) { + this.systemConfig = systemConfig; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ChainGenesis that)) return false; + return Objects.equals(getL1(), that.getL1()) && Objects.equals(getL2(), that.getL2()) && Objects.equals(getL2Time(), that.getL2Time()) && Objects.equals(getExtraData(), that.getExtraData()) && Objects.equals(getSystemConfig(), that.getSystemConfig()); + } + + @Override + public int hashCode() { + return Objects.hash(getL1(), getL2(), getL2Time(), getExtraData(), getSystemConfig()); + } + + @Override + public String toString() { + return "ChainGenesis{" + + "l1=" + l1 + + ", l2=" + l2 + + ", l2Time=" + l2Time + + ", extraData=" + extraData + + ", systemConfig=" + systemConfig + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ContractImplementations.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ContractImplementations.java new file mode 100644 index 000000000..cad1a5da4 --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/ContractImplementations.java @@ -0,0 +1,223 @@ +package io.optimism.superchain; + +import org.hyperledger.besu.datatypes.Address; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + + +public class ContractImplementations { + + private Map l1CrossDomainMessenger= new HashMap<>(); + + private Map l1ERC721Bridge= new HashMap<>(); + + private Map l1StandardBridge= new HashMap<>(); + + private Map l2OutputOracle= new HashMap<>(); + + private Map optimismMintableERC20Factory= new HashMap<>(); + + private Map optimismPortal= new HashMap<>(); + + private Map systemConfig= new HashMap<>(); + // Fault Proof Contracts + private Optional> anchorStateRegistry= Optional.empty(); + + private Optional> delayedWETH= Optional.empty(); + + private Optional> disputeGameFactory= Optional.empty(); + + private Optional> faultDisputeGame= Optional.empty(); + + private Optional> mips= Optional.empty(); + + private Optional> permissionedDisputeGame= Optional.empty(); + + private Optional> preimageOracle= Optional.empty(); + + public Map getL1CrossDomainMessenger() { + + return l1CrossDomainMessenger; + } + + public void setL1CrossDomainMessenger(Map l1CrossDomainMessenger) { + this.l1CrossDomainMessenger = l1CrossDomainMessenger; + } + + public Map getL1ERC721Bridge() { + return l1ERC721Bridge; + } + + public void setL1ERC721Bridge(Map l1ERC721Bridge) { + this.l1ERC721Bridge = l1ERC721Bridge; + } + + public Map getL1StandardBridge() { + return l1StandardBridge; + } + + public void setL1StandardBridge(Map l1StandardBridge) { + this.l1StandardBridge = l1StandardBridge; + } + + public Map getL2OutputOracle() { + return l2OutputOracle; + } + + public void setL2OutputOracle(Map l2OutputOracle) { + this.l2OutputOracle = l2OutputOracle; + } + + public Map getOptimismMintableERC20Factory() { + return optimismMintableERC20Factory; + } + + public void setOptimismMintableERC20Factory(Map optimismMintableERC20Factory) { + this.optimismMintableERC20Factory = optimismMintableERC20Factory; + } + + public Map getOptimismPortal() { + return optimismPortal; + } + + public void setOptimismPortal(Map optimismPortal) { + this.optimismPortal = optimismPortal; + } + + public Map getSystemConfig() { + return systemConfig; + } + + public void setSystemConfig(Map systemConfig) { + this.systemConfig = systemConfig; + } + + public Optional> getAnchorStateRegistry() { + return anchorStateRegistry; + } + + public void setAnchorStateRegistry(Optional> anchorStateRegistry) { + this.anchorStateRegistry = anchorStateRegistry; + } + + public Optional> getDelayedWETH() { + return delayedWETH; + } + + public void setDelayedWETH(Optional> delayedWETH) { + this.delayedWETH = delayedWETH; + } + + public Optional> getDisputeGameFactory() { + return disputeGameFactory; + } + + public void setDisputeGameFactory(Optional> disputeGameFactory) { + this.disputeGameFactory = disputeGameFactory; + } + + public Optional> getFaultDisputeGame() { + return faultDisputeGame; + } + + public void setFaultDisputeGame(Optional> faultDisputeGame) { + this.faultDisputeGame = faultDisputeGame; + } + + public Optional> getMips() { + return mips; + } + + public void setMips(Optional> mips) { + this.mips = mips; + } + + public Optional> getPermissionedDisputeGame() { + return permissionedDisputeGame; + } + + public void setPermissionedDisputeGame(Optional> permissionedDisputeGame) { + this.permissionedDisputeGame = permissionedDisputeGame; + } + + public Optional> getPreimageOracle() { + return preimageOracle; + } + + public void setPreimageOracle(Optional> preimageOracle) { + this.preimageOracle = preimageOracle; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ContractImplementations that)) return false; + return Objects.equals(getL1CrossDomainMessenger(), that.getL1CrossDomainMessenger()) && Objects.equals(getL1ERC721Bridge(), that.getL1ERC721Bridge()) && Objects.equals(getL1StandardBridge(), that.getL1StandardBridge()) && Objects.equals(getL2OutputOracle(), that.getL2OutputOracle()) && Objects.equals(getOptimismMintableERC20Factory(), that.getOptimismMintableERC20Factory()) && Objects.equals(getOptimismPortal(), that.getOptimismPortal()) && Objects.equals(getSystemConfig(), that.getSystemConfig()) && Objects.equals(getAnchorStateRegistry(), that.getAnchorStateRegistry()) && Objects.equals(getDelayedWETH(), that.getDelayedWETH()) && Objects.equals(getDisputeGameFactory(), that.getDisputeGameFactory()) && Objects.equals(getFaultDisputeGame(), that.getFaultDisputeGame()) && Objects.equals(getMips(), that.getMips()) && Objects.equals(getPermissionedDisputeGame(), that.getPermissionedDisputeGame()) && Objects.equals(getPreimageOracle(), that.getPreimageOracle()); + } + + @Override + public int hashCode() { + return Objects.hash(getL1CrossDomainMessenger(), getL1ERC721Bridge(), getL1StandardBridge(), getL2OutputOracle(), getOptimismMintableERC20Factory(), getOptimismPortal(), getSystemConfig(), getAnchorStateRegistry(), getDelayedWETH(), getDisputeGameFactory(), getFaultDisputeGame(), getMips(), getPermissionedDisputeGame(), getPreimageOracle()); + } + + @Override + public String toString() { + return "ContractImplementations{" + + "l1CrossDomainMessenger=" + l1CrossDomainMessenger + + ", l1ERC721Bridge=" + l1ERC721Bridge + + ", l1StandardBridge=" + l1StandardBridge + + ", l2OutputOracle=" + l2OutputOracle + + ", optimismMintableERC20Factory=" + optimismMintableERC20Factory + + ", optimismPortal=" + optimismPortal + + ", systemConfig=" + systemConfig + + ", anchorStateRegistry=" + anchorStateRegistry + + ", delayedWETH=" + delayedWETH + + ", disputeGameFactory=" + disputeGameFactory + + ", faultDisputeGame=" + faultDisputeGame + + ", mips=" + mips + + ", permissionedDisputeGame=" + permissionedDisputeGame + + ", preimageOracle=" + preimageOracle + + '}'; + } + + public void merge(ContractImplementations that) { + this.l1CrossDomainMessenger.putAll(that.getL1CrossDomainMessenger()); + this.l1ERC721Bridge.putAll(that.getL1ERC721Bridge()); + this.l1StandardBridge.putAll(that.getL1StandardBridge()); + this.l2OutputOracle.putAll(that.getL2OutputOracle()); + this.optimismMintableERC20Factory.putAll(that.getOptimismMintableERC20Factory()); + this.optimismPortal.putAll(that.getOptimismPortal()); + this.systemConfig.putAll(that.getSystemConfig()); + this.anchorStateRegistry = Optional.of(this.anchorStateRegistry.orElse(new HashMap<>())).map(map -> { + map.putAll(that.getAnchorStateRegistry().orElse(new HashMap<>())); + return map; + }).filter(map -> !map.isEmpty()); + this.delayedWETH = Optional.of(this.delayedWETH.orElse(new HashMap<>())).map(map -> { + map.putAll(that.getDelayedWETH().orElse(new HashMap<>())); + return map; + }).filter(map -> !map.isEmpty()); + this.disputeGameFactory = Optional.of(this.disputeGameFactory.orElse(new HashMap<>())).map(map -> { + map.putAll(that.getDisputeGameFactory().orElse(new HashMap<>())); + return map; + }).filter(map -> !map.isEmpty()); + this.faultDisputeGame = Optional.of(this.faultDisputeGame.orElse(new HashMap<>())).map(map -> { + map.putAll(that.getFaultDisputeGame().orElse(new HashMap<>())); + return map; + }).filter(map -> !map.isEmpty()); + this.mips = Optional.of(this.mips.orElse(new HashMap<>())).map(map -> { + map.putAll(that.getMips().orElse(new HashMap<>())); + return map; + }).filter(map -> !map.isEmpty()); + this.permissionedDisputeGame = Optional.of(this.permissionedDisputeGame.orElse(new HashMap<>())).map(map -> { + map.putAll(that.getPermissionedDisputeGame().orElse(new HashMap<>())); + return map; + }).filter(map -> !map.isEmpty()); + this.preimageOracle = Optional.of(this.preimageOracle.orElse(new HashMap<>())).map(map -> { + map.putAll(that.getPreimageOracle().orElse(new HashMap<>())); + return map; + }).filter(map -> !map.isEmpty()); + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/HardForkConfiguration.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/HardForkConfiguration.java new file mode 100644 index 000000000..b955ab165 --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/HardForkConfiguration.java @@ -0,0 +1,115 @@ +package io.optimism.superchain; + +import java.util.Objects; +import java.util.Optional; + +/** + * Represents the hard fork configuration of a chain. + * + * @author grapebaba + * @since 0.1.0 + */ +public class HardForkConfiguration { + + private Optional canyonTime = Optional.empty(); + + private Optional deltaTime = Optional.empty(); + + private Optional ecotoneTime = Optional.empty(); + + private Optional fjordTime = Optional.empty(); + + /** + * Gets canyon time. + * + * @return the canyon time + */ + public Optional getCanyonTime() { + return canyonTime; + } + + /** + * Sets canyon time. + * + * @param canyonTime the canyon time + */ + public void setCanyonTime(Optional canyonTime) { + this.canyonTime = canyonTime; + } + + /** + * Gets delta time. + * + * @return the delta time + */ + public Optional getDeltaTime() { + return deltaTime; + } + + /** + * Sets delta time. + * + * @param deltaTime the delta time + */ + public void setDeltaTime(Optional deltaTime) { + this.deltaTime = deltaTime; + } + + /** + * Gets ecotone time. + * + * @return the ecotone time + */ + public Optional getEcotoneTime() { + return ecotoneTime; + } + + /** + * Sets ecotone time. + * + * @param ecotoneTime the ecotone time + */ + public void setEcotoneTime(Optional ecotoneTime) { + this.ecotoneTime = ecotoneTime; + } + + /** + * Gets fjord time. + * + * @return the fjord time + */ + public Optional getFjordTime() { + return fjordTime; + } + + /** + * Sets fjord time. + * + * @param fjordTime the fjord time + */ + public void setFjordTime(Optional fjordTime) { + this.fjordTime = fjordTime; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof HardForkConfiguration that)) return false; + return Objects.equals(canyonTime, that.canyonTime) && Objects.equals(deltaTime, that.deltaTime) && Objects.equals(ecotoneTime, that.ecotoneTime) && Objects.equals(fjordTime, that.fjordTime); + } + + @Override + public int hashCode() { + return Objects.hash(canyonTime, deltaTime, ecotoneTime, fjordTime); + } + + @Override + public String toString() { + return "HardForkConfiguration{" + + "canyonTime=" + canyonTime + + ", deltaTime=" + deltaTime + + ", ecotoneTime=" + ecotoneTime + + ", fjordTime=" + fjordTime + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/PlasmaConfig.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/PlasmaConfig.java new file mode 100644 index 000000000..d279a4b36 --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/PlasmaConfig.java @@ -0,0 +1,97 @@ +package io.optimism.superchain; + +import org.hyperledger.besu.datatypes.Address; + +import java.math.BigInteger; +import java.util.Objects; +import java.util.Optional; + +/** + * Represents the Plasma configuration of a chain. + * + * @author grapebaba + * @since 0.1.0 + */ +public class PlasmaConfig { + + private Optional
daChallengeAddress = Optional.empty(); + + private Optional daChallengeWindow = Optional.empty(); + + private Optional daResolveWindow = Optional.empty(); + + /** + * Gets da challenge address. + * + * @return the da challenge address + */ + public Optional
getDaChallengeAddress() { + return daChallengeAddress; + } + + /** + * Sets da challenge address. + * + * @param daChallengeAddress the da challenge address + */ + public void setDaChallengeAddress(Optional
daChallengeAddress) { + this.daChallengeAddress = daChallengeAddress; + } + + /** + * Gets da challenge window. + * + * @return the da challenge window + */ + public Optional getDaChallengeWindow() { + return daChallengeWindow; + } + + /** + * Sets da challenge window. + * + * @param daChallengeWindow the da challenge window + */ + public void setDaChallengeWindow(Optional daChallengeWindow) { + this.daChallengeWindow = daChallengeWindow; + } + + /** + * Gets da resolve window. + * + * @return the da resolve window + */ + public Optional getDaResolveWindow() { + return daResolveWindow; + } + + /** + * Sets da resolve window. + * + * @param daResolveWindow the da resolve window + */ + public void setDaResolveWindow(Optional daResolveWindow) { + this.daResolveWindow = daResolveWindow; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof PlasmaConfig that)) return false; + return Objects.equals(getDaChallengeAddress(), that.getDaChallengeAddress()) && Objects.equals(getDaChallengeWindow(), that.getDaChallengeWindow()) && Objects.equals(getDaResolveWindow(), that.getDaResolveWindow()); + } + + @Override + public int hashCode() { + return Objects.hash(getDaChallengeAddress(), getDaChallengeWindow(), getDaResolveWindow()); + } + + @Override + public String toString() { + return "PlasmaConfig{" + + "daChallengeAddress=" + daChallengeAddress + + ", daChallengeWindow=" + daChallengeWindow + + ", daResolveWindow=" + daResolveWindow + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/Superchain.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/Superchain.java new file mode 100644 index 000000000..2d50c191a --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/Superchain.java @@ -0,0 +1,73 @@ +package io.optimism.superchain; + +import java.util.List; +import java.util.Objects; + +/** + * The type Superchain. + * + * @author grapebaba + * @since 0.1.0 + */ +public class Superchain { + + private SuperchainConfig config; + + private List chainIds; + + private String superchain; + + public Superchain() { + } + + public Superchain(SuperchainConfig config, List chainIds, String superchain) { + this.config = config; + this.chainIds = chainIds; + this.superchain = superchain; + } + + public SuperchainConfig getConfig() { + return config; + } + + public void setConfig(SuperchainConfig config) { + this.config = config; + } + + public List getChainIds() { + return chainIds; + } + + public void setChainIds(List chainIds) { + this.chainIds = chainIds; + } + + public String getSuperchain() { + return superchain; + } + + public void setSuperchain(String superchain) { + this.superchain = superchain; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Superchain that)) return false; + return Objects.equals(getConfig(), that.getConfig()) && Objects.equals(getChainIds(), that.getChainIds()) && Objects.equals(getSuperchain(), that.getSuperchain()); + } + + @Override + public int hashCode() { + return Objects.hash(getConfig(), getChainIds(), getSuperchain()); + } + + @Override + public String toString() { + return "Superchain{" + + "config=" + config + + ", chainIds=" + chainIds + + ", superchain='" + superchain + '\'' + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainConfig.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainConfig.java new file mode 100644 index 000000000..d7f30410b --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainConfig.java @@ -0,0 +1,138 @@ +package io.optimism.superchain; + +import org.hyperledger.besu.datatypes.Address; + +import java.util.Objects; +import java.util.Optional; + +/** + * The type Superchainl1info. + * + * @author grapebaba + * @since 0.1.0 + */ +public class SuperchainConfig { + + private String name; + + private SuperchainL1Info l1; + + private Optional
protocolVersionsAddr; + + private Optional
superchainConfigAddr; + + private HardForkConfiguration hardforkDefaults; + + /** + * Gets name. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Sets name. + * + * @param name the name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Gets l 1. + * + * @return the l 1 + */ + public SuperchainL1Info getL1() { + return l1; + } + + /** + * Sets l 1. + * + * @param l1 the l 1 + */ + public void setL1(SuperchainL1Info l1) { + this.l1 = l1; + } + + /** + * Gets protocol versions addr. + * + * @return the protocol versions addr + */ + public Optional
getProtocolVersionsAddr() { + return protocolVersionsAddr; + } + + /** + * Sets protocol versions addr. + * + * @param protocolVersionsAddr the protocol versions addr + */ + public void setProtocolVersionsAddr(Optional
protocolVersionsAddr) { + this.protocolVersionsAddr = protocolVersionsAddr; + } + + /** + * Gets superchain config addr. + * + * @return the superchain config addr + */ + public Optional
getSuperchainConfigAddr() { + return superchainConfigAddr; + } + + /** + * Sets superchain config addr. + * + * @param superchainConfigAddr the superchain config addr + */ + public void setSuperchainConfigAddr(Optional
superchainConfigAddr) { + this.superchainConfigAddr = superchainConfigAddr; + } + + /** + * Gets hardfork defaults. + * + * @return the hardfork defaults + */ + public HardForkConfiguration getHardforkDefaults() { + return hardforkDefaults; + } + + /** + * Sets hardfork defaults. + * + * @param hardforkDefaults the hardfork defaults + */ + public void setHardforkDefaults(HardForkConfiguration hardforkDefaults) { + this.hardforkDefaults = hardforkDefaults; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SuperchainConfig that)) return false; + return Objects.equals(getName(), that.getName()) && Objects.equals(getL1(), that.getL1()) && Objects.equals(getProtocolVersionsAddr(), that.getProtocolVersionsAddr()) && Objects.equals(getSuperchainConfigAddr(), that.getSuperchainConfigAddr()) && Objects.equals(getHardforkDefaults(), that.getHardforkDefaults()); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), getL1(), getProtocolVersionsAddr(), getSuperchainConfigAddr(), getHardforkDefaults()); + } + + @Override + public String toString() { + return "SuperchainConfig{" + + "name='" + name + '\'' + + ", l1=" + l1 + + ", protocolVersionsAddr=" + protocolVersionsAddr + + ", superchainConfigAddr=" + superchainConfigAddr + + ", hardforkDefaults=" + hardforkDefaults + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainL1Info.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainL1Info.java new file mode 100644 index 000000000..754e1c17b --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainL1Info.java @@ -0,0 +1,100 @@ +package io.optimism.superchain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * The type Superchainl1info. + * + * @author grapebaba + * @since 0.1.0 + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class SuperchainL1Info { + + @JsonProperty("chain_id") + private long chainId; + + @JsonProperty("public_rpc") + private String publicRpc; + + @JsonProperty("explorer") + private String explorer; + + /** + * Gets chain id. + * + * @return the chain id + */ + public long getChainId() { + return chainId; + } + + /** + * Sets chain id. + * + * @param chainId the chain id + */ + public void setChainId(long chainId) { + this.chainId = chainId; + } + + /** + * Gets public rpc. + * + * @return the public rpc + */ + public String getPublicRpc() { + return publicRpc; + } + + /** + * Sets public rpc. + * + * @param publicRpc the public rpc + */ + public void setPublicRpc(String publicRpc) { + this.publicRpc = publicRpc; + } + + /** + * Gets explorer. + * + * @return the explorer + */ + public String getExplorer() { + return explorer; + } + + /** + * Sets explorer. + * + * @param explorer the explorer + */ + public void setExplorer(String explorer) { + this.explorer = explorer; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SuperchainL1Info that)) return false; + return getChainId() == that.getChainId() && Objects.equals(getPublicRpc(), that.getPublicRpc()) && Objects.equals(getExplorer(), that.getExplorer()); + } + + @Override + public int hashCode() { + return Objects.hash(getChainId(), getPublicRpc(), getExplorer()); + } + + @Override + public String toString() { + return "SuperchainL1Info{" + + "chainId=" + chainId + + ", publicRpc='" + publicRpc + '\'' + + ", explorer='" + explorer + '\'' + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainLevel.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainLevel.java new file mode 100644 index 000000000..107578ea6 --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SuperchainLevel.java @@ -0,0 +1,43 @@ +package io.optimism.superchain; + +/** + * Represents the level of a superchain. + * + * @author grapebaba + * @since 0.1.0 + */ +public enum SuperchainLevel { + /** + * Frontier superchain level. + */ + Frontier((byte) 1), + /** + * Standard superchain level. + */ + Standard((byte) 2); + + private final byte value; + + SuperchainLevel(byte value) { + this.value = value; + } + + /** + * Gets value. + * + * @return the value + */ + public byte getValue() { + return value; + } + + public static SuperchainLevel fromValue(byte value) { + for (SuperchainLevel level : SuperchainLevel.values()) { + if (level.getValue() == value) { + return level; + } + } + return null; + } + +} diff --git a/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SystemConfig.java b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SystemConfig.java new file mode 100644 index 000000000..8197febaf --- /dev/null +++ b/bindings/java-bindings/superchain-primitives/src/main/java/io/optimism/superchain/SystemConfig.java @@ -0,0 +1,147 @@ +package io.optimism.superchain; + +import org.hyperledger.besu.datatypes.Address; + +import java.math.BigInteger; +import java.util.Optional; + +/** + * Represents the system configuration of a chain. + * + * @author grapebaba + * @since 0.1.0 + */ +public class SystemConfig { + + private Address batcherAddr; + + private String overhead; + + private String scalar; + + private BigInteger gasLimit; + + private Optional baseFeeScalar = Optional.empty(); + + private Optional blobBaseFeeScalar = Optional.empty(); + + /** + * Gets batcher addr. + * + * @return the batcher addr + */ + public Address getBatcherAddr() { + return batcherAddr; + } + + /** + * Sets batcher addr. + * + * @param batcherAddr the batcher addr + */ + public void setBatcherAddr(Address batcherAddr) { + this.batcherAddr = batcherAddr; + } + + /** + * Gets overhead. + * + * @return the overhead + */ + public String getOverhead() { + return overhead; + } + + /** + * Sets overhead. + * + * @param overhead the overhead + */ + public void setOverhead(String overhead) { + this.overhead = overhead; + } + + /** + * Gets scalar. + * + * @return the scalar + */ + public String getScalar() { + return scalar; + } + + /** + * Sets scalar. + * + * @param scalar the scalar + */ + public void setScalar(String scalar) { + this.scalar = scalar; + } + + /** + * Gets gas limit. + * + * @return the gas limit + */ + public BigInteger getGasLimit() { + return gasLimit; + } + + /** + * Sets gas limit. + * + * @param gasLimit the gas limit + */ + public void setGasLimit(BigInteger gasLimit) { + this.gasLimit = gasLimit; + } + + /** + * Gets base fee scalar. + * + * @return the base fee scalar + */ + public Optional getBaseFeeScalar() { + return baseFeeScalar; + } + + /** + * Sets base fee scalar. + * + * @param baseFeeScalar the base fee scalar + */ + public void setBaseFeeScalar(Optional baseFeeScalar) { + this.baseFeeScalar = baseFeeScalar; + } + + /** + * Gets blob base fee scalar. + * + * @return the blob base fee scalar + */ + public Optional getBlobBaseFeeScalar() { + return blobBaseFeeScalar; + } + + /** + * Sets blob base fee scalar. + * + * @param blobBaseFeeScalar the blob base fee scalar + */ + public void setBlobBaseFeeScalar(Optional blobBaseFeeScalar) { + this.blobBaseFeeScalar = blobBaseFeeScalar; + } + + @Override + public String toString() { + return "SystemConfig{" + + "batcherAddr=" + batcherAddr + + ", overhead='" + overhead + '\'' + + ", scalar='" + scalar + '\'' + + ", gasLimit=" + gasLimit + + ", baseFeeScalar=" + baseFeeScalar + + ", blobBaseFeeScalar=" + blobBaseFeeScalar + + '}'; + } +} diff --git a/bindings/java-bindings/superchain-registry/build.gradle b/bindings/java-bindings/superchain-registry/build.gradle new file mode 100644 index 000000000..7d1f7dcb0 --- /dev/null +++ b/bindings/java-bindings/superchain-registry/build.gradle @@ -0,0 +1,45 @@ +plugins { + id 'java' +} + +group = 'me.grapebaba' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() + + maven { + url "https://hyperledger.jfrog.io/artifactory/besu-maven/" + } +} + +sourceSets { + main { + resources { + exclude('**/*.go', '**/go.mod', '**/go.sum') + srcDirs+=['../../../superchain'] + } + } + +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + +dependencies { + implementation project(':superchain-primitives') + implementation libs.guava + implementation libs.besu.datatypes + implementation libs.bundles.jackson + implementation libs.jackson.datatype.jdk8 + implementation libs.tuweni.bytes + testImplementation platform(testLibs.junit.bom) + testImplementation testLibs.bundles.junit +} + +test { + useJUnitPlatform() +} diff --git a/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/AddressListDeserializer.java b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/AddressListDeserializer.java new file mode 100644 index 000000000..b7cb8b7d6 --- /dev/null +++ b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/AddressListDeserializer.java @@ -0,0 +1,65 @@ +package io.optimism.embed; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import io.optimism.superchain.AddressList; +import org.hyperledger.besu.datatypes.Address; + +import java.io.IOException; +import java.util.Optional; + +/** + * The type AddressList deserializer. + * + * @author grapebaba + * @since 0.1.0 + */ +public class AddressListDeserializer extends JsonDeserializer { + @Override + public AddressList deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + JsonNode node = p.getCodec().readTree(p); + AddressList addressList = new AddressList(); + addressList.setAddressManager(Address.fromHexStringStrict(node.get("AddressManager").asText())); + addressList.setGuardian(Address.fromHexStringStrict(node.get("Guardian").asText())); + addressList.setL1CrossDomainMessengerProxy(Address.fromHexStringStrict(node.get("L1CrossDomainMessengerProxy").asText())); + addressList.setL1ERC721BridgeProxy(Address.fromHexStringStrict(node.get("L1ERC721BridgeProxy").asText())); + addressList.setL1StandardBridgeProxy(Address.fromHexStringStrict(node.get("L1StandardBridgeProxy").asText())); + addressList.setOptimismMintableERC20FactoryProxy(Address.fromHexStringStrict(node.get("OptimismMintableERC20FactoryProxy").asText())); + addressList.setOptimismPortalProxy(Address.fromHexStringStrict(node.get("OptimismPortalProxy").asText())); + addressList.setSystemConfigProxy(Address.fromHexStringStrict(node.get("SystemConfigProxy").asText())); + addressList.setSystemConfigOwner(Address.fromHexStringStrict(node.get("SystemConfigOwner").asText())); + addressList.setProxyAdmin(Address.fromHexStringStrict(node.get("ProxyAdmin").asText())); + addressList.setProxyAdminOwner(Address.fromHexStringStrict(node.get("ProxyAdminOwner").asText())); + if (node.get("Challenger") != null) { + addressList.setChallenger(Optional.of(Address.fromHexStringStrict(node.get("Challenger").asText()))); + } + if (node.get("L2OutputOracleProxy") != null) { + addressList.setL2OutputOracleProxy(Optional.of(Address.fromHexStringStrict(node.get("L2OutputOracleProxy").asText()))); + } + if (node.get("AnchorStateRegistryProxy") != null) { + addressList.setAnchorStateRegistryProxy(Optional.of(Address.fromHexStringStrict(node.get("AnchorStateRegistryProxy").asText()))); + } + if (node.get("DelayedWETHProxy") != null) { + addressList.setDelayedWETHProxy(Optional.of(Address.fromHexStringStrict(node.get("DelayedWETHProxy").asText()))); + } + if (node.get("DisputeGameFactoryProxy") != null) { + addressList.setDisputeGameFactoryProxy(Optional.of(Address.fromHexStringStrict(node.get("DisputeGameFactoryProxy").asText()))); + } + if (node.get("FaultDisputeGame") != null) { + addressList.setFaultDisputeGame(Optional.of(Address.fromHexStringStrict(node.get("FaultDisputeGame").asText()))); + } + if (node.get("MIPS") != null) { + addressList.setMips(Optional.of(Address.fromHexStringStrict(node.get("MIPS").asText()))); + } + if (node.get("PermissionedDisputeGame") != null) { + addressList.setPermissionedDisputeGame(Optional.of(Address.fromHexStringStrict(node.get("PermissionedDisputeGame").asText()))); + } + if (node.get("PreimageOracle") != null) { + addressList.setPreimageOracle(Optional.of(Address.fromHexStringStrict(node.get("PreimageOracle").asText()))); + } + return addressList; + } +} diff --git a/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ChainConfigDeserializer.java b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ChainConfigDeserializer.java new file mode 100644 index 000000000..a00601fa2 --- /dev/null +++ b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ChainConfigDeserializer.java @@ -0,0 +1,70 @@ +package io.optimism.embed; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import io.optimism.superchain.ChainConfig; +import io.optimism.superchain.ChainGenesis; +import io.optimism.superchain.HardForkConfiguration; +import io.optimism.superchain.PlasmaConfig; +import io.optimism.superchain.SuperchainLevel; +import org.hyperledger.besu.datatypes.Address; + +import java.io.IOException; +import java.util.Optional; + +/** + * Created by IntelliJ IDEA. + * Author: kaichen + * Date: 2024/6/23 + * Time: 21:54 + */ +public class ChainConfigDeserializer extends JsonDeserializer { + @Override + public ChainConfig deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + JsonNode node = p.getCodec().readTree(p); + ChainConfig config = new ChainConfig(); + config.setName(node.get("name").asText()); + config.setChainId(node.get("chain_id").asLong()); + config.setPublicRpc(node.get("public_rpc").asText()); + config.setSequencerRpc(node.get("sequencer_rpc").asText()); + config.setExplorer(node.get("explorer").asText()); + config.setSuperchainLevel(SuperchainLevel.fromValue((byte) node.get("superchain_level").asInt())); + if (node.get("superchain_time") != null) { + config.setSuperchainTime(Optional.of(node.get("superchain_time").asLong())); + } + config.setBatchInboxAddr(Address.fromHexStringStrict(node.get("batch_inbox_addr").asText())); + config.setGenesis(p.getCodec().treeToValue(node.get("genesis"), ChainGenesis.class)); + + HardForkConfiguration hardForkConfiguration = new HardForkConfiguration(); + if (node.get("canyon_time") != null) { + hardForkConfiguration.setCanyonTime(Optional.of(node.get("canyon_time").asLong())); + } else { + hardForkConfiguration.setCanyonTime(Optional.empty()); + } + if (node.get("delta_time") != null) { + hardForkConfiguration.setDeltaTime(Optional.of(node.get("delta_time").asLong())); + } else { + hardForkConfiguration.setDeltaTime(Optional.empty()); + } + if (node.get("ecotone_time") != null) { + hardForkConfiguration.setEcotoneTime(Optional.of(node.get("ecotone_time").asLong())); + } else { + hardForkConfiguration.setEcotoneTime(Optional.empty()); + } + if (node.get("fjord_time") != null) { + hardForkConfiguration.setFjordTime(Optional.of(node.get("fjord_time").asLong())); + } else { + hardForkConfiguration.setFjordTime(Optional.empty()); + } + + config.setHardforkConfiguration(hardForkConfiguration); + + if (node.get("plasma") != null) { + config.setPlasma(Optional.of(p.getCodec().treeToValue(node.get("plasma"), PlasmaConfig.class))); + } + return config; + } +} diff --git a/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ChainGenesisDeserializer.java b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ChainGenesisDeserializer.java new file mode 100644 index 000000000..636963373 --- /dev/null +++ b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ChainGenesisDeserializer.java @@ -0,0 +1,44 @@ +package io.optimism.embed; + + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import io.optimism.superchain.BlockID; +import io.optimism.superchain.ChainGenesis; +import io.optimism.superchain.SystemConfig; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; + +import java.io.IOException; +import java.util.Optional; + +/** + * The type ChainGenesis deserializer. + * + * @author grapebaba + * @since 0.1.0 + */ +public class ChainGenesisDeserializer extends JsonDeserializer { + @Override + public ChainGenesis deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + JsonNode node = p.getCodec().readTree(p); + ChainGenesis genesis = new ChainGenesis(); + BlockID l1 = new BlockID(); + l1.setHash(Hash.fromHexString(node.get("l1").get("hash").asText())); + l1.setNumber(node.get("l1").get("number").bigIntegerValue()); + genesis.setL1(l1); + BlockID l2 = new BlockID(); + l2.setHash(Hash.fromHexString(node.get("l2").get("hash").asText())); + l2.setNumber(node.get("l2").get("number").bigIntegerValue()); + genesis.setL2(l2); + genesis.setL2Time(node.get("l2_time").asLong()); + if (node.get("extra_data") != null) { + genesis.setExtraData(Optional.of(node.get("extra_data").asText())); + } + + return genesis; + } +} diff --git a/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ContractImplementationsDeserializer.java b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ContractImplementationsDeserializer.java new file mode 100644 index 000000000..063b40820 --- /dev/null +++ b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/ContractImplementationsDeserializer.java @@ -0,0 +1,106 @@ +package io.optimism.embed; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.base.Strings; +import io.optimism.superchain.ContractImplementations; +import org.hyperledger.besu.datatypes.Address; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * The type ContractImplementations deserializer. + * + * @author grapebaba + * @since 0.1.0 + */ +public class ContractImplementationsDeserializer extends JsonDeserializer { + @Override + public ContractImplementations deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + JsonNode node = p.getCodec().readTree(p); + ContractImplementations contractImplementations = new ContractImplementations(); + + node.fields().forEachRemaining(entry -> { + switch (entry.getKey()) { + case "l1_cross_domain_messenger": + entry.getValue().fields().forEachRemaining(addressEntry -> contractImplementations.getL1CrossDomainMessenger().put(addressEntry.getKey(), getAddress(addressEntry))); + break; + case "l1_erc721_bridge": + entry.getValue().fields().forEachRemaining(addressEntry -> contractImplementations.getL1ERC721Bridge().put(addressEntry.getKey(), getAddress(addressEntry))); + break; + case "l1_standard_bridge": + entry.getValue().fields().forEachRemaining(addressEntry -> contractImplementations.getL1StandardBridge().put(addressEntry.getKey(), getAddress(addressEntry))); + break; + case "l2_output_oracle": + entry.getValue().fields().forEachRemaining(addressEntry -> contractImplementations.getL2OutputOracle().put(addressEntry.getKey(), getAddress(addressEntry))); + break; + case "optimism_mintable_erc20_factory": + entry.getValue().fields().forEachRemaining(addressEntry -> contractImplementations.getOptimismMintableERC20Factory().put(addressEntry.getKey(), getAddress(addressEntry))); + break; + case "optimism_portal": + entry.getValue().fields().forEachRemaining(addressEntry -> contractImplementations.getOptimismPortal().put(addressEntry.getKey(), getAddress(addressEntry))); + break; + case "system_config": + entry.getValue().fields().forEachRemaining(addressEntry -> contractImplementations.getSystemConfig().put(addressEntry.getKey(), getAddress(addressEntry))); + break; + case "anchor_state_registry": + entry.getValue().fields().forEachRemaining(addressEntry -> { + contractImplementations.setAnchorStateRegistry(Optional.of(new HashMap<>())); + contractImplementations.getAnchorStateRegistry().orElseThrow().put(addressEntry.getKey(), getAddress(addressEntry)); + }); + break; + case "delayed_weth": + entry.getValue().fields().forEachRemaining(addressEntry -> { + contractImplementations.setDelayedWETH(Optional.of(new HashMap<>())); + contractImplementations.getDelayedWETH().orElseThrow().put(addressEntry.getKey(), getAddress(addressEntry)); + }); + break; + case "dispute_game_factory": + entry.getValue().fields().forEachRemaining(addressEntry -> { + contractImplementations.setDisputeGameFactory(Optional.of(new HashMap<>())); + contractImplementations.getDisputeGameFactory().orElseThrow().put(addressEntry.getKey(), getAddress(addressEntry)); + }); + break; + case "fault_dispute_game": + entry.getValue().fields().forEachRemaining(addressEntry -> { + contractImplementations.setFaultDisputeGame(Optional.of(new HashMap<>())); + contractImplementations.getFaultDisputeGame().orElseThrow().put(addressEntry.getKey(), getAddress(addressEntry)); + }); + break; + case "mips": + entry.getValue().fields().forEachRemaining(addressEntry -> { + contractImplementations.setMips(Optional.of(new HashMap<>())); + contractImplementations.getMips().orElseThrow().put(addressEntry.getKey(), getAddress(addressEntry)); + }); + break; + case "permissioned_dispute_game": + entry.getValue().fields().forEachRemaining(addressEntry -> { + contractImplementations.setPermissionedDisputeGame(Optional.of(new HashMap<>())); + contractImplementations.getPermissionedDisputeGame().orElseThrow().put(addressEntry.getKey(), getAddress(addressEntry)); + }); + break; + case "preimage_oracle": + entry.getValue().fields().forEachRemaining(addressEntry -> { + contractImplementations.setPreimageOracle(Optional.of(new HashMap<>())); + contractImplementations.getPreimageOracle().orElseThrow().put(addressEntry.getKey(), getAddress(addressEntry)); + }); + break; + default: + break; + } + }); + + return contractImplementations; + } + + private static Address getAddress(Map.Entry entry) { + return Address.fromHexStringStrict(Strings.padStart(new BigInteger(entry.getValue().asText()).toString(16), 40, '0')); + } + +} diff --git a/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainConfigDeserializer.java b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainConfigDeserializer.java new file mode 100644 index 000000000..f32cbdeca --- /dev/null +++ b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainConfigDeserializer.java @@ -0,0 +1,69 @@ +package io.optimism.embed; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.base.Strings; +import io.optimism.superchain.HardForkConfiguration; +import io.optimism.superchain.SuperchainConfig; +import io.optimism.superchain.SuperchainL1Info; + +import java.io.IOException; +import java.util.Optional; + +import static org.hyperledger.besu.datatypes.Address.fromHexStringStrict; + +/** + * The type SuperchainConfig desirializer. + * + * @author grapebaba + * @since 0.1.0 + */ +public class SuperchainConfigDeserializer extends JsonDeserializer { + @Override + public SuperchainConfig deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + JsonNode node = p.getCodec().readTree(p); + SuperchainConfig config = new SuperchainConfig(); + config.setName(node.get("name").asText()); + SuperchainL1Info l1 = new SuperchainL1Info(); + l1.setChainId(node.get("l1").get("chain_id").asLong()); + l1.setPublicRpc(node.get("l1").get("public_rpc").asText()); + l1.setExplorer(node.get("l1").get("explorer").asText()); + config.setL1(l1); + if (Strings.isNullOrEmpty(node.get("protocol_versions_addr").asText())) { + config.setProtocolVersionsAddr(Optional.empty()); + } else { + config.setProtocolVersionsAddr(Optional.of(fromHexStringStrict(node.get("protocol_versions_addr").asText()))); + } + if (Strings.isNullOrEmpty(node.get("superchain_config_addr").asText())) { + config.setSuperchainConfigAddr(Optional.empty()); + } else { + config.setSuperchainConfigAddr(Optional.of(fromHexStringStrict(node.get("superchain_config_addr").asText()))); + } + HardForkConfiguration hardForkConfiguration = new HardForkConfiguration(); + if (node.get("canyon_time") != null) { + hardForkConfiguration.setCanyonTime(Optional.of(node.get("canyon_time").asLong())); + } else { + hardForkConfiguration.setCanyonTime(Optional.empty()); + } + if (node.get("delta_time") != null) { + hardForkConfiguration.setDeltaTime(Optional.of(node.get("delta_time").asLong())); + } else { + hardForkConfiguration.setDeltaTime(Optional.empty()); + } + if (node.get("ecotone_time") != null) { + hardForkConfiguration.setEcotoneTime(Optional.of(node.get("ecotone_time").asLong())); + } else { + hardForkConfiguration.setEcotoneTime(Optional.empty()); + } + if (node.get("fjord_time") != null) { + hardForkConfiguration.setFjordTime(Optional.of(node.get("fjord_time").asLong())); + } else { + hardForkConfiguration.setFjordTime(Optional.empty()); + } + config.setHardforkDefaults(hardForkConfiguration); + return config; + } +} diff --git a/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainConfigs.java b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainConfigs.java new file mode 100644 index 000000000..1fbbb41fc --- /dev/null +++ b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainConfigs.java @@ -0,0 +1,198 @@ +package io.optimism.embed; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.google.common.base.Strings; +import com.google.common.io.Resources; +import io.optimism.superchain.AddressList; +import io.optimism.superchain.ChainConfig; +import io.optimism.superchain.ChainGenesis; +import io.optimism.superchain.ContractImplementations; +import io.optimism.superchain.Superchain; +import io.optimism.superchain.SuperchainConfig; +import io.optimism.superchain.SuperchainLevel; +import io.optimism.superchain.SystemConfig; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Stream; + +public final class SuperchainConfigs { + + private static final Path CONFIGS_PATH; + + private static final Path EXTRA_PATH; + + private static final Path IMPLEMENTATIONS_PATH; + + private static final ObjectMapper UPPER_CAMEL_CASE_MAPPER = new ObjectMapper(); + + private static final ObjectMapper LOWER_CAMEL_CASE_MAPPER = new ObjectMapper(); + + private static final ObjectMapper SNAKE_CASE_MAPPER = new ObjectMapper(); + + private static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory()); + + private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); + + static { + try { + CONFIGS_PATH = Paths.get(Resources.getResource("configs").toURI()); + EXTRA_PATH = Paths.get(Resources.getResource("extra").toURI()); + IMPLEMENTATIONS_PATH = Paths.get(Resources.getResource("implementations").toURI()); + + UPPER_CAMEL_CASE_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.UpperCamelCaseStrategy.INSTANCE); + LOWER_CAMEL_CASE_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.LowerCamelCaseStrategy.INSTANCE); + SNAKE_CASE_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + + JSON_MAPPER.registerModule(new Jdk8Module()); + YAML_MAPPER.registerModule(new Jdk8Module()); + SimpleModule yamlModule = new SimpleModule(); + yamlModule.addDeserializer(SuperchainConfig.class, new SuperchainConfigDeserializer()); + yamlModule.addDeserializer(ContractImplementations.class, new ContractImplementationsDeserializer()); + yamlModule.addDeserializer(ChainGenesis.class, new ChainGenesisDeserializer()); + yamlModule.addDeserializer(SuperchainLevel.class, new SuperchainLevelDeserializer()); + yamlModule.addDeserializer(ChainConfig.class, new ChainConfigDeserializer()); + YAML_MAPPER.registerModule(yamlModule); + + SimpleModule jsonModule = new SimpleModule(); + jsonModule.addDeserializer(AddressList.class, new AddressListDeserializer()); + JSON_MAPPER.registerModule(jsonModule); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + public static final Map SUPERCHAINS = new HashMap<>(); + + public static final Map OP_CHAINS = new HashMap<>(); + + public static final Map ADDRESSES = new HashMap<>(); + + public static final Map GENESIS_SYSTEM_CONFIGS = new HashMap<>(); + + public static final Map IMPLEMENTATIONS = new HashMap<>(); + + public static void loadConfigs() throws IOException { + final SuperchainConfig[] superchainConfig = {new SuperchainConfig()}; + try (Stream pathStream = Files.list(CONFIGS_PATH)) { + pathStream.filter(Files::isDirectory).forEach(new Consumer() { + @Override + public void accept(Path path) { + String network = path.getFileName().toString(); + List chainIDs = new ArrayList<>(); + try (Stream fileStream = Files.list(path)) { + fileStream.filter(Files::isRegularFile).forEach(new Consumer() { + @Override + public void accept(Path path) { + try { + String content = Files.readString(path, StandardCharsets.UTF_8); + String fileName = path.getFileName().toString(); + if (fileName.equals("superchain.yaml")) { + YAML_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + superchainConfig[0] = YAML_MAPPER.readValue(content, SuperchainConfig.class); + System.out.println(superchainConfig[0]); + return; + } + if (fileName.equals("semver.yaml")) { + // TODO + return; + } + + String chainName = fileName.replaceFirst("[.][^.]+$", ""); + YAML_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + ChainConfig chainConfig = YAML_MAPPER.readValue(content, ChainConfig.class); + chainConfig.setChain(chainName); + chainConfig.setMissingForkConfigs(superchainConfig[0].getHardforkDefaults()); + System.out.println(chainConfig); + + String jsonFileName = chainConfig.getChain() + ".json"; + Path addressesDataFile = Paths.get(String.valueOf(EXTRA_PATH), "addresses", network, jsonFileName); + String addressesData = Files.readString(addressesDataFile, StandardCharsets.UTF_8); + JSON_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE); + AddressList addressList = JSON_MAPPER.readValue(addressesData, AddressList.class); + System.out.println(addressList); + + Path genesisDataFile = Paths.get(String.valueOf(EXTRA_PATH), "genesis-system-configs", network, jsonFileName); + String genesisData = Files.readString(genesisDataFile, StandardCharsets.UTF_8); + JSON_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE); + SystemConfig systemConfig = JSON_MAPPER.readValue(genesisData, SystemConfig.class); + System.out.println(systemConfig); + + long id = chainConfig.getChainId(); + chainConfig.setSuperchain(network); + GENESIS_SYSTEM_CONFIGS.put(id, systemConfig); + ADDRESSES.put(id, addressList); + OP_CHAINS.put(id, chainConfig); + chainIDs.add(id); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + + switch (network) { + case "mainnet": + if (!Strings.isNullOrEmpty(System.getenv("CIRCLE_CI_MAINNET_RPC"))) { + superchainConfig[0].getL1().setPublicRpc(System.getenv("CIRCLE_CI_MAINNET_RPC")); + } + break; + case "sepolia-dev-0", "sepolia": + if (!Strings.isNullOrEmpty(System.getenv("CIRCLE_CI_SEPOLIA_RPC"))) { + superchainConfig[0].getL1().setPublicRpc(System.getenv("CIRCLE_CI_SEPOLIA_RPC")); + } + break; + default: + break; + } + + try { + ContractImplementations contractImplementations = newContractImplementations(network); + IMPLEMENTATIONS.put(network, contractImplementations); + System.out.println(IMPLEMENTATIONS); + + SUPERCHAINS.put(network, new Superchain(superchainConfig[0], chainIDs, network)); + System.out.println(SUPERCHAINS); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + } + + + } + + private static ContractImplementations newContractImplementations(String network) throws IOException { + String implementationsData = Files.readString(Paths.get(String.valueOf(IMPLEMENTATIONS_PATH), "implementations.yaml"), StandardCharsets.UTF_8); + YAML_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + ContractImplementations globalContractImplementations = YAML_MAPPER.readValue(implementationsData, ContractImplementations.class); + + if (Strings.isNullOrEmpty(network)) { + return globalContractImplementations; + } + + String networkImplementationsData = Files.readString(Paths.get(String.valueOf(IMPLEMENTATIONS_PATH), "networks", String.format("%s.yaml", network)), StandardCharsets.UTF_8); + ContractImplementations networkContractImplementations = YAML_MAPPER.readValue(networkImplementationsData, ContractImplementations.class); + + globalContractImplementations.merge(networkContractImplementations); + + return globalContractImplementations; + } +} diff --git a/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainLevelDeserializer.java b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainLevelDeserializer.java new file mode 100644 index 000000000..a31b3b948 --- /dev/null +++ b/bindings/java-bindings/superchain-registry/src/main/java/io/optimism/embed/SuperchainLevelDeserializer.java @@ -0,0 +1,22 @@ +package io.optimism.embed; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import io.optimism.superchain.SuperchainLevel; + +import java.io.IOException; + +/** + * The type Superchainlevel deserializer. + * + * @author grapebaba + * @since 0.1.0 + */ +public class SuperchainLevelDeserializer extends JsonDeserializer { + @Override + public SuperchainLevel deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { + return SuperchainLevel.fromValue((byte) jsonParser.getValueAsInt()); + } +} diff --git a/bindings/java-bindings/superchain-registry/src/test/java/io/optimism/embed/SuperchainConfigsTest.java b/bindings/java-bindings/superchain-registry/src/test/java/io/optimism/embed/SuperchainConfigsTest.java new file mode 100644 index 000000000..c115a8ad3 --- /dev/null +++ b/bindings/java-bindings/superchain-registry/src/test/java/io/optimism/embed/SuperchainConfigsTest.java @@ -0,0 +1,14 @@ +package io.optimism.embed; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; + + +class SuperchainConfigsTest { + + @Test + void loadConfigs() throws IOException { + SuperchainConfigs.loadConfigs(); + } +}