feat[GLIT-67]: add json rpc methods for zkevm

This commit is contained in:
George Qing 2024-01-23 23:19:50 +08:00
parent f55a10b64d
commit b497167264
38 changed files with 815 additions and 32 deletions

16
.github/workflows/docker.sh vendored Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
set -ex
image="ghcr.io/$GITHUB_REPOSITORY"
tag=$(git tag --points-at HEAD)
if [ -z "$tag" ]; then
tag='latest'
fi
echo $image:$tag
docker buildx create --name mybuilder --use || echo 'skip'
docker buildx inspect --bootstrap
docker buildx build --platform linux/amd64,linux/arm64 -t $image:$tag --push .
docker buildx imagetools inspect $image:$tag

23
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,23 @@
name: Docker
on:
workflow_dispatch:
push:
tags:
- v*
jobs:
build:
timeout-minutes: 45
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Login to ghcr.io
env:
PAT: ${{ secrets.GITHUB_TOKEN }}
run: printf "$PAT" | docker login --username _ --password-stdin ghcr.io
- name: Build and push Docker images
run: ./.github/workflows/docker.sh

16
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,16 @@
name: test
on:
workflow_dispatch:
push:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: eth-tests
run: docker compose run --no-TTY --rm test

View file

@ -426,7 +426,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
}
var gasRefund uint64
if !rules.IsLondon {
if !rules.IsLondon && !rules.IsZkEvm {
// Before EIP-3529: refunds were capped to gasUsed / 2
gasRefund = st.refundGas(params.RefundQuotient)
} else {

25
docker-compose.yml Normal file
View file

@ -0,0 +1,25 @@
version: '3.9'
networks:
default:
name: zkevm-geth
services:
build:
build:
dockerfile: docker/retesteth/Dockerfile
command:
retesteth
-t GeneralStateTests
--
--clients zkevm
--filltests
test:
build:
dockerfile: docker/retesteth/Dockerfile-light
command:
retesteth
-t GeneralStateTests
--
--clients zkevm

View file

@ -0,0 +1,40 @@
FROM alpine:3.15 AS base
RUN apk add --no-cache alpine-sdk cmake linux-headers boost-dev boost-static
ENV LDFLAGS="-static"
WORKDIR /build
FROM base as tests
RUN git clone --depth 1 -b zkevm https://github.com/privacy-scaling-explorations/eth-tests.git /tests
FROM base AS retesteth
RUN git clone --depth 1 -b develop https://github.com/ethereum/retesteth.git /retesteth
RUN cmake /retesteth -DCMAKE_BUILD_TYPE=Release && make && cp retesteth/retesteth /target
FROM alpine:3.13 AS lllc
RUN apk add --no-cache alpine-sdk cmake linux-headers boost-dev boost-static
ENV LDFLAGS="-static"
WORKDIR /build
RUN git clone --depth 1 -b master https://github.com/winsvega/solidity.git /lllc
RUN cmake /lllc -DCMAKE_BUILD_TYPE=Release -DLLL=1 && make lllc && cp lllc/lllc /target
FROM base AS solc
RUN git clone --depth 1 -b v0.8.5 https://github.com/ethereum/solidity.git /solidity
RUN touch /solidity/prerelease.txt && cmake /solidity -DCMAKE_BUILD_TYPE=Release && make solc && cp solc/solc /target
FROM golang:1.18-alpine as geth
RUN apk add --no-cache gcc musl-dev linux-headers git
WORKDIR /go-ethereum
COPY go.mod .
COPY go.sum .
RUN go mod download
ADD . .
RUN go run build/ci.go install ./cmd/evm && cp build/bin/evm /target
FROM alpine:3.15
ENV ETHEREUM_TEST_PATH="/tests"
COPY --from=retesteth /target /bin/retesteth
COPY --from=lllc /target /bin/lllc
COPY --from=solc /target /bin/solc
COPY --from=tests /tests /tests
COPY --from=geth /target /bin/evm
COPY docker/retesteth/data /root/.retesteth

View file

@ -0,0 +1,27 @@
FROM alpine:3.15 AS base
RUN apk add --no-cache alpine-sdk cmake linux-headers boost-dev boost-static
ENV LDFLAGS="-static"
WORKDIR /build
FROM base as tests
RUN git clone --depth 1 -b zkevm https://github.com/privacy-scaling-explorations/eth-tests.git /tests
FROM base AS retesteth
RUN git clone --depth 1 -b develop https://github.com/ethereum/retesteth.git /retesteth
RUN cmake /retesteth -DCMAKE_BUILD_TYPE=Release && make && cp retesteth/retesteth /target
FROM golang:1.18-alpine as geth
RUN apk add --no-cache gcc musl-dev linux-headers git
WORKDIR /go-ethereum
COPY go.mod .
COPY go.sum .
RUN go mod download
ADD . .
RUN go run build/ci.go install ./cmd/evm && cp build/bin/evm /target
FROM alpine:3.15
ENV ETHEREUM_TEST_PATH="/tests"
COPY --from=retesteth /target /bin/retesteth
COPY --from=tests /tests /tests
COPY --from=geth /target /bin/evm
COPY docker/retesteth/data /root/.retesteth

View file

@ -0,0 +1 @@
0.2.2-testinfo

View file

@ -0,0 +1,218 @@
{
"name" : "Ethereum GO on StateTool",
"socketType" : "tranition-tool",
"socketAddress" : "start.sh",
"checkLogsHash" : true,
"chainID" : 1,
"forks" : [
"Frontier",
"Homestead",
"EIP150",
"EIP158",
"Byzantium",
"Constantinople",
"ConstantinopleFix",
"Istanbul",
"Berlin",
"ZkEvm",
"London",
"Merge"
],
"additionalForks" : [
"FrontierToHomesteadAt5",
"HomesteadToEIP150At5",
"EIP158ToByzantiumAt5",
"HomesteadToDaoAt5",
"ByzantiumToConstantinopleFixAt5",
"BerlinToLondonAt5",
"ArrowGlacier",
"ArrowGlacierToMergeAtDiffC0000",
"GrayGlacier"
],
"exceptions" : {
"AddressTooShort" : "input string too short for common.Address",
"AddressTooLong" : "rlp: input string too long for common.Address, decoding into (types.Transaction)(types.LegacyTx).To",
"NonceMax" : "nonce exceeds 2^64-1",
"NonceTooLong" : "rlp: input string too long for uint64, decoding into (types.Transaction)(types.LegacyTx).Nonce",
"InvalidVRS" : "invalid transaction v, r, s values",
"InvalidV" : "rlp: expected input string or byte for *big.Int, decoding into (types.Transaction)(types.LegacyTx).V",
"InvalidR" : "rlp: expected input string or byte for *big.Int, decoding into (types.Transaction)(types.LegacyTx).R",
"InvalidS" : "rlp: expected input string or byte for *big.Int, decoding into (types.Transaction)(types.LegacyTx).S",
"InvalidChainID" : "invalid chain id for signer",
"ECRecoveryFail" : "recovery failed",
"InvalidStateRoot" : "",
"ExtraDataTooBig" : "Error importing raw rlp block: Header extraData > 32 bytes",
"InvalidData" : "rlp: expected input string or byte for []uint8, decoding into (types.Transaction)(types.LegacyTx).Data",
"InvalidDifficulty" : "Invalid difficulty:",
"InvalidDifficulty2" : "Error in field: difficulty",
"InvalidDifficulty_TooLarge" : "Blockheader parse error: VALUE >u256",
"InvalidGasLimit" : "Header gasLimit > 0x7fffffffffffffff",
"InvalidGasLimit2" : "Invalid gaslimit:",
"InvalidGasLimit3" : "GasLimit must be < 0x7fffffffffffffff",
"InvalidGasLimit4" : "rlp: input string too long for uint64, decoding into (types.Transaction)(types.LegacyTx).Gas",
"InvalidGasLimit5" : "rlp: expected input string or byte for uint64, decoding into (types.Transaction)(types.LegacyTx).Gas",
"InvalidValue" : "value exceeds 256 bits",
"InvalidGasPrice" : "gasPrice exceeds 256 bits",
"InvalidMaxPriorityFeePerGas" : "maxPriorityFeePerGas exceeds 256 bits",
"InvalidMaxFeePerGas" : "maxFeePerGas exceeds 256 bits",
"InvalidNonce" : "rlp: expected input string or byte for uint64, decoding into (types.Transaction)(types.LegacyTx).Nonce",
"InvalidTo" : "rlp: expected input string or byte for common.Address, decoding into (types.Transaction)(types.LegacyTx).To",
"GasLimitPriceProductOverflow" : "gas * gasPrice exceeds 256 bits",
"TooMuchGasUsed" : "Invalid gasUsed:",
"TooMuchGasUsed2" : "Error importing raw rlp block: t8ntool didn't return a transaction with hash",
"LeadingZerosGasLimit" : "rlp: non-canonical integer (leading zero bytes) for uint64, decoding into (types.Transaction)(types.LegacyTx).Gas",
"LeadingZerosGasPrice" : "rlp: non-canonical integer (leading zero bytes) for *big.Int, decoding into (types.Transaction)(types.LegacyTx).GasPrice",
"LeadingZerosValue" : "rlp: non-canonical integer (leading zero bytes) for *big.Int, decoding into (types.Transaction)(types.LegacyTx).Value",
"LeadingZerosNonce" : "rlp: non-canonical integer (leading zero bytes) for uint64, decoding into (types.Transaction)(types.LegacyTx).Nonce",
"LeadingZerosR" : "rlp: non-canonical integer (leading zero bytes) for *big.Int, decoding into (types.Transaction)(types.LegacyTx).R",
"LeadingZerosS" : "rlp: non-canonical integer (leading zero bytes) for *big.Int, decoding into (types.Transaction)(types.LegacyTx).S",
"LeadingZerosV" : "rlp: non-canonical integer (leading zero bytes) for *big.Int, decoding into (types.Transaction)(types.LegacyTx).V",
"LeadingZerosDataSize" : "rlp: non-canonical size information for []uint8, decoding into (types.Transaction)(types.LegacyTx).Data",
"LeadingZerosNonceSize" : "rlp: non-canonical size information for uint64, decoding into (types.Transaction)(types.LegacyTx).Nonce",
"InvalidNumber" : "BlockHeader number != parent.number + 1",
"InvalidTimestampEqualParent" : "timestamp equals parent's",
"InvalidTimestampOlderParent" : "BlockHeader timestamp is less or equal then it's parent block!",
"InvalidLogBloom" : "Error in field: bloom",
"InvalidStateRoot" : "Error in field: stateRoot",
"InvalidGasUsed" : "Error in field: gasUsed",
"InvalidGasUsed2" : "t8ntool didn't return a transaction with hash",
"InvalidBlockMixHash" : "invalid mix digest",
"InvalidBlockNonce" : "",
"UnknownParent" : "unknown parent hash",
"UnknownParent2" : "unknown parent hash",
"InvalidReceiptsStateRoot" : "Error in field: receiptTrie",
"InvalidTransactionsRoot" : "Error in field: transactionsTrie",
"InvalidUnclesHash" : "Error in field: uncleHash",
"InvalidUncleParentHash" : "Parent block hash not found:",
"UncleInChain" : "Block is already in chain!",
"UncleIsAncestor" : "Block is already in chain!",
"UncleParentIsNotAncestor" : "Uncle number is wrong!",
"TooManyUncles" : "Too many uncles!",
"UncleIsBrother" : "Uncle is brother!",
"OutOfGas" : "out of gas",
"SenderNotEOA" : "sender not an eoa:",
"IntrinsicGas" : "t8ntool didn't return a transaction with hash",
"ExtraDataIncorrectDAO" : "BlockHeader require Dao ExtraData!",
"InvalidTransactionVRS" : "t8ntool didn't return a transaction with hash",
"BLOCKHEADER_VALUE_TOOLARGE" : "Blockheader parse error: VALUE >u256",
"TRANSACTION_VALUE_TOOLARGE" : "TransactionLegacy convertion error: VALUE >u256",
"TRANSACTION_VALUE_TOOSHORT" : "t8ntool didn't return a transaction with hash",
"OVERSIZE_RLP" : "Error importing raw rlp block: OversizeRLP",
"RLP_TooFewElements" : "rlp: too few elements ",
"RLP_TooManyElements" : "rlp: input list has too many elements ",
"RLP_InputContainsMoreThanOneValue" : "Error importing raw rlp block: OversizeRLP",
"RLP_VALUESIZE_MORE_AVAILABLEINPUTLENGTH" : "Error importing raw rlp block: UndersizeRLP",
"RLP_ELEMENT_LARGER_CONTAININGLIST_UNDERSIZE" : "Error importing raw rlp block: UndersizeRLP",
"RLP_ELEMENT_LARGER_CONTAININGLIST_OVERSIZE" : "Error importing raw rlp block: OversizeRLP",
"RLP_ExpectedInputList_EXTBLOCK" : "Error importing raw rlp block: RLP is expected to be list",
"RLP_InvalidArg0_UNMARSHAL_BYTES" : "Error importing raw rlp block: BadCast",
"RLP_ExpectedInputList_HEADER_DECODEINTO_BLOCK_EXTBLOCK" : "Error importing raw rlp block: BlockHeader RLP is expected to be list",
"RLP_InputList_TooManyElements_HEADER_DECODEINTO_BLOCK_EXTBLOCK_HEADER" : "Error importing raw rlp block: Uncleheader RLP is expected to be list",
"RLP_InputList_TooManyElements_TXDATA_DECODEINTO_BLOCK_EXTBLOCK_TXS0" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooShort_ADDRESS_DECODEINTO_BLOCK_EXTBLOCK_HEADER_COINBASE" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooShort_ADDRESS_DECODEINTO_BLOCK_EXTBLOCK_HEADER_COINBASE2" : "Blockheader parse error: Key `coinbase` is not hash20",
"RLP_InputString_TooShort_ADDRESS_DECODEINTO_BLOCK_EXTBLOCK_TXS0_RECIPIENT" : "TransactionLegacy convertion error: Key `to` is not hash20",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_ROOT" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_ROOT2" : "Blockheader parse error: Key `stateRoot` is not hash32",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_MIXDIGEST" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_MIXDIGEST2" : "Blockheader parse error: Key `mixHash` is not hash32",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_PARENTHASH" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_PARENTHASH2" : "Blockheader parse error: Key `parentHash` is not hash32",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_RECEIPTHASH" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_RECEIPTHASH2" : "Blockheader parse error: Key `receiptTrie` is not hash32",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_TXHASH" : "Blockheader parse error: Key `transactionsTrie` is not hash32",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_UNCLEHASH" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooLong_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_UNCLEHASH2" : "Blockheader parse error: Key `uncleHash` is not hash32",
"RLP_InputString_TooLong_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_GASLIMIT" : "Blockheader parse error: VALUE >u256",
"RLP_InputString_TooLong_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_GASUSED" : "Blockheader parse error: VALUE >u256",
"RLP_InputString_TooLong_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_TIME" : "Blockheader parse error: VALUE >u256",
"RLP_InputString_TooLong_UINT64_DECODEINTO_BLOCK_EXTBLOCK_TXS0_GASLIMIT" : "TransactionLegacy convertion error: VALUE >u256",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_RECEIPTHASH" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_RECEIPTHASH2" : "Blockheader parse error: Key `receiptTrie` is not hash32",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_ROOT" : "Blockheader parse error: Key `stateRoot` is not hash32",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_MIXDIGEST" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_MIXDIGEST2" : "Blockheader parse error: Key `mixHash` is not hash32",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_PARENTHASH" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_PARENTHASH2" : "Blockheader parse error: Key `parentHash` is not hash32",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_UNCLEHASH" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_UNCLEHASH2" : "Blockheader parse error: Key `uncleHash` is not hash32",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_TXHASH" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooShort_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_TXHASH2" : "Blockheader parse error: Key `transactionsTrie` is not hash32",
"RLP_InputString_TooShort_BLOOM_DECODEINTO_BLOCK_EXTBLOCK_HEADER_BLOOM" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_HEADER_DIFFICULTY" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_HEADER_DIFFICULTY2" : "Blockheader parse error: VALUE has leading 0",
"RLP_NonCanonicalINT_LeadingZeros_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_GASLIMIT" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_GASLIMIT2" : "Blockheader parse error: VALUE has leading 0",
"RLP_NonCanonicalINT_LeadingZeros_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_GASUSED" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_GASUSED2" : "Blockheader parse error: VALUE has leading 0",
"RLP_NonCanonicalINT_LeadingZeros_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_TIME" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_TIME2" : "Blockheader parse error: VALUE has leading 0",
"RLP_NonCanonicalINT_LeadingZeros_UINT64_DECODEINTO_BLOCK_EXTBLOCK_TXS0_GASLIMIT" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_UINT64_DECODEINTO_BLOCK_EXTBLOCK_TXS0_GASLIMIT2" : "TransactionLegacy convertion error: VALUE has leading 0",
"RLP_NonCanonicalINT_LeadingZeros_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_HEADER_NUMBER" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_HEADER_NUMBER2" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_TXS0_TXDATA_PRICE" : "Error importing raw rlp block: OversizeRLP",
"RLP_NonCanonicalINT_LeadingZeros_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_TXS0_TXDATA_R" : "TransactionLegacy convertion error: VALUE has leading 0",
"RLP_NonCanonicalINT_LeadingZeros_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_TXS0_TXDATA_S" : "TransactionLegacy convertion error: VALUE has leading 0",
"RLP_InputString_TooLong_BLOOM_DECODEINTO_BLOCK_EXTBLOCK_HEADER_BLOOM" : "Blockheader parse error: Key `bloom` is not hash256",
"RLP_ExpectedInputString_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_PARENTHASH" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_RECEIPTHASH" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_ROOT" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_MIXDIGEST" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_TXHASH" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_HASH_DECODEINTO_BLOCK_EXTBLOCK_HEADER_UNCLEHASH" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_ADDRESS_DECODEINTO_BLOCK_EXTBLOCK_HEADER_COINBASE" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_ADDRESS_DECODEINTO_BLOCK_EXTBLOCK_TX0_RECIPIENT" : "Error importing raw rlp block: Transaction RLP field is not data!",
"RLP_InputString_TooLong_ADDRESS_DECODEINTO_BLOCK_EXTBLOCK_HEADER_COINBASE" : "Blockheader parse error: Key `coinbase` is not hash20",
"RLP_InputString_TooLong_ADDRESS_DECODEINTO_BLOCK_EXTBLOCK_TXS0_RECIPIENT" : "TransactionLegacy convertion error: Key `to` is not hash20",
"RLP_ExpectedInputString_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_HEADER_DIFFICULTY" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_TXS0_TXR" : "Error importing raw rlp block: Transaction RLP field is not data!",
"RLP_ExpectedInputString_BIGINT_DECODEINTO_BLOCK_EXTBLOCK_TXS0_TXS" : "Error importing raw rlp block: Transaction RLP field is not data!",
"RLP_ExpectedInputString_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_GASLIMIT" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_GASUSED" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_UINT64_DECODEINTO_BLOCK_EXTBLOCK_HEADER_TIME" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_UINT64_DECODEINTO_BLOCK_EXTBLOCK_TXS0_GASLIMIT" : "Error importing raw rlp block: Transaction RLP field is not data!",
"RLP_ExpectedInputString_NONCE_DECODEINTO_BLOCK_EXTBLOCK_HEADER_NONCE" : "Error importing raw rlp block: Blockheader RLP field is not data!",
"RLP_ExpectedInputString_UINT8_DECODEINTO_BLOCK_EXTBLOCK_TXS0_PAYLOAD" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooLong_BLOCKNONCE_DECODEINTO_BLOCK_EXTBLOCK_HEADER_NONCE" : "Error importing raw rlp block: OversizeRLP",
"RLP_InputString_TooLong_BLOCKNONCE_DECODEINTO_BLOCK_EXTBLOCK_HEADER_NONCE2" : "Blockheader parse error: Key `nonce` is not hash8",
"RLP_NonCanonical_SizeInfo_EXTBLOCK" : "Error importing raw rlp block: BadRLP",
"RLP_ExpectedInputList_TRANSACTION_DECODEINTO_BLOCK_EXTBLOCK_TXS" : "Error importing raw rlp block: BadCast",
"RLP_ExpectedInputList_HEADER_DECODEINTO_BLOCK_EXTBLOCK_UNCLES" : "Error importing raw rlp block: OversizeRLP",
"RLP_ExpectedInputList_TXDATA_DECODEINTO_BLOCK_EXTBLOCK_TXS0" : "Error importing raw rlp block: Transaction RLP is expected to be list",
"RLP_Error_EOF" : "ERROR(11): unexpected EOF",
"RLP_Error_RLP_Size" : "ERROR(11): rlp: value size exceeds available input length",
"RLP_Error_Size_Information" : "ERROR(11): rlp: non-canonical size information",
"LegacyBlockImportImpossible" : "Legacy block import is impossible",
"LegacyBlockImportImpossible2" : "Legacy block can only be on top of LegacyBlock",
"LegacyBlockBaseFeeTransaction" : "BaseFee transaction in a Legacy blcok",
"1559BlockImportImpossible_HeaderIsLegacy" : "1559 block must be on top of 1559",
"1559BlockImportImpossible_BaseFeeWrong": "base fee not correct!",
"1559BlockImportImpossible_InitialBaseFeeWrong": "Initial baseFee must be 1000000000",
"1559BlockImportImpossible_TargetGasLow": "gasTarget decreased too much",
"1559BlockImportImpossible_TargetGasHigh": "gasTarget increased too much",
"1559BlockImportImpossible_InitialGasLimitInvalid": "Invalid block1559: Initial gasLimit must be",
"TR_IntrinsicGas" : "intrinsic gas too low:",
"TR_NoFunds" : "insufficient funds for gas * price + value",
"TR_NoFundsValue" : "insufficient funds for transfer",
"TR_FeeCapLessThanBlocks" : "max fee per gas less than block base fee",
"TR_GasLimitReached" : "gas limit reached",
"TR_NonceTooHigh" : "nonce too high",
"TR_NonceTooLow" : "nonce too low",
"TR_TypeNotSupported" : "transaction type not supported",
"TR_TipGtFeeCap": "max priority fee per gas higher than max fee per gas",
"TR_TooShort": "typed transaction too short",
"1559BaseFeeTooLarge": "TransactionBaseFee convertion error: VALUE >u256",
"1559PriorityFeeGreaterThanBaseFee": "maxFeePerGas \u003c maxPriorityFeePerGas",
"2930AccessListAddressTooLong": "rlp: input string too long for common.Address, decoding into (types.Transaction)(types.AccessListTx).AccessList[0].Address",
"2930AccessListAddressTooShort": "rlp: input string too short for common.Address, decoding into (types.Transaction)(types.AccessListTx).AccessList[0].Address",
"2930AccessListStorageHashTooLong": "rlp: input string too long for common.Hash, decoding into (types.Transaction)(types.AccessListTx).AccessList[0].StorageKeys[0]",
"1559LeadingZerosBaseFee": "rlp: non-canonical integer (leading zero bytes) for *big.Int, decoding into (types.Transaction)(types.DynamicFeeTx).GasFeeCap",
"1559LeadingZerosPriorityFee": "rlp: non-canonical integer (leading zero bytes) for *big.Int, decoding into (types.Transaction)(types.DynamicFeeTx).GasTipCap",
"2930AccessListStorageHashTooShort": "rlp: input string too short for common.Hash, decoding into (types.Transaction)(types.AccessListTx).AccessList[0].StorageKeys[0]",
"2930AccessListStorageHashTooLong": "rlp: input string too long for common.Hash, decoding into (types.Transaction)(types.AccessListTx).AccessList[0].StorageKeys[0]",
"3675PoWBlockRejected" : "Invalid block1559: Chain switched to PoS!",
"3675PoSBlockRejected" : "Parent (transition) block has not reached TTD",
"3675PreMerge1559BlockRejected" : "Trying to import 1559 block on top of PoS block"
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork" : "ArrowGlacier",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,11 @@
{
"params" : {
"fork" : "ArrowGlacierToMergeAtDiffC0000",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00",
"terminalTotalDifficulty" : "0x0C0000"
},
"accounts" : {
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork": "Berlin",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,11 @@
{
"params" : {
"fork" : "BerlinToLondonAt5",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00",
"londonForkBlock" : "0x05"
},
"accounts" : {
}
}

View file

@ -0,0 +1,9 @@
{
"params" : {
"fork" : "Byzantium",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork" : "ByzantiumToConstantinopleFixAt5",
"constantinopleForkBlock" : "0x05",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork" : "Constantinople",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork" : "ConstantinopleFix",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,8 @@
{
"params" : {
"fork" : "EIP150",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,8 @@
{
"params" : {
"fork" : "EIP158",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,9 @@
{
"params" : {
"fork" : "EIP158ToByzantiumAt5",
"byzantiumForkBlock" : "0x05",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,7 @@
{
"params" : {
"fork" : "Frontier"
},
"accounts" : {
}
}

View file

@ -0,0 +1,8 @@
{
"params" : {
"fork" : "FrontierToHomesteadAt5",
"homesteadForkBlock" : "0x05"
},
"accounts" : {
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork" : "GrayGlacier",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,8 @@
{
"params" : {
"fork" : "Homestead",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,8 @@
{
"params" : {
"fork" : "HomesteadToDaoAt5",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,8 @@
{
"params" : {
"fork" : "HomesteadToEIP150At5",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork" : "Istanbul",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork" : "London",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,11 @@
{
"params" : {
"fork" : "Merged",
"terminalTotalDifficulty" : "0x00",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,10 @@
{
"params" : {
"fork": "ZkEvm",
"constantinopleForkBlock" : "0x00",
"byzantiumForkBlock" : "0x00",
"homesteadForkBlock" : "0x00"
},
"accounts" : {
}
}

View file

@ -0,0 +1,25 @@
{
"//comment" : "State Tests does not calculate mining reward in post conditions, so when filling a blockchain test out of it, the mining reward must be set",
"Frontier": "5000000000000000000",
"Homestead": "5000000000000000000",
"EIP150": "5000000000000000000",
"EIP158": "5000000000000000000",
"Byzantium": "3000000000000000000",
"Constantinople": "2000000000000000000",
"ConstantinopleFix": "2000000000000000000",
"Istanbul": "2000000000000000000",
"Berlin" : "2000000000000000000",
"London" : "2000000000000000000",
"ArrowGlacier" : "2000000000000000000",
"GrayGlacier" : "2000000000000000000",
"ZkEvm" : "2000000000000000000",
"//comment" : "Retesteth calculate rewards on behalf of the tool when filling state tests",
"YOLOv1" : "2000000000000000000",
"YOLOv2" : "2000000000000000000",
"YOLOv3" : "2000000000000000000",
"Aleut" : "2000000000000000000",
"Merge" : "0",
"Merged" : "0"
}

View file

@ -0,0 +1,17 @@
#!/bin/sh
if [ $1 = "-v" ]; then
/bin/evm -v
else
stateProvided=0
for index in ${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9} ${10} ${11} ${12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} ${20} ; do
if [ $index = "--input.alloc" ]; then
stateProvided=1
break
fi
done
if [ $stateProvided -eq 1 ]; then
/bin/evm t8n ${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9} ${10} ${11} ${12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} ${20} --verbosity 2
else
/bin/evm t9n ${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9} ${10} ${11} ${12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} ${20}
fi
fi

View file

@ -17,11 +17,14 @@
package eth
import (
"fmt"
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi"
)
// MinerAPI provides an API to control the miner.
@ -83,3 +86,68 @@ func (api *MinerAPI) SetEtherbase(etherbase common.Address) bool {
func (api *MinerAPI) SetRecommitInterval(interval int) {
api.e.Miner().SetRecommitInterval(time.Duration(interval) * time.Millisecond)
}
// Init initializes the miner without starting mining tasks
func (api *MinerAPI) Init() (common.Address, error) {
return api.e.InitMiner()
}
type SealBlockRequest struct {
Parent common.Hash `json:"parent" gencodec:"required"`
Random common.Hash `json:"random" gencodec:"required"`
Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Transactions []hexutil.Bytes `json:"transactions" gencodec:"optional"`
}
func decodeTransactions(enc []hexutil.Bytes) ([]*types.Transaction, error) {
var txs = make([]*types.Transaction, len(enc))
for i, encTx := range enc {
var tx types.Transaction
if err := tx.UnmarshalBinary(encTx); err != nil {
return nil, fmt.Errorf("invalid transaction %d: %v", i, err)
}
txs[i] = &tx
}
return txs, nil
}
// SealBlock mines and seals a block without changing the canonical chain
// If `args.Transactions` is not nil then produces a block with only those transactions. If nil, then it consumes from the transaction pool.
// Returns the block if successful.
func (api *MinerAPI) SealBlock(args SealBlockRequest) (map[string]interface{}, error) {
var transactions []*types.Transaction
if args.Transactions != nil {
txs, err := decodeTransactions(args.Transactions)
if err != nil {
return nil, err
}
transactions = txs
}
block, err := api.e.Miner().SealBlockWith(args.Parent, args.Random, uint64(args.Timestamp), transactions)
if err != nil {
return nil, err
}
return ethapi.RPCMarshalBlock(block, true, true, api.e.APIBackend.ChainConfig()), nil
}
// SetHead updates the canonical chain and announces the block on the p2p layer
func (api *MinerAPI) SetHead(hash common.Hash) (bool, error) {
block := api.e.BlockChain().GetBlockByHash(hash)
if block == nil {
return false, fmt.Errorf("block %s not found", hash.Hex())
}
if _, err := api.e.BlockChain().SetCanonical(block); err != nil {
return false, err
}
// Broadcast the block and announce chain insertion event
api.e.Miner().AnnounceBlock(block)
return true, nil
}

View file

@ -414,45 +414,56 @@ func (s *Ethereum) SetEtherbase(etherbase common.Address) {
s.miner.SetEtherbase(etherbase)
}
// InitMiner initializes the miner without starting mining tasks
func (s *Ethereum) InitMiner() (eb common.Address, err error) {
// Propagate the initial price point to the transaction pool
s.lock.RLock()
price := s.gasPrice
s.lock.RUnlock()
s.txPool.SetGasTip(price)
// Configure the local mining address
eb, err = s.Etherbase()
if err != nil {
log.Error("Cannot start mining without etherbase", "err", err)
return eb, fmt.Errorf("etherbase missing: %v", err)
}
var cli *clique.Clique
if c, ok := s.engine.(*clique.Clique); ok {
cli = c
} else if cl, ok := s.engine.(*beacon.Beacon); ok {
if c, ok := cl.InnerEngine().(*clique.Clique); ok {
cli = c
}
}
if cli != nil {
wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "err", err)
return eb, fmt.Errorf("signer missing: %v", err)
}
cli.Authorize(eb, wallet.SignData)
}
s.miner.SetEtherbase(eb)
// If mining is initialized, we can disable the transaction rejection mechanism
// introduced to speed sync times.
s.handler.enableSyncedFeatures()
return eb, nil
}
// StartMining starts the miner with the given number of CPU threads. If mining
// is already running, this method adjust the number of threads allowed to use
// and updates the minimum price required by the transaction pool.
func (s *Ethereum) StartMining() error {
// If the miner was not running, initialize it
if !s.IsMining() {
// Propagate the initial price point to the transaction pool
s.lock.RLock()
price := s.gasPrice
s.lock.RUnlock()
s.txPool.SetGasTip(price)
// Configure the local mining address
eb, err := s.Etherbase()
eb, err := s.InitMiner()
if err != nil {
log.Error("Cannot start mining without etherbase", "err", err)
return fmt.Errorf("etherbase missing: %v", err)
return err
}
var cli *clique.Clique
if c, ok := s.engine.(*clique.Clique); ok {
cli = c
} else if cl, ok := s.engine.(*beacon.Beacon); ok {
if c, ok := cl.InnerEngine().(*clique.Clique); ok {
cli = c
}
}
if cli != nil {
wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "err", err)
return fmt.Errorf("signer missing: %v", err)
}
cli.Authorize(eb, wallet.SignData)
}
// If mining is started, we can disable the transaction rejection mechanism
// introduced to speed sync times.
s.handler.enableSyncedFeatures()
go s.miner.Start()
go s.miner.Start(eb)
}
return nil
}

View file

@ -244,3 +244,14 @@ func (miner *Miner) SubscribePendingLogs(ch chan<- []*types.Log) event.Subscript
func (miner *Miner) BuildPayload(args *BuildPayloadArgs) (*Payload, error) {
return miner.worker.buildPayload(args)
}
// SealBlock mines and seals a block without changing the canonical chain.
// If `txs` is not nil then produces a block with only those transactions. If nil, then it consumes from the transaction pool.
func (miner *Miner) SealBlockWith(parent common.Hash, random common.Hash, timestamp uint64, txs []*types.Transaction) (*types.Block, error) {
return miner.worker.sealBlockWith(parent, random, timestamp, txs)
}
// AnnounceBlock broadcasts the block and emits a chain insertion event
func (miner *Miner) AnnounceBlock(block *types.Block) error {
return miner.worker.mux.Post(core.NewMinedBlockEvent{Block: block})
}

View file

@ -1212,3 +1212,53 @@ func signalToErr(signal int32) error {
panic(fmt.Errorf("undefined signal %d", signal))
}
}
// sealBlockWith mines and seals a block without changing the canonical chain
// If `txs` is not nil then produces a block with only those transactions. If nil, then it consumes from the transaction pool.
func (w *worker) sealBlockWith(parent common.Hash, random common.Hash, timestamp uint64, txs []*types.Transaction) (*types.Block, error) {
params := &generateParams{
timestamp: timestamp,
forceTime: true,
parentHash: parent,
coinbase: w.coinbase,
random: random,
}
env, err := w.prepareWork(params)
if err != nil {
return nil, err
}
defer env.discard()
if txs == nil {
w.fillTransactions(nil, env)
} else {
gasLimit := env.header.GasLimit
env.gasPool = new(core.GasPool).AddGas(gasLimit)
for _, tx := range txs {
env.state.SetTxContext(tx.Hash(), env.tcount)
if _, err := w.commitTransaction(env, tx); err != nil {
return nil, err
}
env.tcount++
}
}
block, err := w.engine.FinalizeAndAssemble(w.chain, env.header, env.state, env.txs, nil, env.receipts, nil)
if err != nil {
return nil, err
}
results := make(chan *types.Block, 1)
if err := w.engine.Seal(w.chain, block, results, nil); err != nil {
return nil, err
}
block = <-results
// Use InsertBlock... here to verify the block again to avoid inserting a sealed but invalid block
if err := w.chain.InsertBlockWithoutSetHead(block); err != nil {
return nil, err
}
return block, nil
}

View file

@ -155,6 +155,7 @@ var (
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: nil,
ZkEvmBlock: nil,
ShanghaiTime: nil,
CancunTime: nil,
PragueTime: nil,
@ -205,6 +206,7 @@ var (
ArrowGlacierBlock: nil,
GrayGlacierBlock: nil,
MergeNetsplitBlock: nil,
ZkEvmBlock: nil,
ShanghaiTime: nil,
CancunTime: nil,
PragueTime: nil,
@ -235,6 +237,7 @@ var (
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: nil,
ZkEvmBlock: nil,
ShanghaiTime: nil,
CancunTime: nil,
PragueTime: nil,
@ -265,6 +268,7 @@ var (
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0),
ZkEvmBlock: big.NewInt(0),
ShanghaiTime: newUint64(0),
CancunTime: newUint64(0),
PragueTime: nil,
@ -295,6 +299,7 @@ var (
ArrowGlacierBlock: nil,
GrayGlacierBlock: nil,
MergeNetsplitBlock: nil,
ZkEvmBlock: nil,
ShanghaiTime: nil,
CancunTime: nil,
PragueTime: nil,
@ -343,6 +348,7 @@ type ChainConfig struct {
ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` // Eip-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter
ZkEvmBlock *big.Int `json:"zkEvmBlock,omitempty"` // zkevm switch block (nil = no fork, 0 = already activated)
// Fork scheduling was switched from blocks to timestamps here
@ -457,6 +463,11 @@ func (c *ChainConfig) Description() string {
banner += fmt.Sprintf(" - Merge netsplit block: #%-8v\n", c.MergeNetsplitBlock)
}
}
if c.ZkEvmBlock != nil {
banner += fmt.Sprintf("\nzkEVM enabled at block: %-8v\n", c.ZkEvmBlock)
}
banner += "\n"
// Create a list of forks post-merge
@ -556,6 +567,18 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi
return parentTotalDiff.Cmp(c.TerminalTotalDifficulty) < 0 && totalDiff.Cmp(c.TerminalTotalDifficulty) >= 0
}
// IsZkEvm returns whether num is either equal to or greater for zkevm specific behaviour.
// zkevm inherits the `berlin` rules but selectively disables:
// - EIP-2718: Typed Transaction Envelope
// - EIP-2930: Optional access lists
//
// In addition, zkevm enables these EIPs included in `london`:
// - EIP-3541: Reject new contracts starting with the 0xEF byte
// - EIP-3529: Reduction in refunds
func (c *ChainConfig) IsZkEvm(num *big.Int) bool {
return isBlockForked(c.ZkEvmBlock, num)
}
// IsShanghai returns whether time is either equal to the Shanghai fork time or greater.
func (c *ChainConfig) IsShanghai(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.ShanghaiTime, time)
@ -882,6 +905,7 @@ type Rules struct {
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
IsBerlin, IsLondon bool
IsMerge, IsShanghai, IsCancun, IsPrague bool
IsZkEvm bool
IsVerkle bool
}
@ -904,6 +928,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsBerlin: c.IsBerlin(num),
IsLondon: c.IsLondon(num),
IsMerge: isMerge,
IsZkEvm: c.IsZkEvm(num),
IsShanghai: c.IsShanghai(num, timestamp),
IsCancun: c.IsCancun(num, timestamp),
IsPrague: c.IsPrague(num, timestamp),

View file

@ -299,6 +299,20 @@ var Forks = map[string]*params.ChainConfig{
TerminalTotalDifficulty: big.NewInt(0),
ShanghaiTime: u64(15_000),
},
"ZkEvm": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
ZkEvmBlock: big.NewInt(0),
},
"Cancun": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),