mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
Merge tag 'v2.0.3' into release/polygon-2.x-fh3.0
This commit is contained in:
commit
6d7329f1a3
401 changed files with 8934 additions and 3774 deletions
2
.github/ISSUE_TEMPLATE/bug.md
vendored
2
.github/ISSUE_TEMPLATE/bug.md
vendored
|
|
@ -20,7 +20,7 @@ Heimdall client version: [e.g. v0.2.10] <!--Can be found by running the command
|
||||||
|
|
||||||
OS & Version: Windows / Linux / OSX
|
OS & Version: Windows / Linux / OSX
|
||||||
|
|
||||||
Environment: Polygon Mainnet / Polygon Mumbai / Polygon Amoy / Devnet
|
Environment: Polygon Mainnet / Polygon Amoy / Devnet
|
||||||
|
|
||||||
Type of node: Validator / Sentry / Archive
|
Type of node: Validator / Sentry / Archive
|
||||||
|
|
||||||
|
|
|
||||||
38
.github/matic-cli-config.yml
vendored
38
.github/matic-cli-config.yml
vendored
|
|
@ -1,26 +1,38 @@
|
||||||
defaultStake: 10000
|
devnetType: docker
|
||||||
|
|
||||||
defaultFee: 2000
|
defaultFee: 2000
|
||||||
|
defaultStake: 10000
|
||||||
|
|
||||||
borChainId: 15001
|
borChainId: 15001
|
||||||
heimdallChainId: heimdall-15001
|
heimdallChainId: heimdall-15001
|
||||||
contractsBranch: mardizzone/node-16
|
|
||||||
|
borDockerBuildContext: '../../bor'
|
||||||
|
heimdallDockerBuildContext: 'https://github.com/maticnetwork/heimdall.git#develop'
|
||||||
|
|
||||||
genesisContractsBranch: master
|
genesisContractsBranch: master
|
||||||
sprintSize:
|
contractsRepo: https://github.com/0xPolygon/pos-contracts.git
|
||||||
- '64'
|
contractsBranch: anvil-pos
|
||||||
blockNumber:
|
|
||||||
- '0'
|
|
||||||
blockTime:
|
blockTime:
|
||||||
- '2'
|
- '2'
|
||||||
|
blockNumber:
|
||||||
|
- '0'
|
||||||
|
|
||||||
|
sprintSize:
|
||||||
|
- '64'
|
||||||
|
sprintSizeBlockNumber:
|
||||||
|
- '0'
|
||||||
|
|
||||||
numOfBorValidators: 3
|
numOfBorValidators: 3
|
||||||
numOfBorSentries: 0
|
numOfBorSentries: 0
|
||||||
numOfBorArchiveNodes: 0
|
numOfBorArchiveNodes: 0
|
||||||
|
|
||||||
|
devnetBorFlags: config,config,config
|
||||||
|
|
||||||
numOfErigonValidators: 0
|
numOfErigonValidators: 0
|
||||||
numOfErigonSentries: 0
|
numOfErigonSentries: 0
|
||||||
numOfErigonArchiveNodes: 0
|
numOfErigonArchiveNodes: 0
|
||||||
ethURL: http://ganache:9545
|
|
||||||
|
ethURL: http://anvil:9545
|
||||||
ethHostUser: ubuntu
|
ethHostUser: ubuntu
|
||||||
devnetType: docker
|
mnemonic: 'clock radar mass judge dismiss just intact mind resemble fringe diary casino'
|
||||||
borDockerBuildContext: "../../bor"
|
|
||||||
heimdallDockerBuildContext: "https://github.com/maticnetwork/heimdall.git#develop"
|
|
||||||
sprintSizeBlockNumber:
|
|
||||||
- '0'
|
|
||||||
devnetBorFlags: config,config,config
|
|
||||||
|
|
|
||||||
2
.github/no-response.yml
vendored
2
.github/no-response.yml
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
# Number of days of inactivity before an Issue is closed for lack of response
|
# Number of days of inactivity before an Issue is closed for lack of response
|
||||||
daysUntilClose: 30
|
daysUntilClose: 30
|
||||||
# Label requiring a response
|
# Label requiring a response
|
||||||
responseRequiredLabel: "need:more-information"
|
responseRequiredLabel: 'need:more-information'
|
||||||
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
|
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
|
||||||
closeComment: >
|
closeComment: >
|
||||||
This issue has been automatically closed because there has been no response
|
This issue has been automatically closed because there has been no response
|
||||||
|
|
|
||||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
|
|
@ -39,7 +39,7 @@ In case this PR includes changes that must be applied only to a subset of nodes,
|
||||||
- [ ] I have added tests to CI
|
- [ ] I have added tests to CI
|
||||||
- [ ] I have tested this code manually on local environment
|
- [ ] I have tested this code manually on local environment
|
||||||
- [ ] I have tested this code manually on remote devnet using express-cli
|
- [ ] I have tested this code manually on remote devnet using express-cli
|
||||||
- [ ] I have tested this code manually on mumbai/amoy
|
- [ ] I have tested this code manually on amoy
|
||||||
- [ ] I have created new e2e tests into express-cli
|
- [ ] I have created new e2e tests into express-cli
|
||||||
|
|
||||||
### Manual tests
|
### Manual tests
|
||||||
|
|
|
||||||
2
.github/stale.yml
vendored
2
.github/stale.yml
vendored
|
|
@ -7,7 +7,7 @@ exemptLabels:
|
||||||
- pinned
|
- pinned
|
||||||
- security
|
- security
|
||||||
# Label to use when marking an issue as stale
|
# Label to use when marking an issue as stale
|
||||||
staleLabel: "status:inactive"
|
staleLabel: 'status:inactive'
|
||||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||||
markComment: >
|
markComment: >
|
||||||
This issue has been automatically marked as stale because it has not had
|
This issue has been automatically marked as stale because it has not had
|
||||||
|
|
|
||||||
14
.github/workflows/amoy_deb_profiles.yml
vendored
14
.github/workflows/amoy_deb_profiles.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write
|
||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
@ -29,7 +29,6 @@ jobs:
|
||||||
NUMERIC_VERSION=$( echo ${{ env.GIT_TAG }} | sed 's/[^0-9.]//g' )
|
NUMERIC_VERSION=$( echo ${{ env.GIT_TAG }} | sed 's/[^0-9.]//g' )
|
||||||
echo "VERSION=$NUMERIC_VERSION" >> $GITHUB_ENV
|
echo "VERSION=$NUMERIC_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
|
||||||
- name: Making directory structure for yaml
|
- name: Making directory structure for yaml
|
||||||
run: mkdir -p packaging/deb/bor/var/lib/bor
|
run: mkdir -p packaging/deb/bor/var/lib/bor
|
||||||
- name: making directory structure for the systemd
|
- name: making directory structure for the systemd
|
||||||
|
|
@ -391,14 +390,3 @@ jobs:
|
||||||
packaging/deb/bor-pbss-amoy-**.deb
|
packaging/deb/bor-pbss-amoy-**.deb
|
||||||
packaging/deb/bor-amoy-**.deb.checksum
|
packaging/deb/bor-amoy-**.deb.checksum
|
||||||
packaging/deb/bor-pbss-amoy-**.deb.checksum
|
packaging/deb/bor-pbss-amoy-**.deb.checksum
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
61
.github/workflows/ci.yml
vendored
61
.github/workflows/ci.yml
vendored
|
|
@ -2,12 +2,12 @@ name: CI
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "master"
|
- 'master'
|
||||||
- "qa"
|
- 'qa'
|
||||||
- "develop"
|
- 'develop'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- "**"
|
- '**'
|
||||||
types: [opened, synchronize]
|
types: [opened, synchronize]
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
|
|
@ -16,11 +16,14 @@ concurrency:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
name: Build
|
||||||
|
|
||||||
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-20.04 ] # list of os: https://github.com/actions/virtual-environments
|
os: [ubuntu-22.04] # List of OS: https://github.com/actions/virtual-environments
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: |
|
- run: |
|
||||||
|
|
@ -51,7 +54,7 @@ jobs:
|
||||||
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-20.04 ] # list of os: https://github.com/actions/virtual-environments
|
os: [ubuntu-22.04] # List of OS: https://github.com/actions/virtual-environments
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -79,7 +82,7 @@ jobs:
|
||||||
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-20.04 ] # list of os: https://github.com/actions/virtual-environments
|
os: [ubuntu-22.04] # List of OS: https://github.com/actions/virtual-environments
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -130,7 +133,7 @@ jobs:
|
||||||
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-20.04 ] # list of os: https://github.com/actions/virtual-environments
|
os: [ubuntu-22.04] # List of OS: https://github.com/actions/virtual-environments
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -167,7 +170,7 @@ jobs:
|
||||||
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-20.04 ] # list of os: https://github.com/actions/virtual-environments
|
os: [ubuntu-22.04] # List of OS: https://github.com/actions/virtual-environments
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: [unit-tests, integration-tests]
|
needs: [unit-tests, integration-tests]
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -182,7 +185,7 @@ jobs:
|
||||||
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
if: (github.event.action != 'closed' || github.event.pull_request.merged == true)
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-20.04 ] # list of os: https://github.com/actions/virtual-environments
|
os: [ubuntu-22.04] # List of OS: https://github.com/actions/virtual-environments
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -211,9 +214,7 @@ jobs:
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install build-essential
|
sudo apt install build-essential
|
||||||
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
|
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
|
||||||
sudo snap install solc
|
sudo apt install jq curl
|
||||||
sudo apt install python2 jq curl
|
|
||||||
sudo ln -sf /usr/bin/python2 /usr/bin/python
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
|
|
@ -225,6 +226,23 @@ jobs:
|
||||||
matic-cli/devnet/code/genesis-contracts/package-lock.json
|
matic-cli/devnet/code/genesis-contracts/package-lock.json
|
||||||
matic-cli/devnet/code/genesis-contracts/matic-contracts/package-lock.json
|
matic-cli/devnet/code/genesis-contracts/matic-contracts/package-lock.json
|
||||||
|
|
||||||
|
- name: Install solc-select
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install python3 python3-pip -y
|
||||||
|
sudo ln -sf /usr/bin/python3 /usr/bin/python
|
||||||
|
pip install solc-select
|
||||||
|
|
||||||
|
- name: Install Solidity Version
|
||||||
|
run: |
|
||||||
|
solc-select install 0.5.17
|
||||||
|
solc-select install 0.6.12
|
||||||
|
solc-select use 0.5.17
|
||||||
|
solc --version
|
||||||
|
|
||||||
|
- name: Install Foundry
|
||||||
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
|
|
||||||
- name: Bootstrap devnet
|
- name: Bootstrap devnet
|
||||||
run: |
|
run: |
|
||||||
cd matic-cli
|
cd matic-cli
|
||||||
|
|
@ -242,14 +260,21 @@ jobs:
|
||||||
|
|
||||||
- name: Run smoke tests
|
- name: Run smoke tests
|
||||||
run: |
|
run: |
|
||||||
echo "Funding ganache accounts..."
|
|
||||||
timeout 10m bash bor/integration-tests/fund_ganache_accounts.sh
|
|
||||||
echo "Deposit 100 matic for each account to bor network"
|
echo "Deposit 100 matic for each account to bor network"
|
||||||
cd matic-cli/devnet/code/contracts
|
cd matic-cli/devnet/devnet
|
||||||
npm run truffle exec scripts/deposit.js -- --network development $(jq -r .root.tokens.MaticToken contractAddresses.json) 100000000000000000000
|
SCRIPT_ADDRESS=$(jq -r '.[0].address' signer-dump.json)
|
||||||
cd -
|
SCRIPT_PRIVATE_KEY=$(jq -r '.[0].priv_key' signer-dump.json)
|
||||||
|
cd ../code/pos-contracts
|
||||||
|
CONTRACT_ADDRESS=$(jq -r .root.tokens.MaticToken contractAddresses.json)
|
||||||
|
forge script scripts/matic-cli-scripts/Deposit.s.sol:MaticDeposit --rpc-url http://localhost:9545 --private-key $SCRIPT_PRIVATE_KEY --broadcast --sig "run(address,address,uint256)" $SCRIPT_ADDRESS $CONTRACT_ADDRESS 100000000000000000000
|
||||||
|
cd ../../../..
|
||||||
timeout 60m bash bor/integration-tests/smoke_test.sh
|
timeout 60m bash bor/integration-tests/smoke_test.sh
|
||||||
|
|
||||||
|
- name: Run RPC Tests
|
||||||
|
run: |
|
||||||
|
echo "Starting RPC Tests..."
|
||||||
|
timeout 5m bash bor/integration-tests/rpc_test.sh
|
||||||
|
|
||||||
- name: Upload logs
|
- name: Upload logs
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4.4.0
|
uses: actions/upload-artifact@v4.4.0
|
||||||
|
|
|
||||||
8
.github/workflows/codeql.yml
vendored
8
.github/workflows/codeql.yml
vendored
|
|
@ -1,10 +1,10 @@
|
||||||
name: "CodeQL"
|
name: 'CodeQL'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "master", "develop" ]
|
branches: ['master', 'develop']
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "master", "develop" ]
|
branches: ['master', 'develop']
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * *'
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
|
@ -43,4 +43,4 @@ jobs:
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v2
|
||||||
with:
|
with:
|
||||||
category: "/language:${{matrix.language}}"
|
category: '/language:${{matrix.language}}'
|
||||||
|
|
|
||||||
4
.github/workflows/govulncheck.yml
vendored
4
.github/workflows/govulncheck.yml
vendored
|
|
@ -8,7 +8,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: "1.23.6"
|
go-version: '1.23.6'
|
||||||
check-latest: true
|
check-latest: true
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: technote-space/get-diff-action@v6
|
- uses: technote-space/get-diff-action@v6
|
||||||
|
|
@ -20,4 +20,4 @@ jobs:
|
||||||
Makefile
|
Makefile
|
||||||
- name: govulncheck
|
- name: govulncheck
|
||||||
run: make vulncheck
|
run: make vulncheck
|
||||||
if: "env.GIT_DIFF != ''"
|
if: env.GIT_DIFF != ''
|
||||||
|
|
|
||||||
5
.github/workflows/mainnet_deb_profiles.yml
vendored
5
.github/workflows/mainnet_deb_profiles.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write
|
||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
@ -29,7 +29,6 @@ jobs:
|
||||||
NUMERIC_VERSION=$( echo ${{ env.GIT_TAG }} | sed 's/[^0-9.]//g' )
|
NUMERIC_VERSION=$( echo ${{ env.GIT_TAG }} | sed 's/[^0-9.]//g' )
|
||||||
echo "VERSION=$NUMERIC_VERSION" >> $GITHUB_ENV
|
echo "VERSION=$NUMERIC_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
|
||||||
- name: Making directory structure for yaml
|
- name: Making directory structure for yaml
|
||||||
run: mkdir -p packaging/deb/bor/var/lib/bor
|
run: mkdir -p packaging/deb/bor/var/lib/bor
|
||||||
- name: making directory structure for the systemd
|
- name: making directory structure for the systemd
|
||||||
|
|
@ -387,8 +386,6 @@ jobs:
|
||||||
NODE: archive
|
NODE: archive
|
||||||
NETWORK: mainnet
|
NETWORK: mainnet
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
############ Check and Upload ##########################
|
############ Check and Upload ##########################
|
||||||
- name: Confirming package built
|
- name: Confirming package built
|
||||||
run: ls -ltr packaging/deb/ | grep bor
|
run: ls -ltr packaging/deb/ | grep bor
|
||||||
|
|
|
||||||
3
.github/workflows/packager_deb.yml
vendored
3
.github/workflows/packager_deb.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write
|
||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
@ -97,7 +97,6 @@ jobs:
|
||||||
echo "Maintainer: devops@polygon.technology" >> packaging/deb/bor/DEBIAN/control
|
echo "Maintainer: devops@polygon.technology" >> packaging/deb/bor/DEBIAN/control
|
||||||
echo "Description: bor binary package" >> packaging/deb/bor/DEBIAN/control
|
echo "Description: bor binary package" >> packaging/deb/bor/DEBIAN/control
|
||||||
|
|
||||||
|
|
||||||
- name: Creating package for binary for bor ${{ env.ARCH }}
|
- name: Creating package for binary for bor ${{ env.ARCH }}
|
||||||
run: cp -rp packaging/deb/bor packaging/deb/bor-${{ env.GIT_TAG }}-${{ env.ARCH }}
|
run: cp -rp packaging/deb/bor packaging/deb/bor-${{ env.GIT_TAG }}-${{ env.ARCH }}
|
||||||
env:
|
env:
|
||||||
|
|
|
||||||
1
.github/workflows/stale.yml
vendored
1
.github/workflows/stale.yml
vendored
|
|
@ -11,7 +11,6 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
|
|
|
||||||
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -30,6 +30,14 @@ cover.out
|
||||||
/build/bin/
|
/build/bin/
|
||||||
/geth*.zip
|
/geth*.zip
|
||||||
|
|
||||||
|
# used by the build/ci.go archive + upload tool
|
||||||
|
/geth*.tar.gz
|
||||||
|
/geth*.tar.gz.sig
|
||||||
|
/geth*.tar.gz.asc
|
||||||
|
/geth*.zip.sig
|
||||||
|
/geth*.zip.asc
|
||||||
|
|
||||||
|
|
||||||
# travis
|
# travis
|
||||||
profile.tmp
|
profile.tmp
|
||||||
profile.cov
|
profile.cov
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,10 @@ issues:
|
||||||
- path: crypto/bn256/
|
- path: crypto/bn256/
|
||||||
linters:
|
linters:
|
||||||
- revive
|
- revive
|
||||||
|
- path: cmd/utils/flags.go
|
||||||
|
text: "SA1019: cfg.TxLookupLimit is deprecated: use 'TransactionHistory' instead."
|
||||||
|
- path: cmd/utils/flags.go
|
||||||
|
text: "SA1019: ethconfig.Defaults.TxLookupLimit is deprecated: use 'TransactionHistory' instead."
|
||||||
- path: internal/build/pgp.go
|
- path: internal/build/pgp.go
|
||||||
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
|
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
|
||||||
- path: core/vm/contracts.go
|
- path: core/vm/contracts.go
|
||||||
|
|
|
||||||
64
.travis.yml
64
.travis.yml
|
|
@ -9,26 +9,13 @@ jobs:
|
||||||
- azure-osx
|
- azure-osx
|
||||||
|
|
||||||
include:
|
include:
|
||||||
# This builder only tests code linters on latest version of Go
|
# This builder create and push the Docker images for all architectures
|
||||||
- stage: lint
|
|
||||||
os: linux
|
|
||||||
dist: bionic
|
|
||||||
go: 1.22.x
|
|
||||||
env:
|
|
||||||
- lint
|
|
||||||
git:
|
|
||||||
submodules: false # avoid cloning ethereum/tests
|
|
||||||
script:
|
|
||||||
- go run build/ci.go lint
|
|
||||||
|
|
||||||
# These builders create the Docker sub-images for multi-arch push and each
|
|
||||||
# will attempt to push the multi-arch image if they are the last builder
|
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = push
|
if: type = push
|
||||||
os: linux
|
os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
dist: noble
|
dist: focal
|
||||||
go: 1.22.x
|
go: 1.23.x
|
||||||
env:
|
env:
|
||||||
- docker
|
- docker
|
||||||
services:
|
services:
|
||||||
|
|
@ -38,24 +25,7 @@ jobs:
|
||||||
before_install:
|
before_install:
|
||||||
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go
|
- go run build/ci.go dockerx -platform "linux/amd64,linux/arm64" -upload ethereum/client-go
|
||||||
|
|
||||||
- stage: build
|
|
||||||
if: type = push
|
|
||||||
os: linux
|
|
||||||
arch: arm64
|
|
||||||
dist: noble
|
|
||||||
go: 1.22.x
|
|
||||||
env:
|
|
||||||
- docker
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
git:
|
|
||||||
submodules: false # avoid cloning ethereum/tests
|
|
||||||
before_install:
|
|
||||||
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
|
||||||
script:
|
|
||||||
- go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go
|
|
||||||
|
|
||||||
# This builder does the Ubuntu PPA upload
|
# This builder does the Ubuntu PPA upload
|
||||||
- stage: build
|
- stage: build
|
||||||
|
|
@ -85,9 +55,9 @@ jobs:
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = push
|
if: type = push
|
||||||
os: linux
|
os: linux
|
||||||
dist: noble
|
dist: focal
|
||||||
sudo: required
|
sudo: required
|
||||||
go: 1.22.x
|
go: 1.23.x
|
||||||
env:
|
env:
|
||||||
- azure-linux
|
- azure-linux
|
||||||
git:
|
git:
|
||||||
|
|
@ -99,6 +69,7 @@ jobs:
|
||||||
|
|
||||||
# build 386
|
# build 386
|
||||||
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
|
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
|
||||||
|
- git status --porcelain
|
||||||
- go run build/ci.go install -dlgo -arch 386
|
- go run build/ci.go install -dlgo -arch 386
|
||||||
- go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
- go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
||||||
|
|
||||||
|
|
@ -158,12 +129,13 @@ jobs:
|
||||||
if: type = push
|
if: type = push
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode14.2
|
osx_image: xcode14.2
|
||||||
go: 1.22.x
|
go: 1.23.1 # See https://github.com/ethereum/go-ethereum/pull/30478
|
||||||
env:
|
env:
|
||||||
- azure-osx
|
- azure-osx
|
||||||
git:
|
git:
|
||||||
submodules: false # avoid cloning ethereum/tests
|
submodules: false # avoid cloning ethereum/tests
|
||||||
script:
|
script:
|
||||||
|
- ln -sf /Users/travis/gopath/bin/go1.23.1 /usr/local/bin/go # Work around travis go-setup bug
|
||||||
- go run build/ci.go install -dlgo
|
- go run build/ci.go install -dlgo
|
||||||
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
||||||
- go run build/ci.go install -dlgo -arch arm64
|
- go run build/ci.go install -dlgo -arch arm64
|
||||||
|
|
@ -174,8 +146,8 @@ jobs:
|
||||||
if: type = push
|
if: type = push
|
||||||
os: linux
|
os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
dist: noble
|
dist: focal
|
||||||
go: 1.22.x
|
go: 1.23.x
|
||||||
script:
|
script:
|
||||||
- travis_wait 45 go run build/ci.go test $TEST_PACKAGES
|
- travis_wait 45 go run build/ci.go test $TEST_PACKAGES
|
||||||
|
|
||||||
|
|
@ -190,7 +162,7 @@ jobs:
|
||||||
|
|
||||||
- stage: build
|
- stage: build
|
||||||
os: linux
|
os: linux
|
||||||
dist: noble
|
dist: focal
|
||||||
go: 1.22.x
|
go: 1.22.x
|
||||||
script:
|
script:
|
||||||
- travis_wait 45 go run build/ci.go test $TEST_PACKAGES
|
- travis_wait 45 go run build/ci.go test $TEST_PACKAGES
|
||||||
|
|
@ -199,8 +171,8 @@ jobs:
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = cron || (type = push && tag ~= /^v[0-9]/)
|
if: type = cron || (type = push && tag ~= /^v[0-9]/)
|
||||||
os: linux
|
os: linux
|
||||||
dist: noble
|
dist: focal
|
||||||
go: 1.22.x
|
go: 1.23.x
|
||||||
env:
|
env:
|
||||||
- ubuntu-ppa
|
- ubuntu-ppa
|
||||||
git:
|
git:
|
||||||
|
|
@ -215,8 +187,8 @@ jobs:
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = cron
|
if: type = cron
|
||||||
os: linux
|
os: linux
|
||||||
dist: noble
|
dist: focal
|
||||||
go: 1.22.x
|
go: 1.23.x
|
||||||
env:
|
env:
|
||||||
- azure-purge
|
- azure-purge
|
||||||
git:
|
git:
|
||||||
|
|
@ -228,8 +200,8 @@ jobs:
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = cron
|
if: type = cron
|
||||||
os: linux
|
os: linux
|
||||||
dist: noble
|
dist: focal
|
||||||
go: 1.22.x
|
go: 1.23.x
|
||||||
env:
|
env:
|
||||||
- racetests
|
- racetests
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Build Geth in a stock Go builder container
|
# Build Geth in a stock Go builder container
|
||||||
FROM golang:1.22.1-alpine as builder
|
FROM golang:1.23-alpine AS builder
|
||||||
|
|
||||||
RUN apk add --no-cache make gcc musl-dev linux-headers git
|
RUN apk add --no-cache make gcc musl-dev linux-headers git
|
||||||
|
|
||||||
|
|
|
||||||
1
Makefile
1
Makefile
|
|
@ -90,7 +90,6 @@ lintci-deps:
|
||||||
vulncheck:
|
vulncheck:
|
||||||
@go run golang.org/x/vuln/cmd/govulncheck@latest ./...
|
@go run golang.org/x/vuln/cmd/govulncheck@latest ./...
|
||||||
|
|
||||||
|
|
||||||
goimports:
|
goimports:
|
||||||
goimports -local "$(PACKAGE)" -w .
|
goimports -local "$(PACKAGE)" -w .
|
||||||
|
|
||||||
|
|
|
||||||
12
README.md
12
README.md
|
|
@ -1,9 +1,7 @@
|
||||||
# Bor Overview
|
# Bor Overview
|
||||||
Bor is the Official Golang implementation of the Polygon PoS blockchain. It is a fork of [geth](https://github.com/ethereum/go-ethereum) and is EVM compatible (upto London fork).
|
Bor is the official Golang implementation of the Polygon PoS blockchain. It is a fork of [geth](https://github.com/ethereum/go-ethereum) and is EVM compatible (upto London fork).
|
||||||
|
|
||||||
[](https://pkg.go.dev/github.com/maticnetwork/bor)
|
||||||
https://pkg.go.dev/badge/github.com/maticnetwork/bor
|
|
||||||
)](https://pkg.go.dev/github.com/maticnetwork/bor)
|
|
||||||
[](https://goreportcard.com/report/github.com/maticnetwork/bor)
|
[](https://goreportcard.com/report/github.com/maticnetwork/bor)
|
||||||

|

|
||||||
[](https://discord.com/invite/0xpolygonrnd)
|
[](https://discord.com/invite/0xpolygonrnd)
|
||||||
|
|
@ -13,15 +11,15 @@ https://pkg.go.dev/badge/github.com/maticnetwork/bor
|
||||||
|
|
||||||
The easiest way to get started with bor is to install the packages using the command below. Please take a look at the [releases](https://github.com/maticnetwork/bor/releases) section to find the latest stable version of bor.
|
The easiest way to get started with bor is to install the packages using the command below. Please take a look at the [releases](https://github.com/maticnetwork/bor/releases) section to find the latest stable version of bor.
|
||||||
|
|
||||||
curl -L https://raw.githubusercontent.com/maticnetwork/install/main/bor.sh | bash -s -- v0.4.0 <network> <node_type>
|
curl -L https://raw.githubusercontent.com/maticnetwork/install/main/bor.sh | bash -s -- v2.0.0 <network> <node_type>
|
||||||
|
|
||||||
The network accepts `mainnet`,`amoy` or `mumbai` and the node type accepts `validator` or `sentry` or `archive`. The installation script does the following things:
|
The network accepts `mainnet`, or `amoy` and the node type accepts `validator` or `sentry` or `archive`. The installation script does the following things:
|
||||||
- Create a new user named `bor`.
|
- Create a new user named `bor`.
|
||||||
- Install the bor binary at `/usr/bin/bor`.
|
- Install the bor binary at `/usr/bin/bor`.
|
||||||
- Dump the suitable config file (based on the network and node type provided) at `/var/lib/bor` and use it as the home dir.
|
- Dump the suitable config file (based on the network and node type provided) at `/var/lib/bor` and use it as the home dir.
|
||||||
- Create a systemd service named `bor` at `/lib/systemd/system/bor.service` which starts bor using the config file as `bor` user.
|
- Create a systemd service named `bor` at `/lib/systemd/system/bor.service` which starts bor using the config file as `bor` user.
|
||||||
|
|
||||||
The releases supports both the networks i.e. Polygon Mainnet, Amoy and Mumbai (Testnet) unless explicitly specified. Before the stable release for mainnet, pre-releases will be available marked with `beta` tag for deploying on Mumbai/Amoy (testnet). On sufficient testing, stable release for mainnet will be announced with a forum post.
|
The releases supports both the networks i.e. Polygon Mainnet, and Amoy (Testnet) unless explicitly specified. Before the stable release for mainnet, pre-releases will be available marked with `beta` tag for deploying on Amoy (testnet). On sufficient testing, stable release for mainnet will be announced with a forum post.
|
||||||
|
|
||||||
### Building from source
|
### Building from source
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1326,3 +1326,10 @@ func TestUnpackRevert(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInternalContractType(t *testing.T) {
|
||||||
|
jsonData := `[{"inputs":[{"components":[{"internalType":"uint256","name":"dailyLimit","type":"uint256"},{"internalType":"uint256","name":"txLimit","type":"uint256"},{"internalType":"uint256","name":"accountDailyLimit","type":"uint256"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"bool","name":"onlyWhitelisted","type":"bool"}],"internalType":"struct IMessagePassingBridge.BridgeLimits","name":"bridgeLimits","type":"tuple"},{"components":[{"internalType":"uint256","name":"lastTransferReset","type":"uint256"},{"internalType":"uint256","name":"bridged24Hours","type":"uint256"}],"internalType":"struct IMessagePassingBridge.AccountLimit","name":"accountDailyLimit","type":"tuple"},{"components":[{"internalType":"uint256","name":"lastTransferReset","type":"uint256"},{"internalType":"uint256","name":"bridged24Hours","type":"uint256"}],"internalType":"struct IMessagePassingBridge.BridgeDailyLimit","name":"bridgeDailyLimit","type":"tuple"},{"internalType":"contract INameService","name":"nameService","type":"INameService"},{"internalType":"bool","name":"isClosed","type":"bool"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"canBridge","outputs":[{"internalType":"bool","name":"isWithinLimit","type":"bool"},{"internalType":"string","name":"error","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"normalizeFrom18ToTokenDecimals","outputs":[{"internalType":"uint256","name":"normalized","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"normalizeFromTokenTo18Decimals","outputs":[{"internalType":"uint256","name":"normalized","type":"uint256"}],"stateMutability":"pure","type":"function"}]`
|
||||||
|
if _, err := JSON(strings.NewReader(jsonData)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ func (b *SimulatedBackend) rollback(parent *types.Block) {
|
||||||
blocks, _ := core.GenerateChain(b.config, parent, ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
|
blocks, _ := core.GenerateChain(b.config, parent, ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
|
||||||
|
|
||||||
b.pendingBlock = blocks[0]
|
b.pendingBlock = blocks[0]
|
||||||
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.blockchain.StateCache(), nil)
|
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.blockchain.StateCache())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fork creates a side-chain that can be used to simulate reorgs.
|
// Fork creates a side-chain that can be used to simulate reorgs.
|
||||||
|
|
@ -699,7 +699,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
|
||||||
GasTipCap: call.GasTipCap,
|
GasTipCap: call.GasTipCap,
|
||||||
Data: call.Data,
|
Data: call.Data,
|
||||||
AccessList: call.AccessList,
|
AccessList: call.AccessList,
|
||||||
SkipAccountChecks: true,
|
SkipNonceChecks: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new environment which holds all relevant information
|
// Create a new environment which holds all relevant information
|
||||||
|
|
@ -744,7 +744,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b.pendingBlock = blocks[0]
|
b.pendingBlock = blocks[0]
|
||||||
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
|
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database())
|
||||||
b.pendingReceipts = receipts[0]
|
b.pendingReceipts = receipts[0]
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -867,7 +867,7 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b.pendingBlock = blocks[0]
|
b.pendingBlock = blocks[0]
|
||||||
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
|
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,9 @@ func TestWaitDeployed(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Send and mine the transaction.
|
// Send and mine the transaction.
|
||||||
backend.SendTransaction(ctx, tx)
|
if err := backend.SendTransaction(ctx, tx); err != nil {
|
||||||
|
t.Errorf("test %q: failed to send transaction: %v", name, err)
|
||||||
|
}
|
||||||
backend.Commit()
|
backend.Commit()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
|
@ -122,7 +124,9 @@ func TestWaitDeployedCornerCases(t *testing.T) {
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
backend.SendTransaction(ctx, tx)
|
if err := backend.SendTransaction(ctx, tx); err != nil {
|
||||||
|
t.Errorf("failed to send transaction: %q", err)
|
||||||
|
}
|
||||||
backend.Commit()
|
backend.Commit()
|
||||||
notContractCreation := errors.New("tx is not contract creation")
|
notContractCreation := errors.New("tx is not contract creation")
|
||||||
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != notContractCreation.Error() {
|
if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != notContractCreation.Error() {
|
||||||
|
|
@ -140,6 +144,8 @@ func TestWaitDeployedCornerCases(t *testing.T) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
backend.SendTransaction(ctx, tx)
|
if err := backend.SendTransaction(ctx, tx); err != nil {
|
||||||
|
t.Errorf("failed to send transaction: %q", err)
|
||||||
|
}
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -238,8 +238,13 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
|
||||||
typ.T = FunctionTy
|
typ.T = FunctionTy
|
||||||
typ.Size = 24
|
typ.Size = 24
|
||||||
default:
|
default:
|
||||||
|
if strings.HasPrefix(internalType, "contract ") {
|
||||||
|
typ.Size = 20
|
||||||
|
typ.T = AddressTy
|
||||||
|
} else {
|
||||||
return Type{}, fmt.Errorf("unsupported arg type: %s", t)
|
return Type{}, fmt.Errorf("unsupported arg type: %s", t)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
beacon/blsync/block_sync.go
Executable file → Normal file
0
beacon/blsync/block_sync.go
Executable file → Normal file
|
|
@ -70,7 +70,10 @@ func TestBlockSync(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
var expNumber, headNumber uint64
|
var expNumber, headNumber uint64
|
||||||
if expHead != nil {
|
if expHead != nil {
|
||||||
p, _ := expHead.ExecutionPayload()
|
p, err := expHead.ExecutionPayload()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expHead.ExecutionPayload() failed: %v", err)
|
||||||
|
}
|
||||||
expNumber = p.NumberU64()
|
expNumber = p.NumberU64()
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
|
|
|
||||||
|
|
@ -56,32 +56,17 @@ var (
|
||||||
AddFork("DENEB", 132608, []byte{144, 0, 0, 115}),
|
AddFork("DENEB", 132608, []byte{144, 0, 0, 115}),
|
||||||
Checkpoint: common.HexToHash("0x1005a6d9175e96bfbce4d35b80f468e9bff0b674e1e861d16e09e10005a58e81"),
|
Checkpoint: common.HexToHash("0x1005a6d9175e96bfbce4d35b80f468e9bff0b674e1e861d16e09e10005a58e81"),
|
||||||
}
|
}
|
||||||
|
|
||||||
GoerliConfig = lightClientConfig{
|
|
||||||
ChainConfig: (&types.ChainConfig{
|
|
||||||
GenesisValidatorsRoot: common.HexToHash("0x043db0d9a83813551ee2f33450d23797757d430911a9320530ad8a0eabc43efb"),
|
|
||||||
GenesisTime: 1614588812,
|
|
||||||
}).
|
|
||||||
AddFork("GENESIS", 0, []byte{0, 0, 16, 32}).
|
|
||||||
AddFork("ALTAIR", 36660, []byte{1, 0, 16, 32}).
|
|
||||||
AddFork("BELLATRIX", 112260, []byte{2, 0, 16, 32}).
|
|
||||||
AddFork("CAPELLA", 162304, []byte{3, 0, 16, 32}).
|
|
||||||
AddFork("DENEB", 231680, []byte{4, 0, 16, 32}),
|
|
||||||
Checkpoint: common.HexToHash("0x53a0f4f0a378e2c4ae0a9ee97407eb69d0d737d8d8cd0a5fb1093f42f7b81c49"),
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeChainConfig(ctx *cli.Context) lightClientConfig {
|
func makeChainConfig(ctx *cli.Context) lightClientConfig {
|
||||||
var config lightClientConfig
|
var config lightClientConfig
|
||||||
customConfig := ctx.IsSet(utils.BeaconConfigFlag.Name)
|
customConfig := ctx.IsSet(utils.BeaconConfigFlag.Name)
|
||||||
utils.CheckExclusive(ctx, utils.MainnetFlag, utils.GoerliFlag, utils.SepoliaFlag, utils.BeaconConfigFlag)
|
utils.CheckExclusive(ctx, utils.MainnetFlag, utils.SepoliaFlag, utils.BeaconConfigFlag)
|
||||||
switch {
|
switch {
|
||||||
case ctx.Bool(utils.MainnetFlag.Name):
|
case ctx.Bool(utils.MainnetFlag.Name):
|
||||||
config = MainnetConfig
|
config = MainnetConfig
|
||||||
case ctx.Bool(utils.SepoliaFlag.Name):
|
case ctx.Bool(utils.SepoliaFlag.Name):
|
||||||
config = SepoliaConfig
|
config = SepoliaConfig
|
||||||
case ctx.Bool(utils.GoerliFlag.Name):
|
|
||||||
config = GoerliConfig
|
|
||||||
default:
|
default:
|
||||||
if !customConfig {
|
if !customConfig {
|
||||||
config = MainnetConfig
|
config = MainnetConfig
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var enc ExecutableData
|
var enc ExecutableData
|
||||||
|
|
@ -61,6 +63,8 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||||
enc.Withdrawals = e.Withdrawals
|
enc.Withdrawals = e.Withdrawals
|
||||||
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
||||||
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
||||||
|
enc.Deposits = e.Deposits
|
||||||
|
enc.ExecutionWitness = e.ExecutionWitness
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,6 +88,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits *types.Deposits `json:"depositRequests"`
|
||||||
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dec ExecutableData
|
var dec ExecutableData
|
||||||
|
|
@ -187,5 +193,11 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||||
if dec.ExcessBlobGas != nil {
|
if dec.ExcessBlobGas != nil {
|
||||||
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||||
}
|
}
|
||||||
|
if dec.Deposits != nil {
|
||||||
|
e.Deposits = *dec.Deposits
|
||||||
|
}
|
||||||
|
if dec.ExecutionWitness != nil {
|
||||||
|
e.ExecutionWitness = dec.ExecutionWitness
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
|
||||||
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
Override bool `json:"shouldOverrideBuilder"`
|
Override bool `json:"shouldOverrideBuilder"`
|
||||||
|
Witness *hexutil.Bytes `json:"witness"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var enc ExecutionPayloadEnvelope
|
var enc ExecutionPayloadEnvelope
|
||||||
|
|
@ -26,6 +27,7 @@ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
|
||||||
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
|
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
|
||||||
enc.BlobsBundle = e.BlobsBundle
|
enc.BlobsBundle = e.BlobsBundle
|
||||||
enc.Override = e.Override
|
enc.Override = e.Override
|
||||||
|
enc.Witness = e.Witness
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,6 +38,7 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
|
||||||
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
Override *bool `json:"shouldOverrideBuilder"`
|
Override *bool `json:"shouldOverrideBuilder"`
|
||||||
|
Witness *hexutil.Bytes `json:"witness"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dec ExecutionPayloadEnvelope
|
var dec ExecutionPayloadEnvelope
|
||||||
|
|
@ -60,5 +63,8 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
|
||||||
if dec.Override != nil {
|
if dec.Override != nil {
|
||||||
e.Override = *dec.Override
|
e.Override = *dec.Override
|
||||||
}
|
}
|
||||||
|
if dec.Witness != nil {
|
||||||
|
e.Witness = dec.Witness
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,8 @@ type ExecutableData struct {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON type overrides for executableData.
|
// JSON type overrides for executableData.
|
||||||
|
|
@ -92,6 +94,14 @@ type executableDataMarshaling struct {
|
||||||
ExcessBlobGas *hexutil.Uint64
|
ExcessBlobGas *hexutil.Uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatelessPayloadStatusV1 is the result of a stateless payload execution.
|
||||||
|
type StatelessPayloadStatusV1 struct {
|
||||||
|
Status string `json:"status"`
|
||||||
|
StateRoot common.Hash `json:"stateRoot"`
|
||||||
|
ReceiptsRoot common.Hash `json:"receiptsRoot"`
|
||||||
|
ValidationError *string `json:"validationError"`
|
||||||
|
}
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go
|
//go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go
|
||||||
|
|
||||||
type ExecutionPayloadEnvelope struct {
|
type ExecutionPayloadEnvelope struct {
|
||||||
|
|
@ -99,6 +109,7 @@ type ExecutionPayloadEnvelope struct {
|
||||||
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
|
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
Override bool `json:"shouldOverrideBuilder"`
|
Override bool `json:"shouldOverrideBuilder"`
|
||||||
|
Witness *hexutil.Bytes `json:"witness"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlobsBundleV1 struct {
|
type BlobsBundleV1 struct {
|
||||||
|
|
@ -114,6 +125,7 @@ type executionPayloadEnvelopeMarshaling struct {
|
||||||
|
|
||||||
type PayloadStatusV1 struct {
|
type PayloadStatusV1 struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
|
Witness *hexutil.Bytes `json:"witness"`
|
||||||
LatestValidHash *common.Hash `json:"latestValidHash"`
|
LatestValidHash *common.Hash `json:"latestValidHash"`
|
||||||
ValidationError *string `json:"validationError"`
|
ValidationError *string `json:"validationError"`
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +213,20 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
||||||
// Withdrawals value will propagate through the returned block. Empty
|
// Withdrawals value will propagate through the returned block. Empty
|
||||||
// Withdrawals value must be passed via non-nil, length 0 value in data.
|
// Withdrawals value must be passed via non-nil, length 0 value in data.
|
||||||
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
|
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
|
||||||
|
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if block.Hash() != data.BlockHash {
|
||||||
|
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", data.BlockHash, block.Hash())
|
||||||
|
}
|
||||||
|
return block, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
|
||||||
|
// for stateless execution, so it skips checking if the executable data hashes to
|
||||||
|
// the requested hash (stateless has to *compute* the root hash, it's not given).
|
||||||
|
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
|
||||||
txs, err := decodeTransactions(data.Transactions)
|
txs, err := decodeTransactions(data.Transactions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -235,7 +261,19 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
||||||
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
||||||
withdrawalsRoot = &h
|
withdrawalsRoot = &h
|
||||||
}
|
}
|
||||||
|
// Compute requestsHash if any requests are non-nil.
|
||||||
|
var (
|
||||||
|
requestsHash *common.Hash
|
||||||
|
requests types.Requests
|
||||||
|
)
|
||||||
|
if data.Deposits != nil {
|
||||||
|
requests = make(types.Requests, 0)
|
||||||
|
for _, d := range data.Deposits {
|
||||||
|
requests = append(requests, types.NewRequest(d))
|
||||||
|
}
|
||||||
|
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
|
||||||
|
requestsHash = &h
|
||||||
|
}
|
||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
ParentHash: data.ParentHash,
|
ParentHash: data.ParentHash,
|
||||||
UncleHash: types.EmptyUncleHash,
|
UncleHash: types.EmptyUncleHash,
|
||||||
|
|
@ -256,13 +294,12 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
||||||
ExcessBlobGas: data.ExcessBlobGas,
|
ExcessBlobGas: data.ExcessBlobGas,
|
||||||
BlobGasUsed: data.BlobGasUsed,
|
BlobGasUsed: data.BlobGasUsed,
|
||||||
ParentBeaconRoot: beaconRoot,
|
ParentBeaconRoot: beaconRoot,
|
||||||
|
RequestsHash: requestsHash,
|
||||||
}
|
}
|
||||||
block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals})
|
return types.NewBlockWithHeader(header).
|
||||||
if block.Hash() != data.BlockHash {
|
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals, Requests: requests}).
|
||||||
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", data.BlockHash, block.Hash())
|
WithWitness(data.ExecutionWitness),
|
||||||
}
|
nil
|
||||||
|
|
||||||
return block, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
||||||
|
|
@ -286,6 +323,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
||||||
Withdrawals: block.Withdrawals(),
|
Withdrawals: block.Withdrawals(),
|
||||||
BlobGasUsed: block.BlobGasUsed(),
|
BlobGasUsed: block.BlobGasUsed(),
|
||||||
ExcessBlobGas: block.ExcessBlobGas(),
|
ExcessBlobGas: block.ExcessBlobGas(),
|
||||||
|
ExecutionWitness: block.ExecutionWitness(),
|
||||||
}
|
}
|
||||||
bundle := BlobsBundleV1{
|
bundle := BlobsBundleV1{
|
||||||
Commitments: make([]hexutil.Bytes, 0),
|
Commitments: make([]hexutil.Bytes, 0),
|
||||||
|
|
@ -299,13 +337,30 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
||||||
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setRequests(block.Requests(), data)
|
||||||
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
|
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
|
// setRequests differentiates the different request types and
|
||||||
type ExecutionPayloadBodyV1 struct {
|
// assigns them to the associated fields in ExecutableData.
|
||||||
|
func setRequests(requests types.Requests, data *ExecutableData) {
|
||||||
|
if requests != nil {
|
||||||
|
// If requests is non-nil, it means deposits are available in block and we
|
||||||
|
// should return an empty slice instead of nil if there are no deposits.
|
||||||
|
data.Deposits = make(types.Deposits, 0)
|
||||||
|
}
|
||||||
|
for _, r := range requests {
|
||||||
|
if d, ok := r.Inner().(*types.Deposit); ok {
|
||||||
|
data.Deposits = append(data.Deposits, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange
|
||||||
|
type ExecutionPayloadBody struct {
|
||||||
TransactionData []hexutil.Bytes `json:"transactions"`
|
TransactionData []hexutil.Bytes `json:"transactions"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client identifiers to support ClientVersionV1.
|
// Client identifiers to support ClientVersionV1.
|
||||||
|
|
|
||||||
0
beacon/light/api/api_server.go
Executable file → Normal file
0
beacon/light/api/api_server.go
Executable file → Normal file
49
beacon/light/api/light_api.go
Executable file → Normal file
49
beacon/light/api/light_api.go
Executable file → Normal file
|
|
@ -23,6 +23,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -120,8 +122,12 @@ func NewBeaconLightApi(url string, customHeaders map[string]string) *BeaconLight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *BeaconLightApi) httpGet(path string) ([]byte, error) {
|
func (api *BeaconLightApi) httpGet(path string, params url.Values) ([]byte, error) {
|
||||||
req, err := http.NewRequest("GET", api.url+path, nil)
|
uri, err := api.buildURL(path, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest("GET", uri, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -145,17 +151,16 @@ func (api *BeaconLightApi) httpGet(path string) ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *BeaconLightApi) httpGetf(format string, params ...any) ([]byte, error) {
|
|
||||||
return api.httpGet(fmt.Sprintf(format, params...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBestUpdatesAndCommittees fetches and validates LightClientUpdate for given
|
// GetBestUpdatesAndCommittees fetches and validates LightClientUpdate for given
|
||||||
// period and full serialized committee for the next period (committee root hash
|
// period and full serialized committee for the next period (committee root hash
|
||||||
// equals update.NextSyncCommitteeRoot).
|
// equals update.NextSyncCommitteeRoot).
|
||||||
// Note that the results are validated but the update signature should be verified
|
// Note that the results are validated but the update signature should be verified
|
||||||
// by the caller as its validity depends on the update chain.
|
// by the caller as its validity depends on the update chain.
|
||||||
func (api *BeaconLightApi) GetBestUpdatesAndCommittees(firstPeriod, count uint64) ([]*types.LightClientUpdate, []*types.SerializedSyncCommittee, error) {
|
func (api *BeaconLightApi) GetBestUpdatesAndCommittees(firstPeriod, count uint64) ([]*types.LightClientUpdate, []*types.SerializedSyncCommittee, error) {
|
||||||
resp, err := api.httpGetf("/eth/v1/beacon/light_client/updates?start_period=%d&count=%d", firstPeriod, count)
|
resp, err := api.httpGet("/eth/v1/beacon/light_client/updates", map[string][]string{
|
||||||
|
"start_period": {strconv.FormatUint(firstPeriod, 10)},
|
||||||
|
"count": {strconv.FormatUint(count, 10)},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +197,7 @@ func (api *BeaconLightApi) GetBestUpdatesAndCommittees(firstPeriod, count uint64
|
||||||
// See data structure definition here:
|
// See data structure definition here:
|
||||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate
|
||||||
func (api *BeaconLightApi) GetOptimisticUpdate() (types.OptimisticUpdate, error) {
|
func (api *BeaconLightApi) GetOptimisticUpdate() (types.OptimisticUpdate, error) {
|
||||||
resp, err := api.httpGet("/eth/v1/beacon/light_client/optimistic_update")
|
resp, err := api.httpGet("/eth/v1/beacon/light_client/optimistic_update", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.OptimisticUpdate{}, err
|
return types.OptimisticUpdate{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -245,7 +250,7 @@ func decodeOptimisticUpdate(enc []byte) (types.OptimisticUpdate, error) {
|
||||||
// See data structure definition here:
|
// See data structure definition here:
|
||||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate
|
||||||
func (api *BeaconLightApi) GetFinalityUpdate() (types.FinalityUpdate, error) {
|
func (api *BeaconLightApi) GetFinalityUpdate() (types.FinalityUpdate, error) {
|
||||||
resp, err := api.httpGet("/eth/v1/beacon/light_client/finality_update")
|
resp, err := api.httpGet("/eth/v1/beacon/light_client/finality_update", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.FinalityUpdate{}, err
|
return types.FinalityUpdate{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +316,7 @@ func (api *BeaconLightApi) GetHeader(blockRoot common.Hash) (types.Header, bool,
|
||||||
} else {
|
} else {
|
||||||
blockId = blockRoot.Hex()
|
blockId = blockRoot.Hex()
|
||||||
}
|
}
|
||||||
resp, err := api.httpGetf("/eth/v1/beacon/headers/%s", blockId)
|
resp, err := api.httpGet(fmt.Sprintf("/eth/v1/beacon/headers/%s", blockId), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.Header{}, false, false, err
|
return types.Header{}, false, false, err
|
||||||
}
|
}
|
||||||
|
|
@ -342,7 +347,7 @@ func (api *BeaconLightApi) GetHeader(blockRoot common.Hash) (types.Header, bool,
|
||||||
|
|
||||||
// GetCheckpointData fetches and validates bootstrap data belonging to the given checkpoint.
|
// GetCheckpointData fetches and validates bootstrap data belonging to the given checkpoint.
|
||||||
func (api *BeaconLightApi) GetCheckpointData(checkpointHash common.Hash) (*types.BootstrapData, error) {
|
func (api *BeaconLightApi) GetCheckpointData(checkpointHash common.Hash) (*types.BootstrapData, error) {
|
||||||
resp, err := api.httpGetf("/eth/v1/beacon/light_client/bootstrap/0x%x", checkpointHash[:])
|
resp, err := api.httpGet(fmt.Sprintf("/eth/v1/beacon/light_client/bootstrap/0x%x", checkpointHash[:]), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -384,7 +389,7 @@ func (api *BeaconLightApi) GetCheckpointData(checkpointHash common.Hash) (*types
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *BeaconLightApi) GetBeaconBlock(blockRoot common.Hash) (*types.BeaconBlock, error) {
|
func (api *BeaconLightApi) GetBeaconBlock(blockRoot common.Hash) (*types.BeaconBlock, error) {
|
||||||
resp, err := api.httpGetf("/eth/v2/beacon/blocks/0x%x", blockRoot)
|
resp, err := api.httpGet(fmt.Sprintf("/eth/v2/beacon/blocks/0x%x", blockRoot), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -545,9 +550,13 @@ func (api *BeaconLightApi) StartHeadListener(listener HeadEventListener) func()
|
||||||
// established. It can only return nil when the context is canceled.
|
// established. It can only return nil when the context is canceled.
|
||||||
func (api *BeaconLightApi) startEventStream(ctx context.Context, listener *HeadEventListener) *eventsource.Stream {
|
func (api *BeaconLightApi) startEventStream(ctx context.Context, listener *HeadEventListener) *eventsource.Stream {
|
||||||
for retry := true; retry; retry = ctxSleep(ctx, 5*time.Second) {
|
for retry := true; retry; retry = ctxSleep(ctx, 5*time.Second) {
|
||||||
path := "/eth/v1/events?topics=head&topics=light_client_finality_update&topics=light_client_optimistic_update"
|
|
||||||
log.Trace("Sending event subscription request")
|
log.Trace("Sending event subscription request")
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", api.url+path, nil)
|
uri, err := api.buildURL("/eth/v1/events", map[string][]string{"topics": {"head", "light_client_finality_update", "light_client_optimistic_update"}})
|
||||||
|
if err != nil {
|
||||||
|
listener.OnError(fmt.Errorf("error creating event subscription URL: %v", err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "GET", uri, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
listener.OnError(fmt.Errorf("error creating event subscription request: %v", err))
|
listener.OnError(fmt.Errorf("error creating event subscription request: %v", err))
|
||||||
continue
|
continue
|
||||||
|
|
@ -576,3 +585,15 @@ func ctxSleep(ctx context.Context, timeout time.Duration) (ok bool) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *BeaconLightApi) buildURL(path string, params url.Values) (string, error) {
|
||||||
|
uri, err := url.Parse(api.url)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
uri = uri.JoinPath(path)
|
||||||
|
if params != nil {
|
||||||
|
uri.RawQuery = params.Encode()
|
||||||
|
}
|
||||||
|
return uri.String(), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,7 @@ func (s *Scheduler) addEvent(event Event) {
|
||||||
s.Trigger()
|
s.Trigger()
|
||||||
}
|
}
|
||||||
|
|
||||||
// filterEvent sorts each Event either as a request event or a server event,
|
// filterEvents sorts each Event either as a request event or a server event,
|
||||||
// depending on its type. Request events are also sorted in a map based on the
|
// depending on its type. Request events are also sorted in a map based on the
|
||||||
// module that originally initiated the request. It also ensures that no events
|
// module that originally initiated the request. It also ensures that no events
|
||||||
// related to a server are returned before EvRegistered or after EvUnregistered.
|
// related to a server are returned before EvRegistered or after EvUnregistered.
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,34 @@ func TestUpdateSyncDifferentHeads(t *testing.T) {
|
||||||
chain.ExpNextSyncPeriod(t, 17)
|
chain.ExpNextSyncPeriod(t, 17)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRangeLock(t *testing.T) {
|
||||||
|
r := make(rangeLock)
|
||||||
|
|
||||||
|
// Lock from 0 to 99.
|
||||||
|
r.lock(0, 100, 1)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
if v, ok := r[uint64(i)]; v <= 0 || !ok {
|
||||||
|
t.Fatalf("integer space: %d not locked", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock from 0 to 99.
|
||||||
|
r.lock(0, 100, -1)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
if v, ok := r[uint64(i)]; v > 0 || ok {
|
||||||
|
t.Fatalf("integer space: %d is locked", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock from 0 to 99 then unlock from 10 to 59.
|
||||||
|
r.lock(0, 100, 1)
|
||||||
|
r.lock(10, 50, -1)
|
||||||
|
first, count := r.firstUnlocked(0, 100)
|
||||||
|
if first != 10 || count != 50 {
|
||||||
|
t.Fatalf("unexpected first: %d or count: %d", first, count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testRespUpdate(request requestWithID) request.Response {
|
func testRespUpdate(request requestWithID) request.Response {
|
||||||
var resp RespUpdates
|
var resp RespUpdates
|
||||||
if request.request == nil {
|
if request.request == nil {
|
||||||
|
|
|
||||||
|
|
@ -5,55 +5,56 @@
|
||||||
# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/
|
# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/
|
||||||
ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz
|
ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz
|
||||||
|
|
||||||
# version:golang 1.22.6
|
# version:golang 1.23.1
|
||||||
# https://go.dev/dl/
|
# https://go.dev/dl/
|
||||||
9e48d99d519882579917d8189c17e98c373ce25abaebb98772e2927088992a51 go1.22.6.src.tar.gz
|
6ee44e298379d146a5e5aa6b1c5b5d5f5d0a3365eabdd70741e6e21340ec3b0d go1.23.1.src.tar.gz
|
||||||
eeb0cc42120cbae6d3695dae2e5420fa0e93a5db957db139b55efdb879dd9856 go1.22.6.aix-ppc64.tar.gz
|
f17f2791717c15728ec63213a014e244c35f9c8846fb29f5a1b63d0c0556f756 go1.23.1.aix-ppc64.tar.gz
|
||||||
b47ac340f0b072943fed1f558a26eb260cc23bd21b8af175582e9103141d465b go1.22.6.darwin-amd64.pkg
|
dd9e772686ed908bcff94b6144322d4e2473a7dcd7c696b7e8b6d12f23c887fd go1.23.1.darwin-amd64.pkg
|
||||||
9c3c0124b01b5365f73a1489649f78f971ecf84844ad9ca58fde133096ddb61b go1.22.6.darwin-amd64.tar.gz
|
488d9e4ca3e3ed513ee4edd91bef3a2360c65fa6d6be59cf79640bf840130a58 go1.23.1.darwin-amd64.tar.gz
|
||||||
14d0355ec1c0eeb213a16efa8635fac1f16067ef78a8173abf9a8c7b805e551e go1.22.6.darwin-arm64.pkg
|
be34b488157ec69d94e26e1554558219a2c90789bcb7e3686965a7f9c8cfcbe7 go1.23.1.darwin-arm64.pkg
|
||||||
ebac39fd44fc22feed1bb519af431c84c55776e39b30f4fd62930da9c0cfd1e3 go1.22.6.darwin-arm64.tar.gz
|
e223795ca340e285a760a6446ce57a74500b30e57469a4109961d36184d3c05a go1.23.1.darwin-arm64.tar.gz
|
||||||
3695b10c722a4920c8a736284f8820c142e1e752f3a87f797a45c64366f7a173 go1.22.6.dragonfly-amd64.tar.gz
|
6af626176923a6ae6c5de6dc1c864f38365793c0e4ecd0d6eab847bdc23953e5 go1.23.1.dragonfly-amd64.tar.gz
|
||||||
a9b9570c80294a664d50b566d6bd1aa42465997d2d76a57936b32f55f5c69c63 go1.22.6.freebsd-386.tar.gz
|
cc957c1a019702e6cdc2e257202d42799011ebc1968b6c3bcd6b1965952607d5 go1.23.1.freebsd-386.tar.gz
|
||||||
424a5618406800365fe3ad96a795fb55ce394bea3ff48eaf56d292bf7a916d1e go1.22.6.freebsd-amd64.tar.gz
|
a7d57781c50bb80886a8f04066791956d45aa3eea0f83070c5268b6223afb2ff go1.23.1.freebsd-amd64.tar.gz
|
||||||
e0dce3a6dbe8e7e054d329dd4cb403935c63c0f7e22e693077aa60e12018b883 go1.22.6.freebsd-arm.tar.gz
|
c7b09f3fef456048e596db9bea746eb66796aeb82885622b0388feee18f36a3e go1.23.1.freebsd-arm.tar.gz
|
||||||
34930b01f58889c71f7a78c51c6c3bd2ce289ac7862c76dab691303cfa935fd1 go1.22.6.freebsd-arm64.tar.gz
|
b05cd6a77995a0c8439d88df124811c725fb78b942d0b6dd1643529d7ba62f1f go1.23.1.freebsd-arm64.tar.gz
|
||||||
4c9d630e55d4d600a5b4297e59620c3bdfe63a441981682b3638e2fdda228a44 go1.22.6.freebsd-riscv64.tar.gz
|
56236ae70be1613f2915943b94f53c96be5bffc0719314078facd778a89bc57e go1.23.1.freebsd-riscv64.tar.gz
|
||||||
9ed63feaf2ef56c56f1cf0d9d3fab4006efd22a38e2f1f5252e95c6ac09332f3 go1.22.6.illumos-amd64.tar.gz
|
8644c52df4e831202114fd67c9fcaf1f7233ad27bf945ac53fa7217cf1a0349f go1.23.1.illumos-amd64.tar.gz
|
||||||
9e680027b058beab10ce5938607660964b6d2c564bf50bdb01aa090dc5beda98 go1.22.6.linux-386.tar.gz
|
cdee2f4e2efa001f7ee75c90f2efc310b63346cfbba7b549987e9139527c6b17 go1.23.1.linux-386.tar.gz
|
||||||
999805bed7d9039ec3da1a53bfbcafc13e367da52aa823cb60b68ba22d44c616 go1.22.6.linux-amd64.tar.gz
|
49bbb517cfa9eee677e1e7897f7cf9cfdbcf49e05f61984a2789136de359f9bd go1.23.1.linux-amd64.tar.gz
|
||||||
c15fa895341b8eaf7f219fada25c36a610eb042985dc1a912410c1c90098eaf2 go1.22.6.linux-arm64.tar.gz
|
faec7f7f8ae53fda0f3d408f52182d942cc89ef5b7d3d9f23ff117437d4b2d2f go1.23.1.linux-arm64.tar.gz
|
||||||
b566484fe89a54c525dd1a4cbfec903c1f6e8f0b7b3dbaf94c79bc9145391083 go1.22.6.linux-armv6l.tar.gz
|
6c7832c7dcd8fb6d4eb308f672a725393403c74ee7be1aeccd8a443015df99de go1.23.1.linux-armv6l.tar.gz
|
||||||
1ee6e1896aea856142d2af7045cea118995b39404aa61afd12677d023d47ee69 go1.22.6.linux-loong64.tar.gz
|
649ce3856ddc808c00b14a46232eab0bf95e7911cdf497010b17d76656f5ca4e go1.23.1.linux-loong64.tar.gz
|
||||||
fdd0e1a3e178f9bc79adf6ff1e3de4554ce581b4c468fd6e113c43fbbbe1eec6 go1.22.6.linux-mips.tar.gz
|
201911048f234e5a0c51ec94b1a11d4e47062fee4398b1d2faa6c820dc026724 go1.23.1.linux-mips.tar.gz
|
||||||
d3e5a621fc5a07759e503a971af0b28ded6a7d6f5604ab511f51f930a18dd3e4 go1.22.6.linux-mips64.tar.gz
|
2bce3743df463915e45d2612f9476ffb03d0b3750b1cb3879347de08715b5fc6 go1.23.1.linux-mips64.tar.gz
|
||||||
01547606c5b5c1b0e5587b3afd65172860d2f4755e523785832905759ecce2d7 go1.22.6.linux-mips64le.tar.gz
|
54e301f266e33431b0703136e0bbd4cf02461b1ecedd37b7cbd90cb862a98e5f go1.23.1.linux-mips64le.tar.gz
|
||||||
2cd771416ae03c11240cfdb551d66ab9a941077664f3727b966f94386c23b0fa go1.22.6.linux-mipsle.tar.gz
|
8efd495e93d17408c0803595cdc3bf13cb28e0f957aeabd9cc18245fb8e64019 go1.23.1.linux-mipsle.tar.gz
|
||||||
6ef61d517777925e6bdb0321ea42d5f60acc20c1314dd902b9d0bfa3a5fd4fca go1.22.6.linux-ppc64.tar.gz
|
52bd68689095831ad9af7160844c23b28bb8d0acd268de7e300ff5f0662b7a07 go1.23.1.linux-ppc64.tar.gz
|
||||||
9d99fce3f6f72a76630fe91ec0884dfe3db828def4713368424900fa98bb2bd6 go1.22.6.linux-ppc64le.tar.gz
|
042888cae54b5fbfd9dd1e3b6bc4a5134879777fe6497fc4c62ec394b5ecf2da go1.23.1.linux-ppc64le.tar.gz
|
||||||
30be9c9b9cc4f044d4da9a33ee601ab7b3aff4246107d323a79e08888710754e go1.22.6.linux-riscv64.tar.gz
|
1a4a609f0391bea202d9095453cbfaf7368fa88a04c206bf9dd715a738664dc3 go1.23.1.linux-riscv64.tar.gz
|
||||||
82f3bae3ddb4ede45b848db48c5486fadb58551e74507bda45484257e7194a95 go1.22.6.linux-s390x.tar.gz
|
47dc49ad45c45e192efa0df7dc7bc5403f5f2d15b5d0dc74ef3018154b616f4d go1.23.1.linux-s390x.tar.gz
|
||||||
85b2eb9d40a930bd3e75d0096a6eb5847aac86c5085e6d13a5845e9ef03f8d4b go1.22.6.netbsd-386.tar.gz
|
fbfbd5efa6a5d581ea7f5e65015f927db0e52135cab057e43d39d5482da54b61 go1.23.1.netbsd-386.tar.gz
|
||||||
6e9acbdc34fb2a942d547c47c9c1989bb6e32b4a37d57fb312499e2bb33b46b7 go1.22.6.netbsd-amd64.tar.gz
|
e96e1cc5cf36113ee6099d1a7306b22cd9c3f975a36bdff954c59f104f22b853 go1.23.1.netbsd-amd64.tar.gz
|
||||||
e6eff3cf0038f2a9b0c9e01e228577a783bddcd8051222a3d949e24ee392e769 go1.22.6.netbsd-arm.tar.gz
|
c394dfc06bfc276a591209a37e09cd39089ec9a9cc3db30b94814ce2e39eb1d4 go1.23.1.netbsd-arm.tar.gz
|
||||||
43a7e2ba22da700b844f7561e3dd5434540ed6c9781be2e9c42e8a8cbf558f8e go1.22.6.netbsd-arm64.tar.gz
|
b3b35d64f32821a68b3e2994032dbefb81978f2ec3f218c7a770623b82d36b8e go1.23.1.netbsd-arm64.tar.gz
|
||||||
a90b758ccb45d8a17af8e140fafa1e97607de5a7ecd53a4c55f69258bfb043d0 go1.22.6.openbsd-386.tar.gz
|
3c775c4c16c182e33c2c4ac090d9a247a93b3fb18a3df01d87d490f29599faff go1.23.1.openbsd-386.tar.gz
|
||||||
cc13436c4a644e55bedcea65981eb80ca8317b39b129f5563ab3b6da1391bd47 go1.22.6.openbsd-amd64.tar.gz
|
5edbe53b47c57b32707fd7154536fbe9eaa79053fea01650c93b54cdba13fc0f go1.23.1.openbsd-amd64.tar.gz
|
||||||
aee34f61ba2b0a8f2618f5c7065e20da7714ce7651680509eda30728fe01ee88 go1.22.6.openbsd-arm.tar.gz
|
c30903dd8fa98b8aca8e9db0962ce9f55502aed93e0ef41e5ae148aaa0088de1 go1.23.1.openbsd-arm.tar.gz
|
||||||
c67d57daf8baada93c69c8fb02401270cd33159730b1f2d70d9e724ba1a918cf go1.22.6.openbsd-arm64.tar.gz
|
12da183489e58f9c6b357bc1b626f85ed7d4220cab31a49d6a49e6ac6a718b67 go1.23.1.openbsd-arm64.tar.gz
|
||||||
03e1f96002e94a6b381bcf66a0a62b9d5f63148682a780d727840ad540185c7c go1.22.6.openbsd-ppc64.tar.gz
|
9cc9aad37696a4a10c31dcec9e35a308de0b369dad354d54cf07406ac6fa7c6f go1.23.1.openbsd-ppc64.tar.gz
|
||||||
0ac2b5bbe2c8a293d284512630e629bf0578aaa7b7b1f39ac4ee182c7924aaad go1.22.6.plan9-386.tar.gz
|
e1d740dda062ce5a276a0c3ed7d8b6353238bc8ff405f63e2e3480bfd26a5ec5 go1.23.1.openbsd-riscv64.tar.gz
|
||||||
f9afdab8a72a8d874f023f5605482cc94160843ac768dbd840e6f772d16578c7 go1.22.6.plan9-amd64.tar.gz
|
da2a37f9987f01f096859230aa13ecc4ad2e7884465bce91004bc78c64435d65 go1.23.1.plan9-386.tar.gz
|
||||||
4b9f01a47e6a29d57cbb3097b6770583336cef9c8f0d51d3d1451e42a851002e go1.22.6.plan9-arm.tar.gz
|
fd8fff8b0697d55c4a4d02a8dc998192b80a9dc2a057647373d6ff607cad29de go1.23.1.plan9-amd64.tar.gz
|
||||||
46c2552ac7b8d6314a52e14e0a0761aaeebdd6aba5f531de386f4cf2b66ec723 go1.22.6.solaris-amd64.tar.gz
|
52efbc5804c1c86ba7868aa8ebbc31cc8c2a27b62a60fd57944970d48fc67525 go1.23.1.plan9-arm.tar.gz
|
||||||
a57821dab76af1ef7a6b62db1628f0caa74343e0c7cb829df9ce8ea0713a3e8e go1.22.6.windows-386.msi
|
f54205f21e2143f2ada1bf1c00ddf64590f5139d5c3fb77cc06175f0d8cc7567 go1.23.1.solaris-amd64.tar.gz
|
||||||
eb734bacc9aabca1273b61dd392bb84a9bb33783f5e2fff2cd6ab9885bbefbe6 go1.22.6.windows-386.zip
|
369a17f0cfd29e5c848e58ffe0d772da20abe334d1c7ca01dbcd55bb3db0b440 go1.23.1.windows-386.msi
|
||||||
1238a3e6892eb8a0eb3fe0640e18ab82ca21cc1a933f16897b2ad081f057b5da go1.22.6.windows-amd64.msi
|
ab866f47d7be56e6b1c67f1d529bf4c23331a339fb0785f435a0552d352cb257 go1.23.1.windows-386.zip
|
||||||
6023083a6e4d3199b44c37e9ba7b25d9674da20fd846a35ee5f9589d81c21a6a go1.22.6.windows-amd64.zip
|
e99dac215ee437b9bb8f8b14bbfe0e8756882c1ed291f30818e8363bc9c047a5 go1.23.1.windows-amd64.msi
|
||||||
6791218c568a3d000cb36317506541d7fd67e7cfe613baaf361ca36cad5e2cd5 go1.22.6.windows-arm.msi
|
32dedf277c86610e380e1765593edb66876f00223df71690bd6be68ee17675c0 go1.23.1.windows-amd64.zip
|
||||||
ee41ca83bb07c4fd46a1d6b2d083519bb8ca156fcd9db37ee711234d43126e2f go1.22.6.windows-arm.zip
|
23169c79dc6b54e0dffb25be6b67425ad9759392a58309bc057430a9bf4c8f6a go1.23.1.windows-arm.msi
|
||||||
91c6b3376612095315a0aeae4b03e3da34fabe9dfd4532d023e2a70f913cf22a go1.22.6.windows-arm64.msi
|
1a57615a09f13534f88e9f2d7efd5743535d1a5719b19e520eef965a634f8efb go1.23.1.windows-arm.zip
|
||||||
7cf55f357ba8116cd3bff992980e20a704ba451b3dab341cf1787b133d900512 go1.22.6.windows-arm64.zip
|
313e1a543931ad8735b4df8969e00f5f4c2ef07be21f54015ede961a70263d35 go1.23.1.windows-arm64.msi
|
||||||
|
64ad0954d2c33f556fb1018d62de091254aa6e3a94f1c8a8b16af0d3701d194e go1.23.1.windows-arm64.zip
|
||||||
|
|
||||||
# version:golangci 1.59.0
|
# version:golangci 1.59.0
|
||||||
# https://github.com/golangci/golangci-lint/releases/
|
# https://github.com/golangci/golangci-lint/releases/
|
||||||
|
|
|
||||||
233
build/ci.go
233
build/ci.go
|
|
@ -50,7 +50,6 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -127,8 +126,6 @@ var (
|
||||||
"focal", // 20.04, EOL: 04/2030
|
"focal", // 20.04, EOL: 04/2030
|
||||||
"jammy", // 22.04, EOL: 04/2032
|
"jammy", // 22.04, EOL: 04/2032
|
||||||
"noble", // 24.04, EOL: 04/2034
|
"noble", // 24.04, EOL: 04/2034
|
||||||
|
|
||||||
"mantic", // 23.10, EOL: 07/2024
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is where the tests should be unpacked.
|
// This is where the tests should be unpacked.
|
||||||
|
|
@ -162,8 +159,8 @@ func main() {
|
||||||
doLint(os.Args[2:])
|
doLint(os.Args[2:])
|
||||||
case "archive":
|
case "archive":
|
||||||
doArchive(os.Args[2:])
|
doArchive(os.Args[2:])
|
||||||
case "docker":
|
case "dockerx":
|
||||||
doDocker(os.Args[2:])
|
doDockerBuildx(os.Args[2:])
|
||||||
case "debsrc":
|
case "debsrc":
|
||||||
doDebianSource(os.Args[2:])
|
doDebianSource(os.Args[2:])
|
||||||
case "nsis":
|
case "nsis":
|
||||||
|
|
@ -240,6 +237,10 @@ func doInstall(cmdline []string) {
|
||||||
// buildFlags returns the go tool flags for building.
|
// buildFlags returns the go tool flags for building.
|
||||||
func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) {
|
func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) {
|
||||||
var ld []string
|
var ld []string
|
||||||
|
// See https://github.com/golang/go/issues/33772#issuecomment-528176001
|
||||||
|
// We need to set --buildid to the linker here, and also pass --build-id to the
|
||||||
|
// cgo-linker further down.
|
||||||
|
ld = append(ld, "--buildid=none")
|
||||||
if env.Commit != "" {
|
if env.Commit != "" {
|
||||||
ld = append(ld, "-X", "github.com/maticnetwork/bor/internal/version.gitCommit="+env.Commit)
|
ld = append(ld, "-X", "github.com/maticnetwork/bor/internal/version.gitCommit="+env.Commit)
|
||||||
ld = append(ld, "-X", "github.com/maticnetwork/bor/internal/version.gitDate="+env.Date)
|
ld = append(ld, "-X", "github.com/maticnetwork/bor/internal/version.gitDate="+env.Date)
|
||||||
|
|
@ -252,7 +253,11 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (
|
||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
// Enforce the stacksize to 8M, which is the case on most platforms apart from
|
// Enforce the stacksize to 8M, which is the case on most platforms apart from
|
||||||
// alpine Linux.
|
// alpine Linux.
|
||||||
extld := []string{"-Wl,-z,stack-size=0x800000"}
|
// See https://sourceware.org/binutils/docs-2.23.1/ld/Options.html#Options
|
||||||
|
// regarding the options --build-id=none and --strip-all. It is needed for
|
||||||
|
// reproducible builds; removing references to temporary files in C-land, and
|
||||||
|
// making build-id reproducably absent.
|
||||||
|
extld := []string{"-Wl,-z,stack-size=0x800000,--build-id=none,--strip-all"}
|
||||||
if staticLinking {
|
if staticLinking {
|
||||||
extld = append(extld, "-static")
|
extld = append(extld, "-static")
|
||||||
// Under static linking, use of certain glibc features must be
|
// Under static linking, use of certain glibc features must be
|
||||||
|
|
@ -299,7 +304,7 @@ func doTest(cmdline []string) {
|
||||||
gotest := tc.Go("test")
|
gotest := tc.Go("test")
|
||||||
|
|
||||||
// CI needs a bit more time for the statetests (default 10m).
|
// CI needs a bit more time for the statetests (default 10m).
|
||||||
gotest.Args = append(gotest.Args, "-timeout=20m")
|
gotest.Args = append(gotest.Args, "-timeout=30m")
|
||||||
|
|
||||||
// Enable CKZG backend in CI.
|
// Enable CKZG backend in CI.
|
||||||
gotest.Args = append(gotest.Args, "-tags=ckzg")
|
gotest.Args = append(gotest.Args, "-tags=ckzg")
|
||||||
|
|
@ -350,10 +355,10 @@ func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string {
|
||||||
return filepath.Join(cachedir, base)
|
return filepath.Join(cachedir, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashSourceFiles iterates all files under the top-level project directory
|
// hashAllSourceFiles iterates all files under the top-level project directory
|
||||||
// computing the hash of each file (excluding files within the tests
|
// computing the hash of each file (excluding files within the tests
|
||||||
// subrepo)
|
// subrepo)
|
||||||
func hashSourceFiles() (map[string]common.Hash, error) {
|
func hashAllSourceFiles() (map[string]common.Hash, error) {
|
||||||
res := make(map[string]common.Hash)
|
res := make(map[string]common.Hash)
|
||||||
err := filepath.WalkDir(".", func(path string, d os.DirEntry, err error) error {
|
err := filepath.WalkDir(".", func(path string, d os.DirEntry, err error) error {
|
||||||
if strings.HasPrefix(path, filepath.FromSlash("tests/testdata")) {
|
if strings.HasPrefix(path, filepath.FromSlash("tests/testdata")) {
|
||||||
|
|
@ -380,6 +385,56 @@ func hashSourceFiles() (map[string]common.Hash, error) {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hashSourceFiles iterates the provided set of filepaths (relative to the top-level geth project directory)
|
||||||
|
// computing the hash of each file.
|
||||||
|
func hashSourceFiles(files []string) (map[string]common.Hash, error) {
|
||||||
|
res := make(map[string]common.Hash)
|
||||||
|
for _, filePath := range files {
|
||||||
|
f, err := os.OpenFile(filePath, os.O_RDONLY, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hasher := sha256.New()
|
||||||
|
if _, err := io.Copy(hasher, f); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res[filePath] = common.Hash(hasher.Sum(nil))
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareHashedFilesets compares two maps (key is relative file path to top-level geth directory, value is its hash)
|
||||||
|
// and returns the list of file paths whose hashes differed.
|
||||||
|
func compareHashedFilesets(preHashes map[string]common.Hash, postHashes map[string]common.Hash) []string {
|
||||||
|
updates := []string{}
|
||||||
|
for path, postHash := range postHashes {
|
||||||
|
preHash, ok := preHashes[path]
|
||||||
|
if !ok || preHash != postHash {
|
||||||
|
updates = append(updates, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updates
|
||||||
|
}
|
||||||
|
|
||||||
|
func doGoModTidy() {
|
||||||
|
targetFiles := []string{"go.mod", "go.sum"}
|
||||||
|
preHashes, err := hashSourceFiles(targetFiles)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("failed to hash go.mod/go.sum", "err", err)
|
||||||
|
}
|
||||||
|
tc := new(build.GoToolchain)
|
||||||
|
c := tc.Go("mod", "tidy")
|
||||||
|
build.MustRun(c)
|
||||||
|
postHashes, err := hashSourceFiles(targetFiles)
|
||||||
|
updates := compareHashedFilesets(preHashes, postHashes)
|
||||||
|
for _, updatedFile := range updates {
|
||||||
|
fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile)
|
||||||
|
}
|
||||||
|
if len(updates) != 0 {
|
||||||
|
log.Fatal("go.sum and/or go.mod were updated by running 'go mod tidy'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// doGenerate ensures that re-generating generated files does not cause
|
// doGenerate ensures that re-generating generated files does not cause
|
||||||
// any mutations in the source file tree: i.e. all generated files were
|
// any mutations in the source file tree: i.e. all generated files were
|
||||||
// updated and committed. Any stale generated files are updated.
|
// updated and committed. Any stale generated files are updated.
|
||||||
|
|
@ -396,7 +451,7 @@ func doGenerate() {
|
||||||
var preHashes map[string]common.Hash
|
var preHashes map[string]common.Hash
|
||||||
if *verify {
|
if *verify {
|
||||||
var err error
|
var err error
|
||||||
preHashes, err = hashSourceFiles()
|
preHashes, err = hashAllSourceFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("failed to compute map of source hashes", "err", err)
|
log.Fatal("failed to compute map of source hashes", "err", err)
|
||||||
}
|
}
|
||||||
|
|
@ -411,17 +466,11 @@ func doGenerate() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Check if files were changed.
|
// Check if files were changed.
|
||||||
postHashes, err := hashSourceFiles()
|
postHashes, err := hashAllSourceFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("error computing source tree file hashes", "err", err)
|
log.Fatal("error computing source tree file hashes", "err", err)
|
||||||
}
|
}
|
||||||
updates := []string{}
|
updates := compareHashedFilesets(preHashes, postHashes)
|
||||||
for path, postHash := range postHashes {
|
|
||||||
preHash, ok := preHashes[path]
|
|
||||||
if !ok || preHash != postHash {
|
|
||||||
updates = append(updates, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, updatedFile := range updates {
|
for _, updatedFile := range updates {
|
||||||
fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile)
|
fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile)
|
||||||
}
|
}
|
||||||
|
|
@ -444,6 +493,8 @@ func doLint(cmdline []string) {
|
||||||
linter := downloadLinter(*cachedir)
|
linter := downloadLinter(*cachedir)
|
||||||
lflags := []string{"run", "--config", ".golangci.yml"}
|
lflags := []string{"run", "--config", ".golangci.yml"}
|
||||||
build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
|
build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
|
||||||
|
|
||||||
|
doGoModTidy()
|
||||||
fmt.Println("You have achieved perfection.")
|
fmt.Println("You have achieved perfection.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -672,10 +723,9 @@ func maybeSkipArchive(env build.Environment) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds the docker images and optionally uploads them to Docker Hub.
|
// Builds the docker images and optionally uploads them to Docker Hub.
|
||||||
func doDocker(cmdline []string) {
|
func doDockerBuildx(cmdline []string) {
|
||||||
var (
|
var (
|
||||||
image = flag.Bool("image", false, `Whether to build and push an arch specific docker image`)
|
platform = flag.String("platform", "", `Push a multi-arch docker image for the specified architectures (usually "linux/amd64,linux/arm64")`)
|
||||||
manifest = flag.String("manifest", "", `Push a multi-arch docker image for the specified architectures (usually "amd64,arm64")`)
|
|
||||||
upload = flag.String("upload", "", `Where to upload the docker image (usually "ethereum/client-go")`)
|
upload = flag.String("upload", "", `Where to upload the docker image (usually "ethereum/client-go")`)
|
||||||
)
|
)
|
||||||
flag.CommandLine.Parse(cmdline)
|
flag.CommandLine.Parse(cmdline)
|
||||||
|
|
@ -714,129 +764,26 @@ func doDocker(cmdline []string) {
|
||||||
case strings.Contains(env.Tag, "fh"):
|
case strings.Contains(env.Tag, "fh"):
|
||||||
tags = []string{"stable-fh" + tracers.FirehoseProtocolVersion, "v" + params.Version + "-fh" + tracers.FirehoseProtocolVersion}
|
tags = []string{"stable-fh" + tracers.FirehoseProtocolVersion, "v" + params.Version + "-fh" + tracers.FirehoseProtocolVersion}
|
||||||
}
|
}
|
||||||
// If architecture specific image builds are requested, build and push them
|
// Need to create a mult-arch builder
|
||||||
if *image {
|
build.MustRunCommand("docker", "buildx", "create", "--use", "--name", "multi-arch-builder", "--platform", *platform)
|
||||||
build.MustRunCommand("docker", "build", "--build-arg", "COMMIT="+env.Commit, "--build-arg", "VERSION="+params.VersionWithMeta, "--build-arg", "BUILDNUM="+env.Buildnum, "--tag", fmt.Sprintf("%s:TAG", *upload), ".")
|
|
||||||
build.MustRunCommand("docker", "build", "--build-arg", "COMMIT="+env.Commit, "--build-arg", "VERSION="+params.VersionWithMeta, "--build-arg", "BUILDNUM="+env.Buildnum, "--tag", fmt.Sprintf("%s:alltools-TAG", *upload), "-f", "Dockerfile.alltools", ".")
|
|
||||||
|
|
||||||
// Tag and upload the images to Docker Hub
|
for _, spec := range []struct {
|
||||||
for _, tag := range tags {
|
file string
|
||||||
gethImage := fmt.Sprintf("%s:%s-%s", *upload, tag, runtime.GOARCH)
|
base string
|
||||||
toolImage := fmt.Sprintf("%s:alltools-%s-%s", *upload, tag, runtime.GOARCH)
|
}{
|
||||||
|
{file: "Dockerfile", base: fmt.Sprintf("%s:", *upload)},
|
||||||
// If the image already exists (non version tag), check the build
|
{file: "Dockerfile.alltools", base: fmt.Sprintf("%s:alltools-", *upload)},
|
||||||
// number to prevent overwriting a newer commit if concurrent builds
|
} {
|
||||||
// are running. This is still a tiny bit racey if two published are
|
for _, tag := range tags { // latest, stable etc
|
||||||
// done at the same time, but that's extremely unlikely even on the
|
gethImage := fmt.Sprintf("%s%s", spec.base, tag)
|
||||||
// master branch.
|
build.MustRunCommand("docker", "buildx", "build",
|
||||||
for _, img := range []string{gethImage, toolImage} {
|
"--build-arg", "COMMIT="+env.Commit,
|
||||||
if exec.Command("docker", "pull", img).Run() != nil {
|
"--build-arg", "VERSION="+params.VersionWithMeta,
|
||||||
continue // Generally the only failure is a missing image, which is good
|
"--build-arg", "BUILDNUM="+env.Buildnum,
|
||||||
}
|
"--tag", gethImage,
|
||||||
buildnum, err := exec.Command("docker", "inspect", "--format", "{{index .Config.Labels \"buildnum\"}}", img).CombinedOutput()
|
"--platform", *platform,
|
||||||
if err != nil {
|
"--push",
|
||||||
log.Fatalf("Failed to inspect container: %v\nOutput: %s", err, string(buildnum))
|
"--file", spec.file, ".")
|
||||||
}
|
|
||||||
buildnum = bytes.TrimSpace(buildnum)
|
|
||||||
|
|
||||||
if len(buildnum) > 0 && len(env.Buildnum) > 0 {
|
|
||||||
oldnum, err := strconv.Atoi(string(buildnum))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to parse old image build number: %v", err)
|
|
||||||
}
|
|
||||||
newnum, err := strconv.Atoi(env.Buildnum)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to parse current build number: %v", err)
|
|
||||||
}
|
|
||||||
if oldnum > newnum {
|
|
||||||
log.Fatalf("Current build number %d not newer than existing %d", newnum, oldnum)
|
|
||||||
} else {
|
|
||||||
log.Printf("Updating %s from build %d to %d", img, oldnum, newnum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
build.MustRunCommand("docker", "image", "tag", fmt.Sprintf("%s:TAG", *upload), gethImage)
|
|
||||||
build.MustRunCommand("docker", "image", "tag", fmt.Sprintf("%s:alltools-TAG", *upload), toolImage)
|
|
||||||
build.MustRunCommand("docker", "push", gethImage)
|
|
||||||
build.MustRunCommand("docker", "push", toolImage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If multi-arch image manifest push is requested, assemble it
|
|
||||||
if len(*manifest) != 0 {
|
|
||||||
// Since different architectures are pushed by different builders, wait
|
|
||||||
// until all required images are updated.
|
|
||||||
var mismatch bool
|
|
||||||
for i := 0; i < 2; i++ { // 2 attempts, second is race check
|
|
||||||
mismatch = false // hope there's no mismatch now
|
|
||||||
|
|
||||||
for _, tag := range tags {
|
|
||||||
for _, arch := range strings.Split(*manifest, ",") {
|
|
||||||
gethImage := fmt.Sprintf("%s:%s-%s", *upload, tag, arch)
|
|
||||||
toolImage := fmt.Sprintf("%s:alltools-%s-%s", *upload, tag, arch)
|
|
||||||
|
|
||||||
for _, img := range []string{gethImage, toolImage} {
|
|
||||||
if out, err := exec.Command("docker", "pull", img).CombinedOutput(); err != nil {
|
|
||||||
log.Printf("Required image %s unavailable: %v\nOutput: %s", img, err, out)
|
|
||||||
mismatch = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buildnum, err := exec.Command("docker", "inspect", "--format", "{{index .Config.Labels \"buildnum\"}}", img).CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to inspect container: %v\nOutput: %s", err, string(buildnum))
|
|
||||||
}
|
|
||||||
buildnum = bytes.TrimSpace(buildnum)
|
|
||||||
|
|
||||||
if string(buildnum) != env.Buildnum {
|
|
||||||
log.Printf("Build number mismatch on %s: want %s, have %s", img, env.Buildnum, buildnum)
|
|
||||||
mismatch = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if mismatch {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if mismatch {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if mismatch {
|
|
||||||
// Build numbers mismatching, retry in a short time to
|
|
||||||
// avoid concurrent fails in both publisher images. If
|
|
||||||
// however the retry failed too, it means the concurrent
|
|
||||||
// builder is still crunching, let that do the publish.
|
|
||||||
if i == 0 {
|
|
||||||
time.Sleep(30 * time.Second)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if mismatch {
|
|
||||||
log.Println("Relinquishing publish to other builder")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Assemble and push the Geth manifest image
|
|
||||||
for _, tag := range tags {
|
|
||||||
gethImage := fmt.Sprintf("%s:%s", *upload, tag)
|
|
||||||
|
|
||||||
var gethSubImages []string
|
|
||||||
for _, arch := range strings.Split(*manifest, ",") {
|
|
||||||
gethSubImages = append(gethSubImages, gethImage+"-"+arch)
|
|
||||||
}
|
|
||||||
build.MustRunCommand("docker", append([]string{"manifest", "create", gethImage}, gethSubImages...)...)
|
|
||||||
build.MustRunCommand("docker", "manifest", "push", gethImage)
|
|
||||||
}
|
|
||||||
// Assemble and push the alltools manifest image
|
|
||||||
for _, tag := range tags {
|
|
||||||
toolImage := fmt.Sprintf("%s:alltools-%s", *upload, tag)
|
|
||||||
|
|
||||||
var toolSubImages []string
|
|
||||||
for _, arch := range strings.Split(*manifest, ",") {
|
|
||||||
toolSubImages = append(toolSubImages, toolImage+"-"+arch)
|
|
||||||
}
|
|
||||||
build.MustRunCommand("docker", append([]string{"manifest", "create", toolImage}, toolSubImages...)...)
|
|
||||||
build.MustRunCommand("docker", "manifest", "push", toolImage)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
build/deb/ethereum/completions/bash/geth
Executable file → Normal file
0
build/deb/ethereum/completions/bash/geth
Executable file → Normal file
0
build/goimports.sh
Executable file → Normal file
0
build/goimports.sh
Executable file → Normal file
0
build/travis_keepalive.sh
Executable file → Normal file
0
build/travis_keepalive.sh
Executable file → Normal file
|
|
@ -39,7 +39,7 @@ syncmode = "full"
|
||||||
# nodekeyhex = ""
|
# nodekeyhex = ""
|
||||||
[p2p.discovery]
|
[p2p.discovery]
|
||||||
# v4disc = true
|
# v4disc = true
|
||||||
# v5disc = false
|
# v5disc = true
|
||||||
bootnodes = ["enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303"]
|
bootnodes = ["enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303"]
|
||||||
# Uncomment below `bootnodes` field for Amoy
|
# Uncomment below `bootnodes` field for Amoy
|
||||||
# bootnodes = ["enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303"]
|
# bootnodes = ["enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303"]
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ func main() {
|
||||||
//TODO datadir for optional permanent database
|
//TODO datadir for optional permanent database
|
||||||
utils.MainnetFlag,
|
utils.MainnetFlag,
|
||||||
utils.SepoliaFlag,
|
utils.SepoliaFlag,
|
||||||
utils.GoerliFlag,
|
|
||||||
utils.BlsyncApiFlag,
|
utils.BlsyncApiFlag,
|
||||||
utils.BlsyncJWTSecretFlag,
|
utils.BlsyncJWTSecretFlag,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ GLOBAL OPTIONS:
|
||||||
--loglevel value log level to emit to the screen (default: 4)
|
--loglevel value log level to emit to the screen (default: 4)
|
||||||
--keystore value Directory for the keystore (default: "$HOME/.ethereum/keystore")
|
--keystore value Directory for the keystore (default: "$HOME/.ethereum/keystore")
|
||||||
--configdir value Directory for Clef configuration (default: "$HOME/.clef")
|
--configdir value Directory for Clef configuration (default: "$HOME/.clef")
|
||||||
--chainid value Chain id to use for signing (1=mainnet, 5=Goerli) (default: 1)
|
--chainid value Chain id to use for signing (1=mainnet, 17000=Holesky) (default: 1)
|
||||||
--lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength
|
--lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength
|
||||||
--nousb Disables monitoring for and managing USB hardware wallets
|
--nousb Disables monitoring for and managing USB hardware wallets
|
||||||
--pcscdpath value Path to the smartcard daemon (pcscd) socket file (default: "/run/pcscd/pcscd.comm")
|
--pcscdpath value Path to the smartcard daemon (pcscd) socket file (default: "/run/pcscd/pcscd.comm")
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ var (
|
||||||
chainIdFlag = &cli.Int64Flag{
|
chainIdFlag = &cli.Int64Flag{
|
||||||
Name: "chainid",
|
Name: "chainid",
|
||||||
Value: params.MainnetChainConfig.ChainID.Int64(),
|
Value: params.MainnetChainConfig.ChainID.Int64(),
|
||||||
Usage: "Chain id to use for signing (1=mainnet, 5=Goerli)",
|
Usage: "Chain id to use for signing (1=mainnet, 17000=Holesky)",
|
||||||
}
|
}
|
||||||
rpcPortFlag = &cli.IntFlag{
|
rpcPortFlag = &cli.IntFlag{
|
||||||
Name: "http.port",
|
Name: "http.port",
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,7 @@ func TestMain(m *testing.M) {
|
||||||
func runClef(t *testing.T, args ...string) *testproc {
|
func runClef(t *testing.T, args ...string) *testproc {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
ddir, err := os.MkdirTemp("", "cleftest-*")
|
ddir := t.TempDir()
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Cleanup(func() {
|
|
||||||
os.RemoveAll(ddir)
|
|
||||||
})
|
|
||||||
|
|
||||||
return runWithKeystore(t, ddir, args...)
|
return runWithKeystore(t, ddir, args...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/cli"
|
"github.com/ethereum/go-ethereum/internal/cli"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
params.UpdateBorInfo()
|
||||||
os.Exit(cli.Run(os.Args[1:]))
|
os.Exit(cli.Run(os.Args[1:]))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ set to standard output. The following filters are supported:
|
||||||
- `-limit <N>` limits the output set to N entries, taking the top N nodes by score
|
- `-limit <N>` limits the output set to N entries, taking the top N nodes by score
|
||||||
- `-ip <CIDR>` filters nodes by IP subnet
|
- `-ip <CIDR>` filters nodes by IP subnet
|
||||||
- `-min-age <duration>` filters nodes by 'first seen' time
|
- `-min-age <duration>` filters nodes by 'first seen' time
|
||||||
- `-eth-network <mainnet/goerli/sepolia/holesky>` filters nodes by "eth" ENR entry
|
- `-eth-network <mainnet/sepolia/holesky>` filters nodes by "eth" ENR entry
|
||||||
- `-les-server` filters nodes by LES server support
|
- `-les-server` filters nodes by LES server support
|
||||||
- `-snap` filters nodes by snap protocol support
|
- `-snap` filters nodes by snap protocol support
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,8 @@ func (c *cloudflareClient) checkZone(name string) error {
|
||||||
if !strings.HasSuffix(name, "."+zone.Name) {
|
if !strings.HasSuffix(name, "."+zone.Name) {
|
||||||
return fmt.Errorf("CloudFlare zone name %q does not match name %q to be deployed", zone.Name, name)
|
return fmt.Errorf("CloudFlare zone name %q does not match name %q to be deployed", zone.Name, name)
|
||||||
}
|
}
|
||||||
|
// Necessary permissions for Cloudlare management - Zone:Read, DNS:Read, Zone:Edit, DNS:Edit
|
||||||
needPerms := map[string]bool{"#zone:edit": false, "#zone:read": false}
|
needPerms := map[string]bool{"#zone:edit": false, "#zone:read": false, "#dns_records:read": false, "#dns_records:edit": false}
|
||||||
for _, perm := range zone.Permissions {
|
for _, perm := range zone.Permissions {
|
||||||
if _, ok := needPerms[perm]; ok {
|
if _, ok := needPerms[perm]; ok {
|
||||||
needPerms[perm] = true
|
needPerms[perm] = true
|
||||||
|
|
|
||||||
0
cmd/devp2p/internal/ethtest/testdata/chain.rlp.gz
vendored
Executable file → Normal file
0
cmd/devp2p/internal/ethtest/testdata/chain.rlp.gz
vendored
Executable file → Normal file
|
|
@ -259,8 +259,6 @@ func ethFilter(args []string) (nodeFilter, error) {
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case "mainnet":
|
case "mainnet":
|
||||||
filter = forkid.NewStaticFilter(params.MainnetChainConfig, core.DefaultGenesisBlock().ToBlock())
|
filter = forkid.NewStaticFilter(params.MainnetChainConfig, core.DefaultGenesisBlock().ToBlock())
|
||||||
case "goerli":
|
|
||||||
filter = forkid.NewStaticFilter(params.GoerliChainConfig, core.DefaultGoerliGenesisBlock().ToBlock())
|
|
||||||
case "sepolia":
|
case "sepolia":
|
||||||
filter = forkid.NewStaticFilter(params.SepoliaChainConfig, core.DefaultSepoliaGenesisBlock().ToBlock())
|
filter = forkid.NewStaticFilter(params.SepoliaChainConfig, core.DefaultSepoliaGenesisBlock().ToBlock())
|
||||||
case "bor-mumbai":
|
case "bor-mumbai":
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ type ExecutionResult struct {
|
||||||
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
||||||
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
||||||
|
RequestsHash *common.Hash `json:"requestsRoot,omitempty"`
|
||||||
|
DepositRequests *types.Deposits `json:"depositRequests,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ommer struct {
|
type ommer struct {
|
||||||
|
|
@ -201,7 +203,14 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
|
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
}
|
}
|
||||||
|
if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number)) {
|
||||||
|
var (
|
||||||
|
prevNumber = pre.Env.Number - 1
|
||||||
|
prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)]
|
||||||
|
evm = vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
|
||||||
|
)
|
||||||
|
core.ProcessParentBlockHash(prevHash, evm, statedb)
|
||||||
|
}
|
||||||
for i := 0; txIt.Next(); i++ {
|
for i := 0; txIt.Next(); i++ {
|
||||||
tx, err := txIt.Tx()
|
tx, err := txIt.Tx()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -385,9 +394,31 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
||||||
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
||||||
}
|
}
|
||||||
|
if chainConfig.IsPrague(vmContext.BlockNumber) && chainConfig.Bor == nil {
|
||||||
|
// Parse the requests from the logs
|
||||||
|
var allLogs []*types.Log
|
||||||
|
for _, receipt := range receipts {
|
||||||
|
allLogs = append(allLogs, receipt.Logs...)
|
||||||
|
}
|
||||||
|
requests, err := core.ParseDepositLogs(allLogs, chainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
|
||||||
|
}
|
||||||
|
// Calculate the requests root
|
||||||
|
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
|
||||||
|
execRs.RequestsHash = &h
|
||||||
|
// Get the deposits from the requests
|
||||||
|
deposits := make(types.Deposits, 0)
|
||||||
|
for _, req := range requests {
|
||||||
|
if dep, ok := req.Inner().(*types.Deposit); ok {
|
||||||
|
deposits = append(deposits, dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
execRs.DepositRequests = &deposits
|
||||||
|
}
|
||||||
// Re-create statedb instance with new root upon the updated database
|
// Re-create statedb instance with new root upon the updated database
|
||||||
// for accessing latest states.
|
// for accessing latest states.
|
||||||
statedb, err = state.New(root, statedb.Database(), nil)
|
statedb, err = state.New(root, statedb.Database())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
||||||
}
|
}
|
||||||
|
|
@ -396,8 +427,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
|
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
|
||||||
sdb := state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
|
||||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
sdb := state.NewDatabase(tdb, nil)
|
||||||
|
statedb, _ := state.New(types.EmptyRootHash, sdb)
|
||||||
for addr, a := range accounts {
|
for addr, a := range accounts {
|
||||||
statedb.SetCode(addr, a.Code)
|
statedb.SetCode(addr, a.Code)
|
||||||
statedb.SetNonce(addr, a.Nonce)
|
statedb.SetNonce(addr, a.Nonce)
|
||||||
|
|
@ -408,8 +440,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
|
||||||
}
|
}
|
||||||
// Commit and re-open to start with a clean state.
|
// Commit and re-open to start with a clean state.
|
||||||
root, _ := statedb.Commit(0, false)
|
root, _ := statedb.Commit(0, false)
|
||||||
statedb, _ = state.New(root, sdb, nil)
|
statedb, _ = state.New(root, sdb)
|
||||||
|
|
||||||
return statedb
|
return statedb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,8 +163,8 @@ func runCmd(ctx *cli.Context) error {
|
||||||
})
|
})
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
genesis := genesisConfig.MustCommit(db, triedb)
|
genesis := genesisConfig.MustCommit(db, triedb)
|
||||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
sdb := state.NewDatabase(triedb, nil)
|
||||||
statedb, _ = state.New(genesis.Root(), sdb, nil)
|
statedb, _ = state.New(genesis.Root(), sdb)
|
||||||
chainConfig = genesisConfig.Config
|
chainConfig = genesisConfig.Config
|
||||||
|
|
||||||
if ctx.String(SenderFlag.Name) != "" {
|
if ctx.String(SenderFlag.Name) != "" {
|
||||||
|
|
@ -297,7 +297,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
fmt.Printf("Failed to commit changes %v\n", err)
|
fmt.Printf("Failed to commit changes %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dumpdb, err := state.New(root, sdb, nil)
|
dumpdb, err := state.New(root, sdb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to open statedb %v\n", err)
|
fmt.Printf("Failed to open statedb %v\n", err)
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ func runStateTest(fname string, cfg vm.Config, dump bool) error {
|
||||||
result.Root = &root
|
result.Root = &root
|
||||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||||
if dump { // Dump any state to aid debugging
|
if dump { // Dump any state to aid debugging
|
||||||
cpy, _ := state.New(root, tstate.StateDB.Database(), nil)
|
cpy, _ := state.New(root, tstate.StateDB.Database())
|
||||||
dump := cpy.RawDump(nil)
|
dump := cpy.RawDump(nil)
|
||||||
result.State = &dump
|
result.State = &dump
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -226,8 +226,8 @@ func initGenesis(ctx *cli.Context) error {
|
||||||
v := ctx.Int64(utils.OverrideVerkle.Name)
|
v := ctx.Int64(utils.OverrideVerkle.Name)
|
||||||
overrides.OverrideVerkle = new(big.Int).SetInt64(v)
|
overrides.OverrideVerkle = new(big.Int).SetInt64(v)
|
||||||
}
|
}
|
||||||
for _, name := range []string{"chaindata", "lightchaindata"} {
|
|
||||||
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, false, false)
|
chaindb, err := stack.OpenDatabaseWithFreezer("chaindata", 0, 0, ctx.String(utils.AncientFlag.Name), "", false, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to open database: %v", err)
|
utils.Fatalf("Failed to open database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -240,8 +240,8 @@ func initGenesis(ctx *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to write genesis block: %v", err)
|
utils.Fatalf("Failed to write genesis block: %v", err)
|
||||||
}
|
}
|
||||||
log.Info("Successfully wrote genesis state", "database", name, "hash", hash)
|
|
||||||
}
|
log.Info("Successfully wrote genesis state", "database", "chaindata", "hash", hash)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -265,25 +265,18 @@ func dumpGenesis(ctx *cli.Context) error {
|
||||||
|
|
||||||
// dump whatever already exists in the datadir
|
// dump whatever already exists in the datadir
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
for _, name := range []string{"chaindata", "lightchaindata"} {
|
|
||||||
db, err := stack.OpenDatabase(name, 0, 0, "", true)
|
|
||||||
|
|
||||||
|
db, err := stack.OpenDatabase("chaindata", 0, 0, "", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
continue
|
genesis, err = core.ReadGenesis(db)
|
||||||
}
|
|
||||||
|
|
||||||
genesis, err := core.ReadGenesis(db)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("failed to read genesis: %s", err)
|
utils.Fatalf("failed to read genesis: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Close()
|
|
||||||
|
|
||||||
if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil {
|
if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil {
|
||||||
utils.Fatalf("could not encode stored genesis: %s", err)
|
utils.Fatalf("could not encode stored genesis: %s", err)
|
||||||
}
|
}
|
||||||
|
|
@ -291,13 +284,6 @@ func dumpGenesis(ctx *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(utils.DataDirFlag.Name) {
|
|
||||||
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
|
|
||||||
}
|
|
||||||
utils.Fatalf("no network preset provided, and no genesis exists in the default datadir")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func importChain(ctx *cli.Context) error {
|
func importChain(ctx *cli.Context) error {
|
||||||
if ctx.Args().Len() < 1 {
|
if ctx.Args().Len() < 1 {
|
||||||
utils.Fatalf("This command requires an argument.")
|
utils.Fatalf("This command requires an argument.")
|
||||||
|
|
@ -451,8 +437,6 @@ func importHistory(ctx *cli.Context) error {
|
||||||
network = "mainnet"
|
network = "mainnet"
|
||||||
case ctx.Bool(utils.SepoliaFlag.Name):
|
case ctx.Bool(utils.SepoliaFlag.Name):
|
||||||
network = "sepolia"
|
network = "sepolia"
|
||||||
case ctx.Bool(utils.GoerliFlag.Name):
|
|
||||||
network = "goerli"
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No network flag set, try to determine network based on files
|
// No network flag set, try to determine network based on files
|
||||||
|
|
@ -596,8 +580,7 @@ func parseDumpConfig(ctx *cli.Context, db ethdb.Database) (*state.DumpConfig, co
|
||||||
default:
|
default:
|
||||||
return nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg)
|
return nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg)
|
||||||
}
|
}
|
||||||
|
conf := &state.DumpConfig{
|
||||||
var conf = &state.DumpConfig{
|
|
||||||
SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name),
|
SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name),
|
||||||
SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
|
SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
|
||||||
OnlyWithAddresses: !ctx.Bool(utils.IncludeIncompletesFlag.Name),
|
OnlyWithAddresses: !ctx.Bool(utils.IncludeIncompletesFlag.Name),
|
||||||
|
|
@ -625,7 +608,7 @@ func dump(ctx *cli.Context) error {
|
||||||
triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
|
triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
state, err := state.New(root, state.NewDatabase(triedb, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@ var tomlSettings = toml.Config{
|
||||||
},
|
},
|
||||||
MissingField: func(rt reflect.Type, field string) error {
|
MissingField: func(rt reflect.Type, field string) error {
|
||||||
id := fmt.Sprintf("%s.%s", rt.String(), field)
|
id := fmt.Sprintf("%s.%s", rt.String(), field)
|
||||||
if deprecated(id) {
|
if deprecatedConfigFields[id] {
|
||||||
log.Warn("Config field is deprecated and won't have an effect", "name", id)
|
log.Warn(fmt.Sprintf("Config field '%s' is deprecated and won't have any effect.", id))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var link string
|
var link string
|
||||||
|
|
@ -91,6 +91,19 @@ var tomlSettings = toml.Config{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var deprecatedConfigFields = map[string]bool{
|
||||||
|
"ethconfig.Config.EVMInterpreter": true,
|
||||||
|
"ethconfig.Config.EWASMInterpreter": true,
|
||||||
|
"ethconfig.Config.TrieCleanCacheJournal": true,
|
||||||
|
"ethconfig.Config.TrieCleanCacheRejournal": true,
|
||||||
|
"ethconfig.Config.LightServ": true,
|
||||||
|
"ethconfig.Config.LightIngress": true,
|
||||||
|
"ethconfig.Config.LightEgress": true,
|
||||||
|
"ethconfig.Config.LightPeers": true,
|
||||||
|
"ethconfig.Config.LightNoPrune": true,
|
||||||
|
"ethconfig.Config.LightNoSyncServe": true,
|
||||||
|
}
|
||||||
|
|
||||||
type ethstatsConfig struct {
|
type ethstatsConfig struct {
|
||||||
URL string `toml:",omitempty"`
|
URL string `toml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
@ -335,21 +348,6 @@ func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func deprecated(field string) bool {
|
|
||||||
switch field {
|
|
||||||
case "ethconfig.Config.EVMInterpreter":
|
|
||||||
return true
|
|
||||||
case "ethconfig.Config.EWASMInterpreter":
|
|
||||||
return true
|
|
||||||
case "ethconfig.Config.TrieCleanCacheJournal":
|
|
||||||
return true
|
|
||||||
case "ethconfig.Config.TrieCleanCacheRejournal":
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setAccountManagerBackends(conf *node.Config, am *accounts.Manager, keydir string) error {
|
func setAccountManagerBackends(conf *node.Config, am *accounts.Manager, keydir string) error {
|
||||||
scryptN := keystore.StandardScryptN
|
scryptN := keystore.StandardScryptN
|
||||||
scryptP := keystore.StandardScryptP
|
scryptP := keystore.StandardScryptP
|
||||||
|
|
|
||||||
|
|
@ -129,9 +129,7 @@ func remoteConsole(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if path != "" {
|
if path != "" {
|
||||||
if ctx.Bool(utils.GoerliFlag.Name) {
|
if ctx.Bool(utils.MumbaiFlag.Name) || ctx.Bool(utils.AmoyFlag.Name) || ctx.Bool(utils.BorMainnetFlag.Name) {
|
||||||
path = filepath.Join(path, "goerli")
|
|
||||||
} else if ctx.Bool(utils.MumbaiFlag.Name) || ctx.Bool(utils.AmoyFlag.Name) || ctx.Bool(utils.BorMainnetFlag.Name) {
|
|
||||||
homeDir, _ := os.UserHomeDir()
|
homeDir, _ := os.UserHomeDir()
|
||||||
path = filepath.Join(homeDir, "/.bor/data")
|
path = filepath.Join(homeDir, "/.bor/data")
|
||||||
} else if ctx.Bool(utils.SepoliaFlag.Name) {
|
} else if ctx.Bool(utils.SepoliaFlag.Name) {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ipcAPIs = "admin:1.0 bor:1.0 clique:1.0 debug:1.0 engine:1.0 eth:1.0 miner:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0"
|
ipcAPIs = "admin:1.0 bor:1.0 debug:1.0 engine:1.0 eth:1.0 miner:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0"
|
||||||
httpAPIs = "eth:1.0 net:1.0 rpc:1.0 web3:1.0"
|
httpAPIs = "eth:1.0 net:1.0 rpc:1.0 web3:1.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -38,10 +38,10 @@ const (
|
||||||
// memory and disk IO. If the args don't set --datadir, the
|
// memory and disk IO. If the args don't set --datadir, the
|
||||||
// child g gets a temporary data directory.
|
// child g gets a temporary data directory.
|
||||||
func runMinimalGeth(t *testing.T, args ...string) *testgeth {
|
func runMinimalGeth(t *testing.T, args ...string) *testgeth {
|
||||||
// --goerli to make the 'writing genesis to disk' faster (no accounts)
|
// --holesky to make the 'writing genesis to disk' faster (no accounts)
|
||||||
// --networkid=1337 to avoid cache bump
|
// --networkid=1337 to avoid cache bump
|
||||||
// --syncmode=full to avoid allocating fast sync bloom
|
// --syncmode=full to avoid allocating fast sync bloom
|
||||||
allArgs := []string{"--goerli", "--networkid", "1337", "--authrpc.port", "0", "--syncmode=full", "--port", "0",
|
allArgs := []string{"--holesky", "--networkid", "1337", "--authrpc.port", "0", "--syncmode=full", "--port", "0",
|
||||||
"--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64",
|
"--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64",
|
||||||
"--datadir.minfreedisk", "0"}
|
"--datadir.minfreedisk", "0"}
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ func TestConsoleWelcome(t *testing.T) {
|
||||||
geth.SetTemplateFunc("gover", runtime.Version)
|
geth.SetTemplateFunc("gover", runtime.Version)
|
||||||
geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
||||||
geth.SetTemplateFunc("niltime", func() string {
|
geth.SetTemplateFunc("niltime", func() string {
|
||||||
return time.Unix(1548854791, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||||
})
|
})
|
||||||
geth.SetTemplateFunc("apis", func() string { return ipcAPIs })
|
geth.SetTemplateFunc("apis", func() string { return ipcAPIs })
|
||||||
|
|
||||||
|
|
@ -133,7 +133,7 @@ func testAttachWelcome(t *testing.T, geth *testgeth, endpoint, apis string) {
|
||||||
attach.SetTemplateFunc("gover", runtime.Version)
|
attach.SetTemplateFunc("gover", runtime.Version)
|
||||||
attach.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
attach.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
||||||
attach.SetTemplateFunc("niltime", func() string {
|
attach.SetTemplateFunc("niltime", func() string {
|
||||||
return time.Unix(1548854791, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||||
})
|
})
|
||||||
attach.SetTemplateFunc("ipc", func() bool { return strings.HasPrefix(endpoint, "ipc") })
|
attach.SetTemplateFunc("ipc", func() bool { return strings.HasPrefix(endpoint, "ipc") })
|
||||||
attach.SetTemplateFunc("datadir", func() string { return geth.Datadir })
|
attach.SetTemplateFunc("datadir", func() string { return geth.Datadir })
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,6 @@ var (
|
||||||
utils.BeaconGenesisRootFlag,
|
utils.BeaconGenesisRootFlag,
|
||||||
utils.BeaconGenesisTimeFlag,
|
utils.BeaconGenesisTimeFlag,
|
||||||
utils.BeaconCheckpointFlag,
|
utils.BeaconCheckpointFlag,
|
||||||
utils.CollectWitnessFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags)
|
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||||
|
|
||||||
rpcFlags = []cli.Flag{
|
rpcFlags = []cli.Flag{
|
||||||
|
|
@ -299,9 +298,6 @@ func main() {
|
||||||
func prepare(ctx *cli.Context) {
|
func prepare(ctx *cli.Context) {
|
||||||
// If we're running a known preset, log it for convenience.
|
// If we're running a known preset, log it for convenience.
|
||||||
switch {
|
switch {
|
||||||
case ctx.IsSet(utils.GoerliFlag.Name):
|
|
||||||
log.Info("Starting Geth on Görli testnet...")
|
|
||||||
|
|
||||||
case ctx.IsSet(utils.SepoliaFlag.Name):
|
case ctx.IsSet(utils.SepoliaFlag.Name):
|
||||||
log.Info("Starting Geth on Sepolia testnet...")
|
log.Info("Starting Geth on Sepolia testnet...")
|
||||||
|
|
||||||
|
|
@ -339,8 +335,8 @@ func prepare(ctx *cli.Context) {
|
||||||
if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
||||||
// Make sure we're not on any supported preconfigured testnet either
|
// Make sure we're not on any supported preconfigured testnet either
|
||||||
if !ctx.IsSet(utils.SepoliaFlag.Name) &&
|
if !ctx.IsSet(utils.SepoliaFlag.Name) &&
|
||||||
!ctx.IsSet(utils.GoerliFlag.Name) &&
|
|
||||||
!ctx.IsSet(utils.MumbaiFlag.Name) &&
|
!ctx.IsSet(utils.MumbaiFlag.Name) &&
|
||||||
|
!ctx.IsSet(utils.HoleskyFlag.Name) &&
|
||||||
!ctx.IsSet(utils.AmoyFlag.Name) &&
|
!ctx.IsSet(utils.AmoyFlag.Name) &&
|
||||||
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||||
// Nope, we're really on mainnet. Bump that cache up!
|
// Nope, we're really on mainnet. Bump that cache up!
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
|
|
@ -22,6 +23,13 @@ var (
|
||||||
Value: "http://localhost:1317",
|
Value: "http://localhost:1317",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HeimdallTimeoutFlag flag for heimdall timeout
|
||||||
|
HeimdallTimeoutFlag = &cli.DurationFlag{
|
||||||
|
Name: "bor.heimdalltimeout",
|
||||||
|
Usage: "Timeout of Heimdall service",
|
||||||
|
Value: 5 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
// WithoutHeimdallFlag no heimdall (for testing purpose)
|
// WithoutHeimdallFlag no heimdall (for testing purpose)
|
||||||
WithoutHeimdallFlag = &cli.BoolFlag{
|
WithoutHeimdallFlag = &cli.BoolFlag{
|
||||||
Name: "bor.withoutheimdall",
|
Name: "bor.withoutheimdall",
|
||||||
|
|
@ -56,6 +64,7 @@ var (
|
||||||
// BorFlags all bor related flags
|
// BorFlags all bor related flags
|
||||||
BorFlags = []cli.Flag{
|
BorFlags = []cli.Flag{
|
||||||
HeimdallURLFlag,
|
HeimdallURLFlag,
|
||||||
|
HeimdallTimeoutFlag,
|
||||||
WithoutHeimdallFlag,
|
WithoutHeimdallFlag,
|
||||||
HeimdallgRPCAddressFlag,
|
HeimdallgRPCAddressFlag,
|
||||||
RunHeimdallFlag,
|
RunHeimdallFlag,
|
||||||
|
|
@ -67,6 +76,7 @@ var (
|
||||||
// SetBorConfig sets bor config
|
// SetBorConfig sets bor config
|
||||||
func SetBorConfig(ctx *cli.Context, cfg *eth.Config) {
|
func SetBorConfig(ctx *cli.Context, cfg *eth.Config) {
|
||||||
cfg.HeimdallURL = ctx.String(HeimdallURLFlag.Name)
|
cfg.HeimdallURL = ctx.String(HeimdallURLFlag.Name)
|
||||||
|
cfg.HeimdallTimeout = ctx.Duration(HeimdallTimeoutFlag.Name)
|
||||||
cfg.WithoutHeimdall = ctx.Bool(WithoutHeimdallFlag.Name)
|
cfg.WithoutHeimdall = ctx.Bool(WithoutHeimdallFlag.Name)
|
||||||
cfg.HeimdallgRPCAddress = ctx.String(HeimdallgRPCAddressFlag.Name)
|
cfg.HeimdallgRPCAddress = ctx.String(HeimdallgRPCAddressFlag.Name)
|
||||||
cfg.RunHeimdall = ctx.Bool(RunHeimdallFlag.Name)
|
cfg.RunHeimdall = ctx.Bool(RunHeimdallFlag.Name)
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ var (
|
||||||
}
|
}
|
||||||
NetworkIdFlag = &cli.Uint64Flag{
|
NetworkIdFlag = &cli.Uint64Flag{
|
||||||
Name: "networkid",
|
Name: "networkid",
|
||||||
Usage: "Explicitly set network id (integer)(For testnets: use --goerli, --sepolia, --holesky instead)",
|
Usage: "Explicitly set network id (integer)(For testnets: use --sepolia, --holesky instead)",
|
||||||
Value: ethconfig.Defaults.NetworkId,
|
Value: ethconfig.Defaults.NetworkId,
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
|
|
@ -144,11 +144,6 @@ var (
|
||||||
Usage: "Ethereum mainnet",
|
Usage: "Ethereum mainnet",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
GoerliFlag = &cli.BoolFlag{
|
|
||||||
Name: "goerli",
|
|
||||||
Usage: "Görli network: pre-configured proof-of-authority test network",
|
|
||||||
Category: flags.EthCategory,
|
|
||||||
}
|
|
||||||
SepoliaFlag = &cli.BoolFlag{
|
SepoliaFlag = &cli.BoolFlag{
|
||||||
Name: "sepolia",
|
Name: "sepolia",
|
||||||
Usage: "Sepolia network: pre-configured proof-of-work test network",
|
Usage: "Sepolia network: pre-configured proof-of-work test network",
|
||||||
|
|
@ -644,11 +639,6 @@ var (
|
||||||
Usage: "Disables db compaction after import",
|
Usage: "Disables db compaction after import",
|
||||||
Category: flags.LoggingCategory,
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
CollectWitnessFlag = &cli.BoolFlag{
|
|
||||||
Name: "collectwitness",
|
|
||||||
Usage: "Enable state witness generation during block execution. Work in progress flag, don't use.",
|
|
||||||
Category: flags.MiscCategory,
|
|
||||||
}
|
|
||||||
|
|
||||||
// MISC settings
|
// MISC settings
|
||||||
SyncTargetFlag = &cli.StringFlag{
|
SyncTargetFlag = &cli.StringFlag{
|
||||||
|
|
@ -851,8 +841,9 @@ var (
|
||||||
DiscoveryV5Flag = &cli.BoolFlag{
|
DiscoveryV5Flag = &cli.BoolFlag{
|
||||||
Name: "discovery.v5",
|
Name: "discovery.v5",
|
||||||
Aliases: []string{"discv5"},
|
Aliases: []string{"discv5"},
|
||||||
Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
|
Usage: "Enables the V5 discovery mechanism",
|
||||||
Category: flags.NetworkingCategory,
|
Category: flags.NetworkingCategory,
|
||||||
|
Value: true,
|
||||||
}
|
}
|
||||||
NetrestrictFlag = &cli.StringFlag{
|
NetrestrictFlag = &cli.StringFlag{
|
||||||
Name: "netrestrict",
|
Name: "netrestrict",
|
||||||
|
|
@ -1004,7 +995,6 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
||||||
var (
|
var (
|
||||||
// TestnetFlags is the flag group of all built-in supported testnets.
|
// TestnetFlags is the flag group of all built-in supported testnets.
|
||||||
TestnetFlags = []cli.Flag{
|
TestnetFlags = []cli.Flag{
|
||||||
GoerliFlag,
|
|
||||||
SepoliaFlag,
|
SepoliaFlag,
|
||||||
}
|
}
|
||||||
// NetworkFlags is the flag group of all built-in supported networks.
|
// NetworkFlags is the flag group of all built-in supported networks.
|
||||||
|
|
@ -1026,10 +1016,6 @@ var (
|
||||||
// then a subdirectory of the specified datadir will be used.
|
// then a subdirectory of the specified datadir will be used.
|
||||||
func MakeDataDir(ctx *cli.Context) string {
|
func MakeDataDir(ctx *cli.Context) string {
|
||||||
if path := ctx.String(DataDirFlag.Name); path != "" {
|
if path := ctx.String(DataDirFlag.Name); path != "" {
|
||||||
if ctx.Bool(GoerliFlag.Name) {
|
|
||||||
return filepath.Join(path, "goerli")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Bool(SepoliaFlag.Name) {
|
if ctx.Bool(SepoliaFlag.Name) {
|
||||||
return filepath.Join(path, "sepolia")
|
return filepath.Join(path, "sepolia")
|
||||||
}
|
}
|
||||||
|
|
@ -1083,7 +1069,7 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
|
||||||
//
|
//
|
||||||
// 1. --bootnodes flag
|
// 1. --bootnodes flag
|
||||||
// 2. Config file
|
// 2. Config file
|
||||||
// 3. Network preset flags (e.g. --goerli)
|
// 3. Network preset flags (e.g. --holesky)
|
||||||
// 4. default to mainnet nodes
|
// 4. default to mainnet nodes
|
||||||
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
urls := params.MainnetBootnodes
|
urls := params.MainnetBootnodes
|
||||||
|
|
@ -1096,8 +1082,6 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
switch {
|
switch {
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
urls = params.SepoliaBootnodes
|
urls = params.SepoliaBootnodes
|
||||||
case ctx.Bool(GoerliFlag.Name):
|
|
||||||
urls = params.GoerliBootnodes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg.BootstrapNodes = mustParseBootnodes(urls)
|
cfg.BootstrapNodes = mustParseBootnodes(urls)
|
||||||
|
|
@ -1378,8 +1362,8 @@ func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error
|
||||||
|
|
||||||
// setEtherbase retrieves the etherbase from the directly specified command line flags.
|
// setEtherbase retrieves the etherbase from the directly specified command line flags.
|
||||||
func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
|
func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
if !ctx.IsSet(MinerEtherbaseFlag.Name) {
|
if ctx.IsSet(MinerEtherbaseFlag.Name) {
|
||||||
return
|
log.Warn("Option --miner.etherbase is deprecated as the etherbase is set by the consensus client post-merge")
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := ctx.String(MinerEtherbaseFlag.Name)
|
addr := ctx.String(MinerEtherbaseFlag.Name)
|
||||||
|
|
@ -1556,8 +1540,6 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) {
|
||||||
cfg.DataDir = ctx.String(DataDirFlag.Name)
|
cfg.DataDir = ctx.String(DataDirFlag.Name)
|
||||||
case ctx.Bool(DeveloperFlag.Name):
|
case ctx.Bool(DeveloperFlag.Name):
|
||||||
cfg.DataDir = "" // unless explicitly requested, use memory databases
|
cfg.DataDir = "" // unless explicitly requested, use memory databases
|
||||||
case ctx.Bool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
|
||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
|
|
||||||
case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
|
||||||
}
|
}
|
||||||
|
|
@ -1752,7 +1734,7 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) {
|
||||||
// SetEthConfig applies eth-related command line flags to the config.
|
// SetEthConfig applies eth-related command line flags to the config.
|
||||||
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// Avoid conflicting network flags
|
// Avoid conflicting network flags
|
||||||
CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag, HoleskyFlag)
|
CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag)
|
||||||
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
||||||
|
|
||||||
// Set configurations from CLI flags
|
// Set configurations from CLI flags
|
||||||
|
|
@ -1889,9 +1871,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// TODO(fjl): force-enable this in --dev mode
|
// TODO(fjl): force-enable this in --dev mode
|
||||||
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.IsSet(CollectWitnessFlag.Name) {
|
|
||||||
cfg.EnableWitnessCollection = ctx.Bool(CollectWitnessFlag.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
|
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
|
||||||
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
|
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
|
||||||
|
|
@ -1937,13 +1916,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
|
|
||||||
cfg.Genesis = core.DefaultSepoliaGenesisBlock()
|
cfg.Genesis = core.DefaultSepoliaGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
|
||||||
case ctx.Bool(GoerliFlag.Name):
|
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
|
||||||
cfg.NetworkId = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.Genesis = core.DefaultGoerliGenesisBlock()
|
|
||||||
SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash)
|
|
||||||
case ctx.Bool(DeveloperFlag.Name):
|
case ctx.Bool(DeveloperFlag.Name):
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||||
cfg.NetworkId = 1337
|
cfg.NetworkId = 1337
|
||||||
|
|
@ -2071,7 +2043,7 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
|
||||||
|
|
||||||
// RegisterEthService adds an Ethereum client to the stack.
|
// RegisterEthService adds an Ethereum client to the stack.
|
||||||
// The second return value is the full node instance.
|
// The second return value is the full node instance.
|
||||||
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) {
|
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (*eth.EthAPIBackend, *eth.Ethereum) {
|
||||||
backend, err := eth.New(stack, cfg)
|
backend, err := eth.New(stack, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Failed to register the Ethereum service: %v", err)
|
Fatalf("Failed to register the Ethereum service: %v", err)
|
||||||
|
|
@ -2081,7 +2053,7 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterEthStatsService configures the Ethereum Stats daemon and adds it to the node.
|
// RegisterEthStatsService configures the Ethereum Stats daemon and adds it to the node.
|
||||||
func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) {
|
func RegisterEthStatsService(stack *node.Node, backend *eth.EthAPIBackend, url string) {
|
||||||
if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil {
|
if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil {
|
||||||
Fatalf("Failed to register the Ethereum Stats service: %v", err)
|
Fatalf("Failed to register the Ethereum Stats service: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2216,8 +2188,6 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFree
|
||||||
}
|
}
|
||||||
|
|
||||||
chainDb = remotedb.New(client)
|
chainDb = remotedb.New(client)
|
||||||
case ctx.String(SyncModeFlag.Name) == "light":
|
|
||||||
chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
|
|
||||||
default:
|
default:
|
||||||
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false)
|
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly, disableFreeze, false)
|
||||||
}
|
}
|
||||||
|
|
@ -2290,8 +2260,6 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
|
||||||
genesis = core.DefaultGenesisBlock()
|
genesis = core.DefaultGenesisBlock()
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
genesis = core.DefaultSepoliaGenesisBlock()
|
genesis = core.DefaultSepoliaGenesisBlock()
|
||||||
case ctx.Bool(GoerliFlag.Name):
|
|
||||||
genesis = core.DefaultGoerliGenesisBlock()
|
|
||||||
case ctx.Bool(DeveloperFlag.Name):
|
case ctx.Bool(DeveloperFlag.Name):
|
||||||
Fatalf("Developer chains are ephemeral")
|
Fatalf("Developer chains are ephemeral")
|
||||||
}
|
}
|
||||||
|
|
@ -2314,6 +2282,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
configs := ðconfig.Config{
|
configs := ðconfig.Config{
|
||||||
Genesis: gspec,
|
Genesis: gspec,
|
||||||
HeimdallURL: ctx.String(HeimdallURLFlag.Name),
|
HeimdallURL: ctx.String(HeimdallURLFlag.Name),
|
||||||
|
HeimdallTimeout: ctx.Duration(HeimdallTimeoutFlag.Name),
|
||||||
WithoutHeimdall: ctx.Bool(WithoutHeimdallFlag.Name),
|
WithoutHeimdall: ctx.Bool(WithoutHeimdallFlag.Name),
|
||||||
HeimdallgRPCAddress: ctx.String(HeimdallgRPCAddressFlag.Name),
|
HeimdallgRPCAddress: ctx.String(HeimdallgRPCAddressFlag.Name),
|
||||||
RunHeimdall: ctx.Bool(RunHeimdallArgsFlag.Name),
|
RunHeimdall: ctx.Bool(RunHeimdallArgsFlag.Name),
|
||||||
|
|
@ -2367,7 +2336,6 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
}
|
}
|
||||||
vmcfg := vm.Config{
|
vmcfg := vm.Config{
|
||||||
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
|
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
|
||||||
EnableWitnessCollection: ctx.Bool(CollectWitnessFlag.Name),
|
|
||||||
}
|
}
|
||||||
if ctx.IsSet(VMTraceFlag.Name) {
|
if ctx.IsSet(VMTraceFlag.Name) {
|
||||||
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
||||||
|
|
|
||||||
|
|
@ -92,25 +92,21 @@ var (
|
||||||
LightServeFlag = &cli.IntFlag{
|
LightServeFlag = &cli.IntFlag{
|
||||||
Name: "light.serve",
|
Name: "light.serve",
|
||||||
Usage: "Maximum percentage of time allowed for serving LES requests (deprecated)",
|
Usage: "Maximum percentage of time allowed for serving LES requests (deprecated)",
|
||||||
Value: ethconfig.Defaults.LightServ,
|
|
||||||
Category: flags.DeprecatedCategory,
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
LightIngressFlag = &cli.IntFlag{
|
LightIngressFlag = &cli.IntFlag{
|
||||||
Name: "light.ingress",
|
Name: "light.ingress",
|
||||||
Usage: "Incoming bandwidth limit for serving light clients (deprecated)",
|
Usage: "Incoming bandwidth limit for serving light clients (deprecated)",
|
||||||
Value: ethconfig.Defaults.LightIngress,
|
|
||||||
Category: flags.DeprecatedCategory,
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
LightEgressFlag = &cli.IntFlag{
|
LightEgressFlag = &cli.IntFlag{
|
||||||
Name: "light.egress",
|
Name: "light.egress",
|
||||||
Usage: "Outgoing bandwidth limit for serving light clients (deprecated)",
|
Usage: "Outgoing bandwidth limit for serving light clients (deprecated)",
|
||||||
Value: ethconfig.Defaults.LightEgress,
|
|
||||||
Category: flags.DeprecatedCategory,
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
LightMaxPeersFlag = &cli.IntFlag{
|
LightMaxPeersFlag = &cli.IntFlag{
|
||||||
Name: "light.maxpeers",
|
Name: "light.maxpeers",
|
||||||
Usage: "Maximum number of light clients to serve, or light servers to attach to (deprecated)",
|
Usage: "Maximum number of light clients to serve, or light servers to attach to (deprecated)",
|
||||||
Value: ethconfig.Defaults.LightPeers,
|
|
||||||
Category: flags.DeprecatedCategory,
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
LightNoPruneFlag = &cli.BoolFlag{
|
LightNoPruneFlag = &cli.BoolFlag{
|
||||||
|
|
|
||||||
|
|
@ -87,11 +87,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make temp directory for era files.
|
// Make temp directory for era files.
|
||||||
dir, err := os.MkdirTemp("", "history-export-test")
|
dir := t.TempDir()
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error creating temp test directory: %v", err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(dir)
|
|
||||||
|
|
||||||
// Export history to temp directory.
|
// Export history to temp directory.
|
||||||
if err := ExportHistory(chain, dir, 0, count, step); err != nil {
|
if err := ExportHistory(chain, dir, 0, count, step); err != nil {
|
||||||
|
|
|
||||||
0
common/prque/prque.go
Executable file → Normal file
0
common/prque/prque.go
Executable file → Normal file
0
common/prque/sstack.go
Executable file → Normal file
0
common/prque/sstack.go
Executable file → Normal file
|
|
@ -388,8 +388,39 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
|
||||||
// Assign the final state root to header.
|
// Assign the final state root to header.
|
||||||
header.Root = state.IntermediateRoot(true)
|
header.Root = state.IntermediateRoot(true)
|
||||||
|
|
||||||
// Assemble and return the final block.
|
// Assemble the final block.
|
||||||
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
|
block := types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
|
||||||
|
|
||||||
|
// Create the block witness and attach to block.
|
||||||
|
// This step needs to happen as late as possible to catch all access events.
|
||||||
|
if chain.Config().IsVerkle(header.Number) {
|
||||||
|
keys := state.AccessEvents().Keys()
|
||||||
|
|
||||||
|
// Open the pre-tree to prove the pre-state against
|
||||||
|
parent := chain.GetHeaderByNumber(header.Number.Uint64() - 1)
|
||||||
|
if parent == nil {
|
||||||
|
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
|
||||||
|
}
|
||||||
|
|
||||||
|
preTrie, err := state.Database().OpenTrie(parent.Root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vktPreTrie, okpre := preTrie.(*trie.VerkleTrie)
|
||||||
|
vktPostTrie, okpost := state.GetTrie().(*trie.VerkleTrie)
|
||||||
|
if okpre && okpost {
|
||||||
|
if len(keys) > 0 {
|
||||||
|
verkleProof, stateDiff, err := vktPreTrie.Proof(vktPostTrie, keys, vktPreTrie.FlatdbNodeResolver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
|
||||||
|
}
|
||||||
|
block = block.WithWitness(&types.ExecutionWitness{StateDiff: stateDiff, VerkleProof: verkleProof})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return block, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seal generates a new sealing request for the given input block and pushes
|
// Seal generates a new sealing request for the given input block and pushes
|
||||||
|
|
|
||||||
|
|
@ -391,6 +391,10 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
|
||||||
return consensus.ErrUnexpectedWithdrawals
|
return consensus.ErrUnexpectedWithdrawals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if header.RequestsHash != nil {
|
||||||
|
return consensus.ErrUnexpectedRequests
|
||||||
|
}
|
||||||
|
|
||||||
// All basic checks passed, verify cascading fields
|
// All basic checks passed, verify cascading fields
|
||||||
return c.verifyCascadingFields(chain, header, parents)
|
return c.verifyCascadingFields(chain, header, parents)
|
||||||
}
|
}
|
||||||
|
|
@ -820,6 +824,9 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
|
||||||
if body.Withdrawals != nil || header.WithdrawalsHash != nil {
|
if body.Withdrawals != nil || header.WithdrawalsHash != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if body.Requests != nil || header.RequestsHash != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
stateSyncData []*types.StateSyncData
|
stateSyncData []*types.StateSyncData
|
||||||
|
|
@ -906,6 +913,9 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
|
||||||
if body.Withdrawals != nil || header.WithdrawalsHash != nil {
|
if body.Withdrawals != nil || header.WithdrawalsHash != nil {
|
||||||
return nil, consensus.ErrUnexpectedWithdrawals
|
return nil, consensus.ErrUnexpectedWithdrawals
|
||||||
}
|
}
|
||||||
|
if body.Requests != nil || header.RequestsHash != nil {
|
||||||
|
return nil, consensus.ErrUnexpectedRequests
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
stateSyncData []*types.StateSyncData
|
stateSyncData []*types.StateSyncData
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ func TestGenesisContractChange(t *testing.T) {
|
||||||
|
|
||||||
genesis := genspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
|
genesis := genspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
|
||||||
|
|
||||||
statedb, err := state.New(genesis.Root(), state.NewDatabase(db), nil)
|
statedb, err := state.New(genesis.Root(), state.NewDatabase(triedb.NewDatabase(db, triedb.HashDefaults), nil))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, b, vm.Config{}, nil, nil, nil)
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, b, vm.Config{}, nil, nil, nil)
|
||||||
|
|
@ -84,7 +84,7 @@ func TestGenesisContractChange(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, statedb.Database().TrieDB().Commit(root, true))
|
require.NoError(t, statedb.Database().TrieDB().Commit(root, true))
|
||||||
|
|
||||||
statedb, err := state.New(h.Root, state.NewDatabase(db), nil)
|
statedb, err := state.New(h.Root, state.NewDatabase(triedb.NewDatabase(db, triedb.HashDefaults), nil))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return root, statedb
|
return root, statedb
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ var (
|
||||||
const (
|
const (
|
||||||
heimdallAPIBodyLimit = 128 * 1024 * 1024 // 128 MB
|
heimdallAPIBodyLimit = 128 * 1024 * 1024 // 128 MB
|
||||||
stateFetchLimit = 50
|
stateFetchLimit = 50
|
||||||
apiHeimdallTimeout = 5 * time.Second
|
|
||||||
retryCall = 5 * time.Second
|
retryCall = 5 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -59,11 +58,11 @@ type Request struct {
|
||||||
start time.Time
|
start time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHeimdallClient(urlString string) *HeimdallClient {
|
func NewHeimdallClient(urlString string, timeout time.Duration) *HeimdallClient {
|
||||||
return &HeimdallClient{
|
return &HeimdallClient{
|
||||||
urlString: urlString,
|
urlString: urlString,
|
||||||
client: http.Client{
|
client: http.Client{
|
||||||
Timeout: apiHeimdallTimeout,
|
Timeout: timeout,
|
||||||
},
|
},
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +293,13 @@ func FetchWithRetry[T any](ctx context.Context, client http.Client, url *url.URL
|
||||||
log.Warn("an error while trying fetching from Heimdall", "path", url.Path, "attempt", attempt, "error", err)
|
log.Warn("an error while trying fetching from Heimdall", "path", url.Path, "attempt", attempt, "error", err)
|
||||||
|
|
||||||
// create a new ticker for retrying the request
|
// create a new ticker for retrying the request
|
||||||
ticker := time.NewTicker(retryCall)
|
var ticker *time.Ticker
|
||||||
|
if client.Timeout != 0 {
|
||||||
|
ticker = time.NewTicker(client.Timeout)
|
||||||
|
} else {
|
||||||
|
// only reach here when HeimdallClient is HeimdallGRPCClient or HeimdallAppClient
|
||||||
|
ticker = time.NewTicker(retryCall)
|
||||||
|
}
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
const logEach = 5
|
const logEach = 5
|
||||||
|
|
@ -469,7 +474,7 @@ func internalFetch(ctx context.Context, client http.Client, u *url.URL) ([]byte,
|
||||||
}
|
}
|
||||||
|
|
||||||
func internalFetchWithTimeout(ctx context.Context, client http.Client, url *url.URL) ([]byte, error) {
|
func internalFetchWithTimeout(ctx context.Context, client http.Client, url *url.URL) ([]byte, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, apiHeimdallTimeout)
|
ctx, cancel := context.WithTimeout(ctx, client.Timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// request data once
|
// request data once
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ func TestFetchCheckpointFromMockHeimdall(t *testing.T) {
|
||||||
require.NoError(t, err, "expect no error in starting mock heimdall server")
|
require.NoError(t, err, "expect no error in starting mock heimdall server")
|
||||||
|
|
||||||
// Create a new heimdall client and use same port for connection
|
// Create a new heimdall client and use same port for connection
|
||||||
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port))
|
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port), 5*time.Second)
|
||||||
_, err = client.FetchCheckpoint(context.Background(), -1)
|
_, err = client.FetchCheckpoint(context.Background(), -1)
|
||||||
require.NoError(t, err, "expect no error in fetching checkpoint")
|
require.NoError(t, err, "expect no error in fetching checkpoint")
|
||||||
|
|
||||||
|
|
@ -194,7 +194,7 @@ func TestFetchMilestoneFromMockHeimdall(t *testing.T) {
|
||||||
require.NoError(t, err, "expect no error in starting mock heimdall server")
|
require.NoError(t, err, "expect no error in starting mock heimdall server")
|
||||||
|
|
||||||
// Create a new heimdall client and use same port for connection
|
// Create a new heimdall client and use same port for connection
|
||||||
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port))
|
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port), 5*time.Second)
|
||||||
_, err = client.FetchMilestone(context.Background())
|
_, err = client.FetchMilestone(context.Background())
|
||||||
require.NoError(t, err, "expect no error in fetching milestone")
|
require.NoError(t, err, "expect no error in fetching milestone")
|
||||||
|
|
||||||
|
|
@ -250,7 +250,7 @@ func TestFetchShutdown(t *testing.T) {
|
||||||
require.NoError(t, err, "expect no error in starting mock heimdall server")
|
require.NoError(t, err, "expect no error in starting mock heimdall server")
|
||||||
|
|
||||||
// Create a new heimdall client and use same port for connection
|
// Create a new heimdall client and use same port for connection
|
||||||
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port))
|
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port), 5*time.Second)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
|
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// This test case is a repro of an annoying bug that took us forever to catch.
|
// This test case is a repro of an annoying bug that took us forever to catch.
|
||||||
// In Clique PoA networks (Görli, etc), consecutive blocks might have
|
// In Clique PoA networks, consecutive blocks might have the same state root (no
|
||||||
// the same state root (no block subsidy, empty block). If a node crashes, the
|
// block subsidy, empty block). If a node crashes, the chain ends up losing the
|
||||||
// chain ends up losing the recent state and needs to regenerate it from blocks
|
// recent state and needs to regenerate it from blocks already in the database.
|
||||||
// already in the database. The bug was that processing the block *prior* to an
|
// The bug was that processing the block *prior* to an empty one **also
|
||||||
// empty one **also completes** the empty one, ending up in a known-block error.
|
// completes** the empty one, ending up in a known-block error.
|
||||||
func TestReimportMirroredState(t *testing.T) {
|
func TestReimportMirroredState(t *testing.T) {
|
||||||
// Initialize a Clique chain with a single signer
|
// Initialize a Clique chain with a single signer
|
||||||
var (
|
var (
|
||||||
|
|
@ -90,7 +90,6 @@ func TestReimportMirroredState(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Insert the first two blocks and make sure the chain is valid
|
// Insert the first two blocks and make sure the chain is valid
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
|
|
||||||
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil, nil)
|
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,7 @@ var (
|
||||||
|
|
||||||
// ErrUnexpectedWithdrawals is returned if a pre-Shanghai block has withdrawals.
|
// ErrUnexpectedWithdrawals is returned if a pre-Shanghai block has withdrawals.
|
||||||
ErrUnexpectedWithdrawals = errors.New("unexpected withdrawals")
|
ErrUnexpectedWithdrawals = errors.New("unexpected withdrawals")
|
||||||
|
|
||||||
|
// ErrUnexpectedRequests is returned if a pre-Shanghai block has requests.
|
||||||
|
ErrUnexpectedRequests = errors.New("unexpected requests")
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ func TestCalcBaseFee(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestCalcBaseFee assumes all blocks are 1559-blocks post Delhi Hard Fork
|
// TestCalcBaseFeeDelhi assumes all blocks are 1559-blocks post Delhi Hard Fork
|
||||||
func TestCalcBaseFeeDelhi(t *testing.T) {
|
func TestCalcBaseFeeDelhi(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,6 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error creating chain: %v", err)
|
b.Fatalf("error creating chain: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/stateless"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
|
@ -127,15 +125,17 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
|
|
||||||
// ValidateState validates the various changes that happen after a state transition,
|
// ValidateState validates the various changes that happen after a state transition,
|
||||||
// such as amount of used gas, the receipt roots and the state root itself.
|
// such as amount of used gas, the receipt roots and the state root itself.
|
||||||
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, stateless bool) error {
|
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, res *ProcessResult, stateless bool) error {
|
||||||
|
if res == nil {
|
||||||
|
return fmt.Errorf("nil ProcessResult value")
|
||||||
|
}
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
|
if block.GasUsed() != res.GasUsed {
|
||||||
if block.GasUsed() != usedGas {
|
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), res.GasUsed)
|
||||||
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
|
|
||||||
}
|
}
|
||||||
// Validate the received block's bloom with the one derived from the generated receipts.
|
// Validate the received block's bloom with the one derived from the generated receipts.
|
||||||
// For valid blocks this should always validate to true.
|
// For valid blocks this should always validate to true.
|
||||||
rbloom := types.CreateBloom(receipts)
|
rbloom := types.CreateBloom(res.Receipts)
|
||||||
if rbloom != header.Bloom {
|
if rbloom != header.Bloom {
|
||||||
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
||||||
}
|
}
|
||||||
|
|
@ -145,10 +145,17 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// The receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
|
// The receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
|
||||||
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
|
receiptSha := types.DeriveSha(res.Receipts, trie.NewStackTrie(nil))
|
||||||
if receiptSha != header.ReceiptHash {
|
if receiptSha != header.ReceiptHash {
|
||||||
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
|
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
|
||||||
}
|
}
|
||||||
|
// Validate the parsed requests match the expected header value.
|
||||||
|
if header.RequestsHash != nil {
|
||||||
|
depositSha := types.DeriveSha(res.Requests, trie.NewStackTrie(nil))
|
||||||
|
if depositSha != *header.RequestsHash {
|
||||||
|
return fmt.Errorf("invalid deposit root hash (remote: %x local: %x)", *header.RequestsHash, depositSha)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Validate the state root against the received state root and throw
|
// Validate the state root against the received state root and throw
|
||||||
// an error if they don't match.
|
// an error if they don't match.
|
||||||
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
||||||
|
|
@ -158,28 +165,6 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateWitness cross validates a block execution with stateless remote clients.
|
|
||||||
//
|
|
||||||
// Normally we'd distribute the block witness to remote cross validators, wait
|
|
||||||
// for them to respond and then merge the results. For now, however, it's only
|
|
||||||
// Geth, so do an internal stateless run.
|
|
||||||
func (v *BlockValidator) ValidateWitness(witness *stateless.Witness, receiptRoot common.Hash, stateRoot common.Hash) error {
|
|
||||||
// Run the cross client stateless execution
|
|
||||||
// TODO(karalabe): Self-stateless for now, swap with other clients
|
|
||||||
crossReceiptRoot, crossStateRoot, err := ExecuteStateless(v.config, witness)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("stateless execution failed: %v", err)
|
|
||||||
}
|
|
||||||
// Stateless cross execution suceeeded, validate the withheld computed fields
|
|
||||||
if crossReceiptRoot != receiptRoot {
|
|
||||||
return fmt.Errorf("cross validator receipt root mismatch (cross: %x local: %x)", crossReceiptRoot, receiptRoot)
|
|
||||||
}
|
|
||||||
if crossStateRoot != stateRoot {
|
|
||||||
return fmt.Errorf("cross validator state root mismatch (cross: %x local: %x)", crossStateRoot, stateRoot)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
||||||
// to keep the baseline gas close to the provided target, and increase it towards
|
// to keep the baseline gas close to the provided target, and increase it towards
|
||||||
// the target if the baseline gas is lower.
|
// the target if the baseline gas is lower.
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
||||||
t.Fatalf("post-block %d: unexpected result returned: %v", i, result)
|
t.Fatalf("post-block %d: unexpected result returned: %v", i, result)
|
||||||
case <-time.After(25 * time.Millisecond):
|
case <-time.After(25 * time.Millisecond):
|
||||||
}
|
}
|
||||||
chain.InsertBlockWithoutSetHead(postBlocks[i])
|
chain.InsertBlockWithoutSetHead(postBlocks[i], false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the blocks with pre-merge blocks and post-merge blocks
|
// Verify the blocks with pre-merge blocks and post-merge blocks
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
|
"github.com/ethereum/go-ethereum/core/stateless"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
|
@ -78,17 +79,21 @@ var (
|
||||||
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
|
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
|
||||||
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)
|
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)
|
||||||
|
|
||||||
|
accountReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/account/single/reads", nil) //nolint:golint,unused
|
||||||
|
storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil) //nolint:golint,unused
|
||||||
|
|
||||||
|
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)
|
||||||
|
triedbCommitTimer = metrics.NewRegisteredResettingTimer("chain/triedb/commits", nil)
|
||||||
snapshotAccountReadTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/account/reads", nil)
|
snapshotAccountReadTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/account/reads", nil)
|
||||||
snapshotStorageReadTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/storage/reads", nil)
|
snapshotStorageReadTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/storage/reads", nil)
|
||||||
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)
|
|
||||||
|
|
||||||
borConsensusTime = metrics.NewRegisteredTimer("chain/bor/consensus", nil)
|
borConsensusTime = metrics.NewRegisteredTimer("chain/bor/consensus", nil)
|
||||||
|
|
||||||
blockImportTimer = metrics.NewRegisteredMeter("chain/imports", nil)
|
blockImportTimer = metrics.NewRegisteredMeter("chain/imports", nil)
|
||||||
triedbCommitTimer = metrics.NewRegisteredTimer("chain/triedb/commits", nil)
|
|
||||||
|
|
||||||
blockInsertTimer = metrics.NewRegisteredTimer("chain/inserts", nil)
|
blockInsertTimer = metrics.NewRegisteredTimer("chain/inserts", nil)
|
||||||
blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil)
|
blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil)
|
||||||
|
blockCrossValidationTimer = metrics.NewRegisteredResettingTimer("chain/crossvalidation", nil) //nolint:golint,unused
|
||||||
blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil)
|
blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil)
|
||||||
blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil)
|
blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil)
|
||||||
blockExecutionParallelCounter = metrics.NewRegisteredCounter("chain/execution/parallel", nil)
|
blockExecutionParallelCounter = metrics.NewRegisteredCounter("chain/execution/parallel", nil)
|
||||||
|
|
@ -237,7 +242,7 @@ type BlockChain struct {
|
||||||
lastWrite uint64 // Last block when the state was flushed
|
lastWrite uint64 // Last block when the state was flushed
|
||||||
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
|
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
|
||||||
triedb *triedb.Database // The database handler for maintaining trie nodes.
|
triedb *triedb.Database // The database handler for maintaining trie nodes.
|
||||||
stateCache state.Database // State database to reuse between imports (contains state cache)
|
statedb *state.CachingDB // State database to reuse between imports (contains state cache)
|
||||||
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
|
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
|
||||||
|
|
||||||
hc *HeaderChain
|
hc *HeaderChain
|
||||||
|
|
@ -357,7 +362,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
|
|
||||||
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
||||||
bc.forker = NewForkChoice(bc, shouldPreserve, checker)
|
bc.forker = NewForkChoice(bc, shouldPreserve, checker)
|
||||||
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
bc.statedb = state.NewDatabase(bc.triedb, nil)
|
||||||
bc.validator = NewBlockValidator(chainConfig, bc)
|
bc.validator = NewBlockValidator(chainConfig, bc)
|
||||||
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
||||||
bc.processor = NewStateProcessor(chainConfig, bc, bc.hc)
|
bc.processor = NewStateProcessor(chainConfig, bc, bc.hc)
|
||||||
|
|
@ -525,11 +530,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
AsyncBuild: !bc.cacheConfig.SnapshotWait,
|
AsyncBuild: !bc.cacheConfig.SnapshotWait,
|
||||||
}
|
}
|
||||||
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
|
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
|
||||||
}
|
|
||||||
|
|
||||||
// Start future block processor.
|
// Re-initialize the state database with snapshot
|
||||||
// bc.wg.Add(1)
|
bc.statedb = state.NewDatabase(bc.triedb, bc.snaps)
|
||||||
// go bc.updateFutureBlocks()
|
}
|
||||||
|
|
||||||
// Rewind the chain in case of an incompatible config upgrade.
|
// Rewind the chain in case of an incompatible config upgrade.
|
||||||
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
|
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
|
||||||
|
|
@ -616,7 +620,7 @@ func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (_
|
||||||
processorCount := 0
|
processorCount := 0
|
||||||
|
|
||||||
if bc.parallelProcessor != nil {
|
if bc.parallelProcessor != nil {
|
||||||
parallelStatedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
|
parallelStatedb, err := state.New(parent.Root, bc.statedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, nil, 0, err
|
return nil, nil, 0, nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -627,19 +631,22 @@ func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (_
|
||||||
go func() {
|
go func() {
|
||||||
parallelStatedb.StartPrefetcher("chain", nil)
|
parallelStatedb.StartPrefetcher("chain", nil)
|
||||||
pstart := time.Now()
|
pstart := time.Now()
|
||||||
receipts, logs, usedGas, err := bc.parallelProcessor.Process(block, parallelStatedb, bc.vmConfig, ctx)
|
res, err := bc.parallelProcessor.Process(block, parallelStatedb, bc.vmConfig, ctx)
|
||||||
blockExecutionParallelTimer.UpdateSince(pstart)
|
blockExecutionParallelTimer.UpdateSince(pstart)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
vstart := time.Now()
|
vstart := time.Now()
|
||||||
err = bc.validator.ValidateState(block, parallelStatedb, receipts, usedGas, false)
|
err = bc.validator.ValidateState(block, parallelStatedb, res, false)
|
||||||
vtime = time.Since(vstart)
|
vtime = time.Since(vstart)
|
||||||
}
|
}
|
||||||
resultChan <- Result{receipts, logs, usedGas, err, parallelStatedb, blockExecutionParallelCounter, true}
|
if res == nil {
|
||||||
|
res = &ProcessResult{}
|
||||||
|
}
|
||||||
|
resultChan <- Result{res.Receipts, res.Logs, res.GasUsed, err, parallelStatedb, blockExecutionParallelCounter, true}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
if bc.processor != nil && !bc.enforceParallelProcessor {
|
if bc.processor != nil && !bc.enforceParallelProcessor {
|
||||||
statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
|
statedb, err := state.New(parent.Root, bc.statedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, nil, 0, err
|
return nil, nil, 0, nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -650,14 +657,17 @@ func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (_
|
||||||
go func() {
|
go func() {
|
||||||
statedb.StartPrefetcher("chain", nil)
|
statedb.StartPrefetcher("chain", nil)
|
||||||
pstart := time.Now()
|
pstart := time.Now()
|
||||||
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig, ctx)
|
res, err := bc.processor.Process(block, statedb, bc.vmConfig, ctx)
|
||||||
blockExecutionSerialTimer.UpdateSince(pstart)
|
blockExecutionSerialTimer.UpdateSince(pstart)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
vstart := time.Now()
|
vstart := time.Now()
|
||||||
err = bc.validator.ValidateState(block, statedb, receipts, usedGas, false)
|
err = bc.validator.ValidateState(block, statedb, res, false)
|
||||||
vtime = time.Since(vstart)
|
vtime = time.Since(vstart)
|
||||||
}
|
}
|
||||||
resultChan <- Result{receipts, logs, usedGas, err, statedb, blockExecutionSerialCounter, false}
|
if res == nil {
|
||||||
|
res = &ProcessResult{}
|
||||||
|
}
|
||||||
|
resultChan <- Result{res.Receipts, res.Logs, res.GasUsed, err, statedb, blockExecutionSerialCounter, false}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2063,7 +2073,9 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||||
return 0, errChainStopped
|
return 0, errChainStopped
|
||||||
}
|
}
|
||||||
defer bc.chainmu.Unlock()
|
defer bc.chainmu.Unlock()
|
||||||
return bc.insertChain(chain, true)
|
|
||||||
|
_, n, err := bc.insertChain(chain, true, false) // No witness collection for mass inserts (would get super large)
|
||||||
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertChain is the internal implementation of InsertChain, which assumes that
|
// insertChain is the internal implementation of InsertChain, which assumes that
|
||||||
|
|
@ -2074,10 +2086,10 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||||
// racey behaviour. If a sidechain import is in progress, and the historic state
|
// racey behaviour. If a sidechain import is in progress, and the historic state
|
||||||
// is imported, but then new canon-head is added before the actual sidechain
|
// is imported, but then new canon-head is added before the actual sidechain
|
||||||
// completes, then the historic state could be pruned again
|
// completes, then the historic state could be pruned again
|
||||||
func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) {
|
func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness bool) (*stateless.Witness, int, error) {
|
||||||
// If the chain is terminating, don't even bother starting up.
|
// If the chain is terminating, don't even bother starting up.
|
||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
return 0, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
||||||
|
|
@ -2113,13 +2125,13 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
// Check the validity of incoming chain
|
// Check the validity of incoming chain
|
||||||
isValid, err1 := bc.forker.ValidateReorg(bc.CurrentBlock(), headers)
|
isValid, err1 := bc.forker.ValidateReorg(bc.CurrentBlock(), headers)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return it.index, err1
|
return nil, it.index, err1
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isValid {
|
if !isValid {
|
||||||
// The chain to be imported is invalid as the blocks doesn't match with
|
// The chain to be imported is invalid as the blocks doesn't match with
|
||||||
// the whitelisted block number.
|
// the whitelisted block number.
|
||||||
return it.index, whitelist.ErrMismatch
|
return nil, it.index, whitelist.ErrMismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left-trim all the known blocks that don't need to build snapshot
|
// Left-trim all the known blocks that don't need to build snapshot
|
||||||
|
|
@ -2137,7 +2149,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
for block != nil && bc.skipBlock(err, it) {
|
for block != nil && bc.skipBlock(err, it) {
|
||||||
reorg, err = bc.forker.ReorgNeeded(current, block.Header())
|
reorg, err = bc.forker.ReorgNeeded(current, block.Header())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if reorg {
|
if reorg {
|
||||||
|
|
@ -2169,7 +2181,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
log.Debug("Writing previously known block", "number", block.Number(), "hash", block.Hash())
|
log.Debug("Writing previously known block", "number", block.Number(), "hash", block.Hash())
|
||||||
|
|
||||||
if err := bc.writeKnownBlock(block); err != nil {
|
if err := bc.writeKnownBlock(block); err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lastCanon = block
|
lastCanon = block
|
||||||
|
|
@ -2185,13 +2197,12 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
if setHead {
|
if setHead {
|
||||||
// First block is pruned, insert as sidechain and reorg only if TD grows enough
|
// First block is pruned, insert as sidechain and reorg only if TD grows enough
|
||||||
log.Debug("Pruned ancestor, inserting as sidechain", "number", block.Number(), "hash", block.Hash())
|
log.Debug("Pruned ancestor, inserting as sidechain", "number", block.Number(), "hash", block.Hash())
|
||||||
return bc.insertSideChain(block, it)
|
return bc.insertSideChain(block, it, makeWitness)
|
||||||
} else {
|
} else {
|
||||||
// We're post-merge and the parent is pruned, try to recover the parent state
|
// We're post-merge and the parent is pruned, try to recover the parent state
|
||||||
log.Debug("Pruned ancestor", "number", block.Number(), "hash", block.Hash())
|
log.Debug("Pruned ancestor", "number", block.Number(), "hash", block.Hash())
|
||||||
_, err := bc.recoverAncestors(block)
|
_, err := bc.recoverAncestors(block, makeWitness)
|
||||||
|
return nil, it.index, err
|
||||||
return it.index, err
|
|
||||||
}
|
}
|
||||||
// First block is future, shove it (and all children) to the future queue (unknown ancestor)
|
// First block is future, shove it (and all children) to the future queue (unknown ancestor)
|
||||||
case errors.Is(err, consensus.ErrFutureBlock) || (errors.Is(err, consensus.ErrUnknownAncestor) && bc.futureBlocks.Contains(it.first().ParentHash())):
|
case errors.Is(err, consensus.ErrFutureBlock) || (errors.Is(err, consensus.ErrUnknownAncestor) && bc.futureBlocks.Contains(it.first().ParentHash())):
|
||||||
|
|
@ -2199,7 +2210,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
log.Debug("Future block, postponing import", "number", block.Number(), "hash", block.Hash())
|
log.Debug("Future block, postponing import", "number", block.Number(), "hash", block.Hash())
|
||||||
|
|
||||||
if err := bc.addFutureBlock(block); err != nil {
|
if err := bc.addFutureBlock(block); err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err = it.next()
|
block, err = it.next()
|
||||||
|
|
@ -2209,7 +2220,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
stats.ignored += it.remaining()
|
stats.ignored += it.remaining()
|
||||||
|
|
||||||
// If there are any still remaining, mark as ignored
|
// If there are any still remaining, mark as ignored
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
|
|
||||||
// Some other error(except ErrKnownBlock) occurred, abort.
|
// Some other error(except ErrKnownBlock) occurred, abort.
|
||||||
// ErrKnownBlock is allowed here since some known blocks
|
// ErrKnownBlock is allowed here since some known blocks
|
||||||
|
|
@ -2218,8 +2229,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
stats.ignored += len(it.chain)
|
stats.ignored += len(it.chain)
|
||||||
|
|
||||||
bc.reportBlock(block, nil, err)
|
bc.reportBlock(block, nil, err)
|
||||||
|
return nil, it.index, err
|
||||||
return it.index, err
|
|
||||||
}
|
}
|
||||||
// No validation errors for the first block (or chain prefix skipped)
|
// No validation errors for the first block (or chain prefix skipped)
|
||||||
var activeState *state.StateDB
|
var activeState *state.StateDB
|
||||||
|
|
@ -2233,6 +2243,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Track the singleton witness from this chain insertion (if any)
|
||||||
|
var witness *stateless.Witness
|
||||||
|
|
||||||
// accumulator for canonical blocks
|
// accumulator for canonical blocks
|
||||||
var canonAccum []*types.Block
|
var canonAccum []*types.Block
|
||||||
|
|
||||||
|
|
@ -2261,7 +2274,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
// If the header is a banned one, straight out abort
|
// If the header is a banned one, straight out abort
|
||||||
if BadHashes[block.Hash()] {
|
if BadHashes[block.Hash()] {
|
||||||
bc.reportBlock(block, nil, ErrBannedHash)
|
bc.reportBlock(block, nil, ErrBannedHash)
|
||||||
return it.index, ErrBannedHash
|
return nil, it.index, ErrBannedHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the block is known (in the middle of the chain), it's a special case for
|
// If the block is known (in the middle of the chain), it's a special case for
|
||||||
|
|
@ -2296,7 +2309,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bc.writeKnownBlock(block); err != nil {
|
if err := bc.writeKnownBlock(block); err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.processed++
|
stats.processed++
|
||||||
|
|
@ -2308,14 +2321,12 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
Safe: bc.CurrentSafeBlock(),
|
Safe: bc.CurrentSafeBlock(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can assume that logs are empty here, since the only way for consecutive
|
// We can assume that logs are empty here, since the only way for consecutive
|
||||||
// Clique blocks to have the same state is if there are no transactions.
|
// Clique blocks to have the same state is if there are no transactions.
|
||||||
lastCanon = block
|
lastCanon = block
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the parent block and it's state to execute on top
|
// Retrieve the parent block and it's state to execute on top
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
|
|
@ -2330,7 +2341,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
|
|
||||||
if !bc.cacheConfig.TrieCleanNoPrefetch {
|
if !bc.cacheConfig.TrieCleanNoPrefetch {
|
||||||
if followup, err := it.peek(); followup != nil && err == nil {
|
if followup, err := it.peek(); followup != nil && err == nil {
|
||||||
throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps)
|
throwaway, _ := state.New(parent.Root, bc.statedb)
|
||||||
|
|
||||||
go func(start time.Time, followup *types.Block, throwaway *state.StateDB) {
|
go func(start time.Time, followup *types.Block, throwaway *state.StateDB) {
|
||||||
// Disable tracing for prefetcher executions.
|
// Disable tracing for prefetcher executions.
|
||||||
|
|
@ -2353,10 +2364,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
activeState = statedb
|
activeState = statedb
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bc.reportBlock(block, receipts, err)
|
bc.reportBlock(block, &ProcessResult{Receipts: receipts}, err)
|
||||||
followupInterrupt.Store(true)
|
followupInterrupt.Store(true)
|
||||||
|
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOR state sync feed related changes
|
// BOR state sync feed related changes
|
||||||
|
|
@ -2398,10 +2409,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
// so that it's considered as a `past` chain and the validation doesn't get bypassed.
|
// so that it's considered as a `past` chain and the validation doesn't get bypassed.
|
||||||
isValid, err = bc.forker.ValidateReorg(block.Header(), []*types.Header{block.Header()})
|
isValid, err = bc.forker.ValidateReorg(block.Header(), []*types.Header{block.Header()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isValid {
|
if !isValid {
|
||||||
return it.index, whitelist.ErrMismatch
|
return nil, it.index, whitelist.ErrMismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
if !setHead {
|
if !setHead {
|
||||||
|
|
@ -2414,7 +2426,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
followupInterrupt.Store(true)
|
followupInterrupt.Store(true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the metrics touched during block commit
|
// Update the metrics touched during block commit
|
||||||
|
|
@ -2441,7 +2453,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
// After merge we expect few side chains. Simply count
|
// After merge we expect few side chains. Simply count
|
||||||
// all blocks the CL gives us for GC processing time
|
// all blocks the CL gives us for GC processing time
|
||||||
bc.gcproc += proctime
|
bc.gcproc += proctime
|
||||||
return it.index, nil // Direct block insertion of a single block
|
return witness, it.index, nil // Direct block insertion of a single block
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOR
|
// BOR
|
||||||
|
|
@ -2487,14 +2499,14 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
// Any blocks remaining here? The only ones we care about are the future ones
|
// Any blocks remaining here? The only ones we care about are the future ones
|
||||||
if block != nil && errors.Is(err, consensus.ErrFutureBlock) {
|
if block != nil && errors.Is(err, consensus.ErrFutureBlock) {
|
||||||
if err := bc.addFutureBlock(block); err != nil {
|
if err := bc.addFutureBlock(block); err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err = it.next()
|
block, err = it.next()
|
||||||
|
|
||||||
for ; block != nil && errors.Is(err, consensus.ErrUnknownAncestor); block, err = it.next() {
|
for ; block != nil && errors.Is(err, consensus.ErrUnknownAncestor); block, err = it.next() {
|
||||||
if err := bc.addFutureBlock(block); err != nil {
|
if err := bc.addFutureBlock(block); err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.queued++
|
stats.queued++
|
||||||
|
|
@ -2502,7 +2514,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.ignored += it.remaining()
|
stats.ignored += it.remaining()
|
||||||
return it.index, err
|
return witness, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// blockProcessingResult is a summary of block processing
|
// blockProcessingResult is a summary of block processing
|
||||||
|
|
@ -2535,42 +2547,68 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
|
|
||||||
// Process block using the parent state as reference point
|
// Process block using the parent state as reference point
|
||||||
pstart := time.Now()
|
pstart := time.Now()
|
||||||
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig, context.Background())
|
res, err := bc.processor.Process(block, statedb, bc.vmConfig, context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bc.reportBlock(block, receipts, err)
|
bc.reportBlock(block, res, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ptime := time.Since(pstart)
|
ptime := time.Since(pstart)
|
||||||
|
|
||||||
vstart := time.Now()
|
vstart := time.Now()
|
||||||
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas, false); err != nil {
|
if err := bc.validator.ValidateState(block, statedb, res, false); err != nil {
|
||||||
bc.reportBlock(block, receipts, err)
|
bc.reportBlock(block, res, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
vtime := time.Since(vstart)
|
vtime := time.Since(vstart)
|
||||||
|
|
||||||
if witness := statedb.Witness(); witness != nil {
|
// If witnesses was generated and stateless self-validation requested, do
|
||||||
if err = bc.validator.ValidateWitness(witness, block.ReceiptHash(), block.Root()); err != nil {
|
// that now. Self validation should *never* run in production, it's more of
|
||||||
bc.reportBlock(block, receipts, err)
|
// a tight integration to enable running *all* consensus tests through the
|
||||||
return nil, fmt.Errorf("cross verification failed: %v", err)
|
// witness builder/runner, which would otherwise be impossible due to the
|
||||||
|
// various invalid chain states/behaviors being contained in those tests.
|
||||||
|
xvstart := time.Now()
|
||||||
|
if witness := statedb.Witness(); witness != nil && bc.vmConfig.StatelessSelfValidation {
|
||||||
|
log.Warn("Running stateless self-validation", "block", block.Number(), "hash", block.Hash())
|
||||||
|
|
||||||
|
// Remove critical computed fields from the block to force true recalculation
|
||||||
|
context := block.Header()
|
||||||
|
context.Root = common.Hash{}
|
||||||
|
context.ReceiptHash = common.Hash{}
|
||||||
|
|
||||||
|
task := types.NewBlockWithHeader(context).WithBody(*block.Body())
|
||||||
|
|
||||||
|
// Run the stateless self-cross-validation
|
||||||
|
crossStateRoot, crossReceiptRoot, err := ExecuteStateless(bc.chainConfig, task, witness)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("stateless self-validation failed: %v", err)
|
||||||
|
}
|
||||||
|
if crossStateRoot != block.Root() {
|
||||||
|
return nil, fmt.Errorf("stateless self-validation root mismatch (cross: %x local: %x)", crossStateRoot, block.Root())
|
||||||
|
}
|
||||||
|
if crossReceiptRoot != block.ReceiptHash() {
|
||||||
|
return nil, fmt.Errorf("stateless self-validation receipt root mismatch (cross: %x local: %x)", crossReceiptRoot, block.ReceiptHash())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
proctime := time.Since(start) // processing + validation
|
xvtime := time.Since(xvstart)
|
||||||
|
proctime := time.Since(start) // processing + validation + cross validation
|
||||||
|
|
||||||
// Update the metrics touched during block processing and validation
|
// Update the metrics touched during block processing and validation
|
||||||
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
||||||
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing)
|
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing)
|
||||||
snapshotAccountReadTimer.Update(statedb.SnapshotAccountReads) // Account reads are complete(in processing)
|
if statedb.AccountLoaded != 0 {
|
||||||
snapshotStorageReadTimer.Update(statedb.SnapshotStorageReads) // Storage reads are complete(in processing)
|
accountReadSingleTimer.Update(statedb.AccountReads / time.Duration(statedb.AccountLoaded))
|
||||||
|
}
|
||||||
|
if statedb.StorageLoaded != 0 {
|
||||||
|
storageReadSingleTimer.Update(statedb.StorageReads / time.Duration(statedb.StorageLoaded))
|
||||||
|
}
|
||||||
accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation)
|
accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation)
|
||||||
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation)
|
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation)
|
||||||
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation)
|
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation)
|
||||||
triehash := statedb.AccountHashes // The time spent on tries hashing
|
triehash := statedb.AccountHashes // The time spent on tries hashing
|
||||||
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update
|
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update
|
||||||
trieRead := statedb.SnapshotAccountReads + statedb.AccountReads // The time spent on account read
|
blockExecutionTimer.Update(ptime - (statedb.AccountReads + statedb.StorageReads)) // The time spent on EVM processing
|
||||||
trieRead += statedb.SnapshotStorageReads + statedb.StorageReads // The time spent on storage read
|
|
||||||
blockExecutionTimer.Update(ptime - trieRead) // The time spent on EVM processing
|
|
||||||
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation
|
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation
|
||||||
|
blockCrossValidationTimer.Update(xvtime) // The time spent on stateless cross validation
|
||||||
|
|
||||||
// Write the block to the chain and get the status.
|
// Write the block to the chain and get the status.
|
||||||
var (
|
var (
|
||||||
|
|
@ -2579,9 +2617,9 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
)
|
)
|
||||||
if !setHead {
|
if !setHead {
|
||||||
// Don't set the head, only insert the block
|
// Don't set the head, only insert the block
|
||||||
_, err = bc.writeBlockWithState(block, receipts, logs, statedb)
|
_, err = bc.writeBlockWithState(block, res.Receipts, res.Logs, statedb)
|
||||||
} else {
|
} else {
|
||||||
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false)
|
status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, false)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -2595,7 +2633,7 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
|
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
|
||||||
blockInsertTimer.UpdateSince(start)
|
blockInsertTimer.UpdateSince(start)
|
||||||
|
|
||||||
return &blockProcessingResult{usedGas: usedGas, procTime: proctime, status: status}, nil
|
return &blockProcessingResult{usedGas: res.GasUsed, procTime: proctime, status: status}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertSideChain is called when an import batch hits upon a pruned ancestor
|
// insertSideChain is called when an import batch hits upon a pruned ancestor
|
||||||
|
|
@ -2605,7 +2643,7 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
// The method writes all (header-and-body-valid) blocks to disk, then tries to
|
// The method writes all (header-and-body-valid) blocks to disk, then tries to
|
||||||
// switch over to the new chain if the TD exceeded the current chain.
|
// switch over to the new chain if the TD exceeded the current chain.
|
||||||
// insertSideChain is only used pre-merge.
|
// insertSideChain is only used pre-merge.
|
||||||
func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (int, error) {
|
func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, makeWitness bool) (*stateless.Witness, int, error) {
|
||||||
var (
|
var (
|
||||||
externTd *big.Int
|
externTd *big.Int
|
||||||
lastBlock = block
|
lastBlock = block
|
||||||
|
|
@ -2644,7 +2682,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
// If someone legitimately side-mines blocks, they would still be imported as usual. However,
|
// If someone legitimately side-mines blocks, they would still be imported as usual. However,
|
||||||
// we cannot risk writing unverified blocks to disk when they obviously target the pruning
|
// we cannot risk writing unverified blocks to disk when they obviously target the pruning
|
||||||
// mechanism.
|
// mechanism.
|
||||||
return it.index, errors.New("sidechain ghost-state attack")
|
return nil, it.index, errors.New("sidechain ghost-state attack")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2658,7 +2696,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if err := bc.writeBlockWithoutState(block, externTd); err != nil {
|
if err := bc.writeBlockWithoutState(block, externTd); err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("Injected sidechain block", "number", block.Number(), "hash", block.Hash(),
|
log.Debug("Injected sidechain block", "number", block.Number(), "hash", block.Hash(),
|
||||||
|
|
@ -2677,19 +2715,19 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
// blocks to regenerate the required state
|
// blocks to regenerate the required state
|
||||||
reorg, err := bc.forker.ReorgNeeded(current, lastBlock.Header())
|
reorg, err := bc.forker.ReorgNeeded(current, lastBlock.Header())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid, err := bc.forker.ValidateReorg(current, headers)
|
isValid, err := bc.forker.ValidateReorg(current, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reorg || !isValid {
|
if !reorg || !isValid {
|
||||||
localTd := bc.GetTd(current.Hash(), current.Number.Uint64())
|
localTd := bc.GetTd(current.Hash(), current.Number.Uint64())
|
||||||
log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd)
|
log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd)
|
||||||
|
|
||||||
return it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
||||||
var (
|
var (
|
||||||
|
|
@ -2701,7 +2739,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
for parent != nil && !bc.HasState(parent.Root) {
|
for parent != nil && !bc.HasState(parent.Root) {
|
||||||
if bc.stateRecoverable(parent.Root) {
|
if bc.stateRecoverable(parent.Root) {
|
||||||
if err := bc.triedb.Recover(parent.Root); err != nil {
|
if err := bc.triedb.Recover(parent.Root); err != nil {
|
||||||
return 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -2712,7 +2750,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
}
|
}
|
||||||
|
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
return it.index, errors.New("missing parent")
|
return nil, it.index, errors.New("missing parent")
|
||||||
}
|
}
|
||||||
// Import all the pruned blocks to make the state available
|
// Import all the pruned blocks to make the state available
|
||||||
var (
|
var (
|
||||||
|
|
@ -2732,8 +2770,8 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
// memory here.
|
// memory here.
|
||||||
if len(blocks) >= 2048 || memory > 64*1024*1024 {
|
if len(blocks) >= 2048 || memory > 64*1024*1024 {
|
||||||
log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64())
|
log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64())
|
||||||
if _, err := bc.insertChain(blocks, true); err != nil {
|
if _, _, err := bc.insertChain(blocks, true, false); err != nil {
|
||||||
return 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks, memory = blocks[:0], 0
|
blocks, memory = blocks[:0], 0
|
||||||
|
|
@ -2741,24 +2779,23 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
// If the chain is terminating, stop processing blocks
|
// If the chain is terminating, stop processing blocks
|
||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
log.Debug("Abort during blocks processing")
|
log.Debug("Abort during blocks processing")
|
||||||
return 0, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(blocks) > 0 {
|
if len(blocks) > 0 {
|
||||||
log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64())
|
log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64())
|
||||||
return bc.insertChain(blocks, true)
|
return bc.insertChain(blocks, true, makeWitness)
|
||||||
}
|
}
|
||||||
|
return nil, 0, nil
|
||||||
return 0, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// recoverAncestors finds the closest ancestor with available state and re-execute
|
// recoverAncestors finds the closest ancestor with available state and re-execute
|
||||||
// all the ancestor blocks since that.
|
// all the ancestor blocks since that.
|
||||||
// recoverAncestors is only used post-merge.
|
// recoverAncestors is only used post-merge.
|
||||||
// We return the hash of the latest block that we could correctly validate.
|
// We return the hash of the latest block that we could correctly validate.
|
||||||
func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error) {
|
func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (common.Hash, error) {
|
||||||
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
||||||
var (
|
var (
|
||||||
hashes []common.Hash
|
hashes []common.Hash
|
||||||
|
|
@ -2801,7 +2838,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
|
||||||
} else {
|
} else {
|
||||||
b = bc.GetBlock(hashes[i], numbers[i])
|
b = bc.GetBlock(hashes[i], numbers[i])
|
||||||
}
|
}
|
||||||
if _, err := bc.insertChain(types.Blocks{b}, false); err != nil {
|
if _, _, err := bc.insertChain(types.Blocks{b}, false, makeWitness && i == 0); err != nil {
|
||||||
return b.ParentHash(), err
|
return b.ParentHash(), err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3122,14 +3159,14 @@ func ExportN(w io.Writer, blocks []*types.Block) error {
|
||||||
// The key difference between the InsertChain is it won't do the canonical chain
|
// The key difference between the InsertChain is it won't do the canonical chain
|
||||||
// updating. It relies on the additional SetCanonical call to finalize the entire
|
// updating. It relies on the additional SetCanonical call to finalize the entire
|
||||||
// procedure.
|
// procedure.
|
||||||
func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block) error {
|
func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block, makeWitness bool) (*stateless.Witness, error) {
|
||||||
if !bc.chainmu.TryLock() {
|
if !bc.chainmu.TryLock() {
|
||||||
return errChainStopped
|
return nil, errChainStopped
|
||||||
}
|
}
|
||||||
defer bc.chainmu.Unlock()
|
defer bc.chainmu.Unlock()
|
||||||
|
|
||||||
_, err := bc.insertChain(types.Blocks{block}, false)
|
witness, _, err := bc.insertChain(types.Blocks{block}, false, makeWitness)
|
||||||
return err
|
return witness, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCanonical rewinds the chain to set the new head block as the specified
|
// SetCanonical rewinds the chain to set the new head block as the specified
|
||||||
|
|
@ -3143,7 +3180,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
|
||||||
|
|
||||||
// Re-execute the reorged chain in case the head state is missing.
|
// Re-execute the reorged chain in case the head state is missing.
|
||||||
if !bc.HasState(head.Root()) {
|
if !bc.HasState(head.Root()) {
|
||||||
if latestValidHash, err := bc.recoverAncestors(head); err != nil {
|
if latestValidHash, err := bc.recoverAncestors(head, false); err != nil {
|
||||||
return latestValidHash, err
|
return latestValidHash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3230,7 +3267,11 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// reportBlock logs a bad block error.
|
// reportBlock logs a bad block error.
|
||||||
func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
|
func (bc *BlockChain) reportBlock(block *types.Block, res *ProcessResult, err error) {
|
||||||
|
var receipts types.Receipts
|
||||||
|
if res != nil {
|
||||||
|
receipts = res.Receipts
|
||||||
|
}
|
||||||
rawdb.WriteBadBlock(bc.db, block)
|
rawdb.WriteBadBlock(bc.db, block)
|
||||||
log.Error(summarizeBadBlock(block, receipts, bc.Config(), err))
|
log.Error(summarizeBadBlock(block, receipts, bc.Config(), err))
|
||||||
}
|
}
|
||||||
|
|
@ -3281,7 +3322,6 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header) (int, error) {
|
||||||
}
|
}
|
||||||
defer bc.chainmu.Unlock()
|
defer bc.chainmu.Unlock()
|
||||||
_, err := bc.hc.InsertHeaderChain(chain, start, bc.forker)
|
_, err := bc.hc.InsertHeaderChain(chain, start, bc.forker)
|
||||||
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -343,7 +343,7 @@ func (bc *BlockChain) GetTd(hash common.Hash, number uint64) *big.Int {
|
||||||
|
|
||||||
// HasState checks if state trie is fully present in the database or not.
|
// HasState checks if state trie is fully present in the database or not.
|
||||||
func (bc *BlockChain) HasState(hash common.Hash) bool {
|
func (bc *BlockChain) HasState(hash common.Hash) bool {
|
||||||
_, err := bc.stateCache.OpenTrie(hash)
|
_, err := bc.statedb.OpenTrie(hash)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,12 +377,9 @@ func (bc *BlockChain) stateRecoverable(root common.Hash) bool {
|
||||||
// If the code doesn't exist in the in-memory cache, check the storage with
|
// If the code doesn't exist in the in-memory cache, check the storage with
|
||||||
// new code scheme.
|
// new code scheme.
|
||||||
func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
|
func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
|
||||||
type codeReader interface {
|
|
||||||
ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error)
|
|
||||||
}
|
|
||||||
// TODO(rjl493456442) The associated account address is also required
|
// TODO(rjl493456442) The associated account address is also required
|
||||||
// in Verkle scheme. Fix it once snap-sync is supported for Verkle.
|
// in Verkle scheme. Fix it once snap-sync is supported for Verkle.
|
||||||
return bc.stateCache.(codeReader).ContractCodeWithPrefix(common.Address{}, hash)
|
return bc.statedb.ContractCodeWithPrefix(common.Address{}, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// State returns a new mutable state based on the current HEAD block.
|
// State returns a new mutable state based on the current HEAD block.
|
||||||
|
|
@ -392,7 +389,7 @@ func (bc *BlockChain) State() (*state.StateDB, error) {
|
||||||
|
|
||||||
// StateAt returns a new mutable state based on a particular point in time.
|
// StateAt returns a new mutable state based on a particular point in time.
|
||||||
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
|
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
|
||||||
return state.New(root, bc.stateCache, bc.snaps)
|
return state.New(root, bc.statedb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config retrieves the chain's fork configuration.
|
// Config retrieves the chain's fork configuration.
|
||||||
|
|
@ -418,7 +415,7 @@ func (bc *BlockChain) Processor() Processor {
|
||||||
|
|
||||||
// StateCache returns the caching database underpinning the blockchain instance.
|
// StateCache returns the caching database underpinning the blockchain instance.
|
||||||
func (bc *BlockChain) StateCache() state.Database {
|
func (bc *BlockChain) StateCache() state.Database {
|
||||||
return bc.stateCache
|
return bc.statedb
|
||||||
}
|
}
|
||||||
|
|
||||||
// GasLimit returns the gas limit of the current HEAD block.
|
// GasLimit returns the gas limit of the current HEAD block.
|
||||||
|
|
|
||||||
|
|
@ -1797,8 +1797,8 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
|
||||||
|
|
||||||
func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
|
func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
// fmt.Println(tt.dump(true))
|
// fmt.Println(tt.dump(false))
|
||||||
|
|
||||||
// Create a temporary persistent database
|
// Create a temporary persistent database
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
|
|
@ -1952,7 +1952,7 @@ func TestIssue23496(t *testing.T) {
|
||||||
|
|
||||||
func testIssue23496(t *testing.T, scheme string) {
|
func testIssue23496(t *testing.T, scheme string) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
|
|
||||||
// Create a temporary persistent database
|
// Create a temporary persistent database
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
|
|
|
||||||
|
|
@ -1961,7 +1961,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
|
||||||
|
|
||||||
func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
|
func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
// fmt.Println(tt.dump(false))
|
// fmt.Println(tt.dump(false))
|
||||||
|
|
||||||
// Create a temporary persistent database
|
// Create a temporary persistent database
|
||||||
|
|
@ -2042,7 +2042,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
||||||
dbconfig.HashDB = hashdb.Defaults
|
dbconfig.HashDB = hashdb.Defaults
|
||||||
}
|
}
|
||||||
chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
|
chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
|
||||||
chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb)
|
chain.statedb = state.NewDatabase(chain.triedb, chain.snaps)
|
||||||
|
|
||||||
// Force run a freeze cycle
|
// Force run a freeze cycle
|
||||||
type freezer interface {
|
type freezer interface {
|
||||||
|
|
|
||||||
|
|
@ -226,8 +226,8 @@ type snapshotTest struct {
|
||||||
|
|
||||||
func (snaptest *snapshotTest) test(t *testing.T) {
|
func (snaptest *snapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
// fmt.Println(tt.dump())
|
// fmt.Println(snaptest.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Restart the chain normally
|
// Restart the chain normally
|
||||||
|
|
@ -249,8 +249,8 @@ type crashSnapshotTest struct {
|
||||||
|
|
||||||
func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
// fmt.Println(tt.dump())
|
// fmt.Println(snaptest.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Pull the plug on the database, simulating a hard crash
|
// Pull the plug on the database, simulating a hard crash
|
||||||
|
|
@ -303,8 +303,8 @@ type gappedSnapshotTest struct {
|
||||||
|
|
||||||
func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
// fmt.Println(tt.dump())
|
// fmt.Println(snaptest.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Insert blocks without enabling snapshot if gapping is required.
|
// Insert blocks without enabling snapshot if gapping is required.
|
||||||
|
|
@ -347,8 +347,8 @@ type setHeadSnapshotTest struct {
|
||||||
|
|
||||||
func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
|
func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
// fmt.Println(tt.dump())
|
// fmt.Println(snaptest.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Rewind the chain if setHead operation is required.
|
// Rewind the chain if setHead operation is required.
|
||||||
|
|
@ -376,8 +376,8 @@ type wipeCrashSnapshotTest struct {
|
||||||
|
|
||||||
func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
// fmt.Println(tt.dump())
|
// fmt.Println(snaptest.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Firstly, stop the chain properly, with all snapshot journal
|
// Firstly, stop the chain properly, with all snapshot journal
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -170,15 +171,23 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
_, err = state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.statedb)
|
||||||
receipts, _, usedGas, statedb, _, err := blockchain.ProcessBlock(block, blockchain.GetBlockByHash(block.ParentHash()).Header())
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
blockchain.reportBlock(block, receipts, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, false); err != nil {
|
receipts, logs, usedGas, statedb, _, err := blockchain.ProcessBlock(block, blockchain.GetBlockByHash(block.ParentHash()).Header())
|
||||||
blockchain.reportBlock(block, receipts, err)
|
res := &ProcessResult{
|
||||||
|
Receipts: receipts,
|
||||||
|
Logs: logs,
|
||||||
|
GasUsed: usedGas,
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
blockchain.reportBlock(block, res, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = blockchain.validator.ValidateState(block, statedb, res, false)
|
||||||
|
if err != nil {
|
||||||
|
blockchain.reportBlock(block, res, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,8 +234,8 @@ func testParallelBlockChainImport(t *testing.T, scheme string, enforceParallelPr
|
||||||
type AlwaysFailParallelStateProcessor struct {
|
type AlwaysFailParallelStateProcessor struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AlwaysFailParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config, interruptCtx context.Context) (types.Receipts, []*types.Log, uint64, error) {
|
func (p *AlwaysFailParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config, interruptCtx context.Context) (*ProcessResult, error) {
|
||||||
return nil, nil, 0, errors.New("always fail")
|
return nil, errors.New("always fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
type SlowSerialStateProcessor struct {
|
type SlowSerialStateProcessor struct {
|
||||||
|
|
@ -237,7 +246,7 @@ func NewSlowSerialStateProcessor(s Processor) *SlowSerialStateProcessor {
|
||||||
return &SlowSerialStateProcessor{s: s}
|
return &SlowSerialStateProcessor{s: s}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SlowSerialStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config, interruptCtx context.Context) (types.Receipts, []*types.Log, uint64, error) {
|
func (p *SlowSerialStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config, interruptCtx context.Context) (*ProcessResult, error) {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
return p.s.Process(block, statedb, cfg, interruptCtx)
|
return p.s.Process(block, statedb, cfg, interruptCtx)
|
||||||
}
|
}
|
||||||
|
|
@ -1442,7 +1451,6 @@ func testSideLogRebirth(t *testing.T, scheme string) {
|
||||||
if _, err := blockchain.InsertChain(sideChain); err != nil {
|
if _, err := blockchain.InsertChain(sideChain); err != nil {
|
||||||
t.Fatalf("failed to insert forked chain: %v", err)
|
t.Fatalf("failed to insert forked chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
|
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
|
||||||
|
|
||||||
// Generate a new block based on side chain.
|
// Generate a new block based on side chain.
|
||||||
|
|
@ -1450,7 +1458,6 @@ func testSideLogRebirth(t *testing.T, scheme string) {
|
||||||
if _, err := blockchain.InsertChain(newBlocks); err != nil {
|
if _, err := blockchain.InsertChain(newBlocks); err != nil {
|
||||||
t.Fatalf("failed to insert forked chain: %v", err)
|
t.Fatalf("failed to insert forked chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkLogEvents(t, newLogCh, rmLogsCh, 1, 0)
|
checkLogEvents(t, newLogCh, rmLogsCh, 1, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2005,7 +2012,6 @@ func testLargeReorgTrieGC(t *testing.T, scheme string) {
|
||||||
if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil {
|
if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil {
|
||||||
t.Fatalf("failed to insert competitor chain: %v", err)
|
t.Fatalf("failed to insert competitor chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, block := range competitor[:len(competitor)-2] {
|
for i, block := range competitor[:len(competitor)-2] {
|
||||||
if chain.HasState(block.Root()) {
|
if chain.HasState(block.Root()) {
|
||||||
t.Fatalf("competitor %d: low TD chain became processed", i)
|
t.Fatalf("competitor %d: low TD chain became processed", i)
|
||||||
|
|
@ -2376,9 +2382,9 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
// [ Cn, Cn+1, Cc, Sn+3 ... Sm]
|
// [ Cn, Cn+1, Cc, Sn+3 ... Sm]
|
||||||
// ^ ^ ^ pruned
|
// ^ ^ ^ pruned
|
||||||
func TestPrunedImportSide(t *testing.T) {
|
func TestPrunedImportSide(t *testing.T) {
|
||||||
//glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
|
// glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
|
||||||
// glogger.Verbosity(3)
|
// glogger.Verbosity(3)
|
||||||
//log.Root().SetHandler(log.Handler(glogger))
|
// log.SetDefault(log.NewLogger(glogger))
|
||||||
testSideImport(t, 3, 3, -1)
|
testSideImport(t, 3, 3, -1)
|
||||||
testSideImport(t, 3, -3, -1)
|
testSideImport(t, 3, -3, -1)
|
||||||
testSideImport(t, 10, 0, -1)
|
testSideImport(t, 10, 0, -1)
|
||||||
|
|
@ -2387,9 +2393,9 @@ func TestPrunedImportSide(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrunedImportSideWithMerging(t *testing.T) {
|
func TestPrunedImportSideWithMerging(t *testing.T) {
|
||||||
//glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
|
// glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
|
||||||
// glogger.Verbosity(3)
|
// glogger.Verbosity(3)
|
||||||
//log.Root().SetHandler(log.Handler(glogger))
|
// log.SetDefault(log.NewLogger(glogger))
|
||||||
testSideImport(t, 3, 3, 0)
|
testSideImport(t, 3, 3, 0)
|
||||||
testSideImport(t, 3, -3, 0)
|
testSideImport(t, 3, -3, 0)
|
||||||
testSideImport(t, 10, 0, 0)
|
testSideImport(t, 10, 0, 0)
|
||||||
|
|
@ -3049,7 +3055,21 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) {
|
||||||
// Generate and import the canonical chain
|
// Generate and import the canonical chain
|
||||||
_, blocks, _ := GenerateChainWithGenesis(genesis, engine, 2*state.TriesInMemory, nil)
|
_, blocks, _ := GenerateChainWithGenesis(genesis, engine, 2*state.TriesInMemory, nil)
|
||||||
|
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil, nil)
|
// Construct a database with freezer enabled
|
||||||
|
datadir := t.TempDir()
|
||||||
|
ancient := path.Join(datadir, "ancient")
|
||||||
|
|
||||||
|
db, err := rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create persistent database: %v", err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3972,7 +3992,7 @@ func TestSetCanonical(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSetCanonical(t *testing.T, scheme string) {
|
func testSetCanonical(t *testing.T, scheme string) {
|
||||||
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||||
|
|
||||||
var (
|
var (
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
|
@ -4024,7 +4044,7 @@ func testSetCanonical(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, block := range side {
|
for _, block := range side {
|
||||||
err := chain.InsertBlockWithoutSetHead(block)
|
_, err := chain.InsertBlockWithoutSetHead(block, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to insert into chain: %v", err)
|
t.Fatalf("Failed to insert into chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -4583,7 +4603,6 @@ func TestEIP3651(t *testing.T) {
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr).Hooks()}, nil, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr).Hooks()}, nil, nil, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -360,7 +360,18 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
gen(i, b)
|
gen(i, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals}
|
var requests types.Requests
|
||||||
|
if config.IsPrague(b.header.Number) && config.Bor == nil {
|
||||||
|
for _, r := range b.receipts {
|
||||||
|
d, err := ParseDepositLogs(r.Logs, config)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
|
||||||
|
}
|
||||||
|
requests = append(requests, d...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: requests}
|
||||||
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
|
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
@ -382,7 +393,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, triedb), nil)
|
statedb, err := state.New(parent.Root(), state.NewDatabase(triedb, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -483,15 +494,14 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
panic(fmt.Sprintf("trie write error: %v", err))
|
panic(fmt.Sprintf("trie write error: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO uncomment when proof generation is merged
|
proofs = append(proofs, block.ExecutionWitness().VerkleProof)
|
||||||
// proofs = append(proofs, block.ExecutionWitness().VerkleProof)
|
keyvals = append(keyvals, block.ExecutionWitness().StateDiff)
|
||||||
// keyvals = append(keyvals, block.ExecutionWitness().StateDiff)
|
|
||||||
|
|
||||||
return block, b.receipts
|
return block, b.receipts
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, trdb), nil)
|
statedb, err := state.New(parent.Root(), state.NewDatabase(trdb, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
Config: &proConf,
|
Config: &proConf,
|
||||||
}
|
}
|
||||||
|
|
||||||
proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
||||||
defer proBc.Stop()
|
defer proBc.Stop()
|
||||||
|
|
||||||
|
|
@ -63,7 +62,6 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
Config: &conConf,
|
Config: &conConf,
|
||||||
}
|
}
|
||||||
|
|
||||||
conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
||||||
defer conBc.Stop()
|
defer conBc.Stop()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,25 +81,6 @@ func TestCreation(t *testing.T) {
|
||||||
// {50000000, 2000000000, ID{Hash: checksumToBytes(0x9f3d2254), Next: 0}}, // Future Cancun block
|
// {50000000, 2000000000, ID{Hash: checksumToBytes(0x9f3d2254), Next: 0}}, // Future Cancun block
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Goerli test cases
|
|
||||||
{
|
|
||||||
params.GoerliChainConfig,
|
|
||||||
core.DefaultGoerliGenesisBlock().ToBlock(),
|
|
||||||
[]testcase{
|
|
||||||
{0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block
|
|
||||||
{1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block
|
|
||||||
{1561651, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // First Istanbul block
|
|
||||||
{4460643, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // Last Istanbul block
|
|
||||||
{4460644, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // First Berlin block
|
|
||||||
{5000000, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // Last Berlin block
|
|
||||||
// {5062605, 0, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // First London block
|
|
||||||
// {6000000, 1678832735, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // Last London block
|
|
||||||
// {6000001, 1678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // First Shanghai block
|
|
||||||
// {6500002, 1705473119, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // Last Shanghai block
|
|
||||||
// {6500003, 1705473120, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // First Cancun block
|
|
||||||
// {6500003, 2705473120, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // Future Cancun block
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Sepolia test cases
|
// Sepolia test cases
|
||||||
{
|
{
|
||||||
params.SepoliaChainConfig,
|
params.SepoliaChainConfig,
|
||||||
|
|
|
||||||
101
core/genesis.go
101
core/genesis.go
|
|
@ -141,8 +141,8 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
|
||||||
}
|
}
|
||||||
// Create an ephemeral in-memory database for computing hash,
|
// Create an ephemeral in-memory database for computing hash,
|
||||||
// all the derived states will be discarded to not pollute disk.
|
// all the derived states will be discarded to not pollute disk.
|
||||||
db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config)
|
db := rawdb.NewMemoryDatabase()
|
||||||
statedb, err := state.New(types.EmptyRootHash, db, nil)
|
statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(triedb.NewDatabase(db, config), nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -161,13 +161,12 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
|
||||||
return statedb.Commit(0, false)
|
return statedb.Commit(0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// flushAlloc is very similar with hash, but the main difference is all the generated
|
// flushAlloc is very similar with hash, but the main difference is all the
|
||||||
// states will be persisted into the given database. Also, the genesis state
|
// generated states will be persisted into the given database.
|
||||||
// specification will be flushed as well.
|
func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, error) {
|
||||||
func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Database, blockhash common.Hash) error {
|
statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(triedb, nil))
|
||||||
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for addr, account := range *ga {
|
for addr, account := range *ga {
|
||||||
|
|
@ -185,23 +184,15 @@ func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Databa
|
||||||
}
|
}
|
||||||
root, err := statedb.Commit(0, false)
|
root, err := statedb.Commit(0, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
// Commit newly generated states into disk if it's not empty.
|
// Commit newly generated states into disk if it's not empty.
|
||||||
if root != types.EmptyRootHash {
|
if root != types.EmptyRootHash {
|
||||||
if err := triedb.Commit(root, true); err != nil {
|
if err := triedb.Commit(root, true); err != nil {
|
||||||
return err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Marshal the genesis state specification and persist.
|
return root, nil
|
||||||
blob, err := json.Marshal(ga)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rawdb.WriteGenesisStateSpec(db, blockhash, blob)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.GenesisAlloc, err error) {
|
func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.GenesisAlloc, err error) {
|
||||||
|
|
@ -223,8 +214,6 @@ func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.Gene
|
||||||
switch blockhash {
|
switch blockhash {
|
||||||
case params.MainnetGenesisHash:
|
case params.MainnetGenesisHash:
|
||||||
genesis = DefaultGenesisBlock()
|
genesis = DefaultGenesisBlock()
|
||||||
case params.GoerliGenesisHash:
|
|
||||||
genesis = DefaultGoerliGenesisBlock()
|
|
||||||
case params.SepoliaGenesisHash:
|
case params.SepoliaGenesisHash:
|
||||||
genesis = DefaultSepoliaGenesisBlock()
|
genesis = DefaultSepoliaGenesisBlock()
|
||||||
case params.HoleskyGenesisHash:
|
case params.HoleskyGenesisHash:
|
||||||
|
|
@ -464,7 +453,11 @@ func (g *Genesis) ToBlock() *types.Block {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
return g.toBlockWithRoot(root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// toBlockWithRoot constructs the genesis block with the given genesis state root.
|
||||||
|
func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
||||||
head := &types.Header{
|
head := &types.Header{
|
||||||
Number: new(big.Int).SetUint64(g.Number),
|
Number: new(big.Int).SetUint64(g.Number),
|
||||||
Nonce: types.EncodeNonce(g.Nonce),
|
Nonce: types.EncodeNonce(g.Nonce),
|
||||||
|
|
@ -494,28 +487,43 @@ func (g *Genesis) ToBlock() *types.Block {
|
||||||
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
|
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
var withdrawals []*types.Withdrawal
|
withdrawals []*types.Withdrawal
|
||||||
|
requests types.Requests
|
||||||
|
)
|
||||||
if conf := g.Config; conf != nil {
|
if conf := g.Config; conf != nil {
|
||||||
num := big.NewInt(int64(g.Number))
|
num := big.NewInt(int64(g.Number))
|
||||||
if conf.IsShanghai(num) {
|
if conf.IsShanghai(num) {
|
||||||
head.WithdrawalsHash = nil
|
head.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
||||||
withdrawals = nil
|
withdrawals = make([]*types.Withdrawal, 0)
|
||||||
}
|
}
|
||||||
if conf.IsCancun(num) {
|
if conf.IsCancun(num) {
|
||||||
head.ParentBeaconRoot = nil
|
// EIP-4788: The parentBeaconBlockRoot of the genesis block is always
|
||||||
head.ExcessBlobGas = nil
|
// the zero hash. This is because the genesis block does not have a parent
|
||||||
head.BlobGasUsed = nil
|
// by definition.
|
||||||
|
head.ParentBeaconRoot = new(common.Hash)
|
||||||
|
// EIP-4844 fields
|
||||||
|
head.ExcessBlobGas = g.ExcessBlobGas
|
||||||
|
head.BlobGasUsed = g.BlobGasUsed
|
||||||
|
if head.ExcessBlobGas == nil {
|
||||||
|
head.ExcessBlobGas = new(uint64)
|
||||||
|
}
|
||||||
|
if head.BlobGasUsed == nil {
|
||||||
|
head.BlobGasUsed = new(uint64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
|
if conf.IsPrague(num) {
|
||||||
|
head.RequestsHash = &types.EmptyRequestsHash
|
||||||
|
requests = make(types.Requests, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals, Requests: requests}, nil, trie.NewStackTrie(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit writes the block and state of a genesis specification to the database.
|
// Commit writes the block and state of a genesis specification to the database.
|
||||||
// The block is committed as the canonical head block.
|
// The block is committed as the canonical head block.
|
||||||
func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Block, error) {
|
func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Block, error) {
|
||||||
block := g.ToBlock()
|
if g.Number != 0 {
|
||||||
if block.Number().Sign() != 0 {
|
|
||||||
return nil, errors.New("can't commit genesis block with number > 0")
|
return nil, errors.New("can't commit genesis block with number > 0")
|
||||||
}
|
}
|
||||||
config := g.Config
|
config := g.Config
|
||||||
|
|
@ -525,15 +533,22 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
|
||||||
if err := config.CheckConfigForkOrder(); err != nil {
|
if err := config.CheckConfigForkOrder(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength {
|
if config.Clique != nil && len(g.ExtraData) < 32+crypto.SignatureLength {
|
||||||
return nil, errors.New("can't start clique chain without signers")
|
return nil, errors.New("can't start clique chain without signers")
|
||||||
}
|
}
|
||||||
// All the checks has passed, flushAlloc the states derived from the genesis
|
// flush the data to disk and compute the state root
|
||||||
// specification as well as the specification itself into the provided
|
root, err := flushAlloc(&g.Alloc, triedb)
|
||||||
// database.
|
if err != nil {
|
||||||
if err := flushAlloc(&g.Alloc, db, triedb, block.Hash()); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
block := g.toBlockWithRoot(root)
|
||||||
|
|
||||||
|
// Marshal the genesis state specification and persist.
|
||||||
|
blob, err := json.Marshal(g.Alloc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rawdb.WriteGenesisStateSpec(db, block.Hash(), blob)
|
||||||
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())
|
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())
|
||||||
rawdb.WriteBlock(db, block)
|
rawdb.WriteBlock(db, block)
|
||||||
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
|
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
|
||||||
|
|
@ -577,18 +592,6 @@ func DefaultGenesisBlock() *Genesis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultGoerliGenesisBlock returns the Görli network genesis block.
|
|
||||||
func DefaultGoerliGenesisBlock() *Genesis {
|
|
||||||
return &Genesis{
|
|
||||||
Config: params.GoerliChainConfig,
|
|
||||||
Timestamp: 1548854791,
|
|
||||||
ExtraData: hexutil.MustDecode("0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
|
||||||
GasLimit: 10485760,
|
|
||||||
Difficulty: big.NewInt(1),
|
|
||||||
Alloc: decodePrealloc(goerliAllocData),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultSepoliaGenesisBlock returns the Sepolia network genesis block.
|
// DefaultSepoliaGenesisBlock returns the Sepolia network genesis block.
|
||||||
func DefaultSepoliaGenesisBlock() *Genesis {
|
func DefaultSepoliaGenesisBlock() *Genesis {
|
||||||
return &Genesis{
|
return &Genesis{
|
||||||
|
|
@ -679,6 +682,8 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
|
||||||
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
||||||
// Pre-deploy EIP-4788 system contract
|
// Pre-deploy EIP-4788 system contract
|
||||||
params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0},
|
params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0},
|
||||||
|
// Pre-deploy EIP-2935 history contract.
|
||||||
|
params.HistoryStorageAddress: {Nonce: 1, Code: params.HistoryStorageCode, Balance: common.Big0},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if faucet != nil {
|
if faucet != nil {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -35,15 +35,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInvalidCliqueConfig(t *testing.T) {
|
|
||||||
block := DefaultGoerliGenesisBlock()
|
|
||||||
block.ExtraData = []byte{}
|
|
||||||
db := rawdb.NewMemoryDatabase()
|
|
||||||
if _, err := block.Commit(db, triedb.NewDatabase(db, nil)); err == nil {
|
|
||||||
t.Fatal("Expected error on invalid clique config")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetupGenesis(t *testing.T) {
|
func TestSetupGenesis(t *testing.T) {
|
||||||
testSetupGenesis(t, rawdb.HashScheme)
|
testSetupGenesis(t, rawdb.HashScheme)
|
||||||
testSetupGenesis(t, rawdb.PathScheme)
|
testSetupGenesis(t, rawdb.PathScheme)
|
||||||
|
|
@ -106,15 +97,15 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
||||||
wantConfig: customg.Config,
|
wantConfig: customg.Config,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "custom block in DB, genesis == goerli",
|
name: "custom block in DB, genesis == sepolia",
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||||
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||||
customg.Commit(db, tdb)
|
customg.Commit(db, tdb)
|
||||||
return SetupGenesisBlock(db, tdb, DefaultGoerliGenesisBlock())
|
return SetupGenesisBlock(db, tdb, DefaultSepoliaGenesisBlock())
|
||||||
},
|
},
|
||||||
wantErr: &GenesisMismatchError{Stored: customghash, New: params.GoerliGenesisHash},
|
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
|
||||||
wantHash: params.GoerliGenesisHash,
|
wantHash: params.SepoliaGenesisHash,
|
||||||
wantConfig: params.GoerliChainConfig,
|
wantConfig: params.SepoliaChainConfig,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "compatible config in DB",
|
name: "compatible config in DB",
|
||||||
|
|
@ -187,7 +178,6 @@ func TestGenesisHashes(t *testing.T) {
|
||||||
want common.Hash
|
want common.Hash
|
||||||
}{
|
}{
|
||||||
{DefaultGenesisBlock(), params.MainnetGenesisHash},
|
{DefaultGenesisBlock(), params.MainnetGenesisHash},
|
||||||
{DefaultGoerliGenesisBlock(), params.GoerliGenesisHash},
|
|
||||||
{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
|
{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
|
||||||
} {
|
} {
|
||||||
// Test via MustCommit
|
// Test via MustCommit
|
||||||
|
|
@ -313,7 +303,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := common.FromHex("14398d42be3394ff8d50681816a4b7bf8d8283306f577faba2d5bc57498de23b")
|
expected := common.FromHex("4a83dc39eb688dbcfaf581d60e82de18f875e38786ebce5833342011d6fef37b")
|
||||||
got := genesis.ToBlock().Root().Bytes()
|
got := genesis.ToBlock().Root().Bytes()
|
||||||
if !bytes.Equal(got, expected) {
|
if !bytes.Equal(got, expected) {
|
||||||
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got)
|
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got)
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ var parallelizabilityTimer = metrics.NewRegisteredTimer("block/parallelizability
|
||||||
// returns the amount of gas that was used in the process. If any of the
|
// returns the amount of gas that was used in the process. If any of the
|
||||||
// transactions failed to execute due to insufficient gas it will return an error.
|
// transactions failed to execute due to insufficient gas it will return an error.
|
||||||
// nolint:gocognit
|
// nolint:gocognit
|
||||||
func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config, interruptCtx context.Context) (types.Receipts, []*types.Log, uint64, error) {
|
func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config, interruptCtx context.Context) (*ProcessResult, error) {
|
||||||
var (
|
var (
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
header = block.Header()
|
header = block.Header()
|
||||||
|
|
@ -301,13 +301,18 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
|
||||||
}
|
}
|
||||||
|
|
||||||
blockContext := NewEVMBlockContext(header, p.bc, nil)
|
blockContext := NewEVMBlockContext(header, p.bc, nil)
|
||||||
|
context := NewEVMBlockContext(header, p.bc.hc, nil)
|
||||||
|
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
||||||
|
|
||||||
|
if p.config.IsPrague(block.Number()) {
|
||||||
|
ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
|
||||||
|
}
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
msg, err := TransactionToMessage(tx, types.MakeSigner(p.config, header.Number, header.Time), header.BaseFee)
|
msg, err := TransactionToMessage(tx, types.MakeSigner(p.config, header.Number, header.Time), header.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("error creating message", "err", err)
|
log.Error("error creating message", "err", err)
|
||||||
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cleansdb := statedb.Copy()
|
cleansdb := statedb.Copy()
|
||||||
|
|
@ -386,13 +391,27 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, err
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read requests if Prague is enabled.
|
||||||
|
var requests types.Requests
|
||||||
|
if p.config.IsPrague(block.Number()) && p.config.Bor == nil {
|
||||||
|
requests, err = ParseDepositLogs(allLogs, p.config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||||
p.engine.Finalize(p.bc, header, statedb, block.Body())
|
p.engine.Finalize(p.bc, header, statedb, block.Body())
|
||||||
|
|
||||||
return receipts, allLogs, *usedGas, nil
|
return &ProcessResult{
|
||||||
|
Receipts: receipts,
|
||||||
|
Requests: requests,
|
||||||
|
Logs: allLogs,
|
||||||
|
GasUsed: *usedGas,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDeps(txDependency [][]uint64) map[int][]int {
|
func GetDeps(txDependency [][]uint64) map[int][]int {
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,10 @@ func ParseStateScheme(provided string, disk ethdb.Database) (string, error) {
|
||||||
log.Info("State scheme set to already existing", "scheme", stored)
|
log.Info("State scheme set to already existing", "scheme", stored)
|
||||||
return stored, nil // reuse scheme of persistent scheme
|
return stored, nil // reuse scheme of persistent scheme
|
||||||
}
|
}
|
||||||
|
// If state scheme is specified, ensure it's valid.
|
||||||
|
if provided != HashScheme && provided != PathScheme {
|
||||||
|
return "", fmt.Errorf("invalid state scheme %s", provided)
|
||||||
|
}
|
||||||
// If state scheme is specified, ensure it's compatible with
|
// If state scheme is specified, ensure it's compatible with
|
||||||
// persistent state.
|
// persistent state.
|
||||||
if stored == "" || provided == stored {
|
if stored == "" || provided == stored {
|
||||||
|
|
|
||||||
|
|
@ -164,12 +164,6 @@ func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error)
|
||||||
return fn(db)
|
return fn(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MigrateTable processes the entries in a given table in sequence
|
|
||||||
// converting them to a new format if they're of an old format.
|
|
||||||
func (db *nofreezedb) MigrateTable(kind string, convert convertLegacyFn) error {
|
|
||||||
return errNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
// AncientDatadir returns an error as we don't have a backing chain freezer.
|
// AncientDatadir returns an error as we don't have a backing chain freezer.
|
||||||
func (db *nofreezedb) AncientDatadir() (string, error) {
|
func (db *nofreezedb) AncientDatadir() (string, error) {
|
||||||
return "", errNotSupported
|
return "", errNotSupported
|
||||||
|
|
|
||||||
|
|
@ -54,13 +54,11 @@ var (
|
||||||
// freezerTableSize defines the maximum size of freezer data files.
|
// freezerTableSize defines the maximum size of freezer data files.
|
||||||
const freezerTableSize = 2 * 1000 * 1000 * 1000
|
const freezerTableSize = 2 * 1000 * 1000 * 1000
|
||||||
|
|
||||||
// Freezer is a memory mapped append-only database to store immutable ordered
|
// Freezer is an append-only database to store immutable ordered data into
|
||||||
// data into flat files:
|
// flat files:
|
||||||
//
|
//
|
||||||
// - The append-only nature ensures that disk writes are minimized.
|
// - The append-only nature ensures that disk writes are minimized.
|
||||||
// - The memory mapping ensures we can max out system memory for caching without
|
// - The in-order data ensures that disk reads are always optimized.
|
||||||
// reserving it for go-ethereum. This would also reduce the memory requirements
|
|
||||||
// of Geth, and thus also GC overhead.
|
|
||||||
type Freezer struct {
|
type Freezer struct {
|
||||||
frozen atomic.Uint64 // Number of items already frozen
|
frozen atomic.Uint64 // Number of items already frozen
|
||||||
tail atomic.Uint64 // Number of the first stored item in the freezer
|
tail atomic.Uint64 // Number of the first stored item in the freezer
|
||||||
|
|
@ -162,7 +160,7 @@ func NewFreezer(datadir string, namespace string, readonly bool, offset uint64,
|
||||||
return freezer, nil
|
return freezer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close terminates the chain freezer, unmapping all the data files.
|
// Close terminates the chain freezer, closing all the data files.
|
||||||
func (f *Freezer) Close() error {
|
func (f *Freezer) Close() error {
|
||||||
f.writeLock.Lock()
|
f.writeLock.Lock()
|
||||||
defer f.writeLock.Unlock()
|
defer f.writeLock.Unlock()
|
||||||
|
|
|
||||||
|
|
@ -413,13 +413,6 @@ func (f *MemoryFreezer) Sync() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MigrateTable processes and migrates entries of a given table to a new format.
|
|
||||||
// The second argument is a function that takes a raw entry and returns it
|
|
||||||
// in the newest format.
|
|
||||||
func (f *MemoryFreezer) MigrateTable(string, func([]byte) ([]byte, error)) error {
|
|
||||||
return errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close releases all the sources held by the memory freezer. It will panic if
|
// Close releases all the sources held by the memory freezer. It will panic if
|
||||||
// any following invocation is made to a closed freezer.
|
// any following invocation is made to a closed freezer.
|
||||||
func (f *MemoryFreezer) Close() error {
|
func (f *MemoryFreezer) Close() error {
|
||||||
|
|
|
||||||
|
|
@ -219,15 +219,6 @@ func (f *resettableFreezer) Sync() error {
|
||||||
return f.freezer.Sync()
|
return f.freezer.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MigrateTable processes the entries in a given table in sequence
|
|
||||||
// converting them to a new format if they're of an old format.
|
|
||||||
func (f *resettableFreezer) MigrateTable(kind string, convert convertLegacyFn) error {
|
|
||||||
f.lock.RLock()
|
|
||||||
defer f.lock.RUnlock()
|
|
||||||
|
|
||||||
return f.freezer.MigrateTable(kind, convert)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup removes the directory located in the specified path
|
// cleanup removes the directory located in the specified path
|
||||||
// has the name with deletion marker suffix.
|
// has the name with deletion marker suffix.
|
||||||
func cleanup(path string) error {
|
func cleanup(path string) error {
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -418,99 +416,6 @@ func checkAncientCount(t *testing.T, f *Freezer, kind string, n uint64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRenameWindows(t *testing.T) {
|
|
||||||
var (
|
|
||||||
fname = "file.bin"
|
|
||||||
fname2 = "file2.bin"
|
|
||||||
data = []byte{1, 2, 3, 4}
|
|
||||||
data2 = []byte{2, 3, 4, 5}
|
|
||||||
data3 = []byte{3, 5, 6, 7}
|
|
||||||
dataLen = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create 2 temp dirs
|
|
||||||
dir1 := t.TempDir()
|
|
||||||
dir2 := t.TempDir()
|
|
||||||
|
|
||||||
// Create file in dir1 and fill with data
|
|
||||||
f, err := os.Create(filepath.Join(dir1, fname))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
f2, err := os.Create(filepath.Join(dir1, fname2))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
f3, err := os.Create(filepath.Join(dir2, fname2))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := f.Write(data); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := f2.Write(data2); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := f3.Write(data3); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := f.Close(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := f2.Close(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := f3.Close(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := os.Rename(f.Name(), filepath.Join(dir2, fname)); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := os.Rename(f2.Name(), filepath.Join(dir2, fname2)); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check file contents
|
|
||||||
f, err = os.Open(filepath.Join(dir2, fname))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
defer os.Remove(f.Name())
|
|
||||||
|
|
||||||
buf := make([]byte, dataLen)
|
|
||||||
if _, err := f.Read(buf); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(buf, data) {
|
|
||||||
t.Errorf("unexpected file contents. Got %v\n", buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err = os.Open(filepath.Join(dir2, fname2))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
defer os.Remove(f.Name())
|
|
||||||
|
|
||||||
if _, err := f.Read(buf); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(buf, data2) {
|
|
||||||
t.Errorf("unexpected file contents. Got %v\n", buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFreezerCloseSync(t *testing.T) {
|
func TestFreezerCloseSync(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,12 +123,6 @@ func (t *table) Sync() error {
|
||||||
return t.db.Sync()
|
return t.db.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MigrateTable processes the entries in a given table in sequence
|
|
||||||
// converting them to a new format if they're of an old format.
|
|
||||||
func (t *table) MigrateTable(kind string, convert convertLegacyFn) error {
|
|
||||||
return t.db.MigrateTable(kind, convert)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AncientDatadir returns the ancient datadir of the underlying database.
|
// AncientDatadir returns the ancient datadir of the underlying database.
|
||||||
func (t *table) AncientDatadir() (string, error) {
|
func (t *table) AncientDatadir() (string, error) {
|
||||||
return t.db.AncientDatadir()
|
return t.db.AncientDatadir()
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ import (
|
||||||
|
|
||||||
// mode specifies how a tree location has been accessed
|
// mode specifies how a tree location has been accessed
|
||||||
// for the byte value:
|
// for the byte value:
|
||||||
// * the first bit is set if the branch has been edited
|
// * the first bit is set if the branch has been read
|
||||||
// * the second bit is set if the branch has been read
|
// * the second bit is set if the branch has been edited
|
||||||
type mode byte
|
type mode byte
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -94,11 +94,8 @@ func (ae *AccessEvents) Copy() *AccessEvents {
|
||||||
// member fields of an account.
|
// member fields of an account.
|
||||||
func (ae *AccessEvents) AddAccount(addr common.Address, isWrite bool) uint64 {
|
func (ae *AccessEvents) AddAccount(addr common.Address, isWrite bool) uint64 {
|
||||||
var gas uint64
|
var gas uint64
|
||||||
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, isWrite)
|
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, isWrite)
|
||||||
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, isWrite)
|
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, isWrite)
|
||||||
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, isWrite)
|
|
||||||
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeKeccakLeafKey, isWrite)
|
|
||||||
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeSizeLeafKey, isWrite)
|
|
||||||
return gas
|
return gas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,8 +104,7 @@ func (ae *AccessEvents) AddAccount(addr common.Address, isWrite bool) uint64 {
|
||||||
// call to that account.
|
// call to that account.
|
||||||
func (ae *AccessEvents) MessageCallGas(destination common.Address) uint64 {
|
func (ae *AccessEvents) MessageCallGas(destination common.Address) uint64 {
|
||||||
var gas uint64
|
var gas uint64
|
||||||
gas += ae.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.VersionLeafKey, false)
|
gas += ae.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.BasicDataLeafKey, false)
|
||||||
gas += ae.touchAddressAndChargeGas(destination, zeroTreeIndex, utils.CodeSizeLeafKey, false)
|
|
||||||
return gas
|
return gas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,41 +112,43 @@ func (ae *AccessEvents) MessageCallGas(destination common.Address) uint64 {
|
||||||
// cold balance member fields of the caller and the callee accounts.
|
// cold balance member fields of the caller and the callee accounts.
|
||||||
func (ae *AccessEvents) ValueTransferGas(callerAddr, targetAddr common.Address) uint64 {
|
func (ae *AccessEvents) ValueTransferGas(callerAddr, targetAddr common.Address) uint64 {
|
||||||
var gas uint64
|
var gas uint64
|
||||||
gas += ae.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BalanceLeafKey, true)
|
gas += ae.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BasicDataLeafKey, true)
|
||||||
gas += ae.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, true)
|
gas += ae.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true)
|
||||||
|
return gas
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContractCreateCPreheck charges access costs before
|
||||||
|
// a contract creation is initiated. It is just reads, because the
|
||||||
|
// address collision is done before the transfer, and so no write
|
||||||
|
// are guaranteed to happen at this point.
|
||||||
|
func (ae *AccessEvents) ContractCreatePreCheckGas(addr common.Address) uint64 {
|
||||||
|
var gas uint64
|
||||||
|
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, false)
|
||||||
|
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, false)
|
||||||
return gas
|
return gas
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCreateInitGas returns the access gas costs for the initialization of
|
// ContractCreateInitGas returns the access gas costs for the initialization of
|
||||||
// a contract creation.
|
// a contract creation.
|
||||||
func (ae *AccessEvents) ContractCreateInitGas(addr common.Address, createSendsValue bool) uint64 {
|
func (ae *AccessEvents) ContractCreateInitGas(addr common.Address) uint64 {
|
||||||
var gas uint64
|
var gas uint64
|
||||||
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, true)
|
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, true)
|
||||||
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, true)
|
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, true)
|
||||||
if createSendsValue {
|
|
||||||
gas += ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, true)
|
|
||||||
}
|
|
||||||
return gas
|
return gas
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTxOrigin adds the member fields of the sender account to the access event list,
|
// AddTxOrigin adds the member fields of the sender account to the access event list,
|
||||||
// so that cold accesses are not charged, since they are covered by the 21000 gas.
|
// so that cold accesses are not charged, since they are covered by the 21000 gas.
|
||||||
func (ae *AccessEvents) AddTxOrigin(originAddr common.Address) {
|
func (ae *AccessEvents) AddTxOrigin(originAddr common.Address) {
|
||||||
ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.VersionLeafKey, false)
|
ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.BasicDataLeafKey, true)
|
||||||
ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.BalanceLeafKey, true)
|
ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.CodeHashLeafKey, false)
|
||||||
ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.NonceLeafKey, true)
|
|
||||||
ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.CodeKeccakLeafKey, false)
|
|
||||||
ae.touchAddressAndChargeGas(originAddr, zeroTreeIndex, utils.CodeSizeLeafKey, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTxDestination adds the member fields of the sender account to the access event list,
|
// AddTxDestination adds the member fields of the sender account to the access event list,
|
||||||
// so that cold accesses are not charged, since they are covered by the 21000 gas.
|
// so that cold accesses are not charged, since they are covered by the 21000 gas.
|
||||||
func (ae *AccessEvents) AddTxDestination(addr common.Address, sendsValue bool) {
|
func (ae *AccessEvents) AddTxDestination(addr common.Address, sendsValue bool) {
|
||||||
ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, false)
|
ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, sendsValue)
|
||||||
ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, sendsValue)
|
ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, false)
|
||||||
ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, false)
|
|
||||||
ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeKeccakLeafKey, false)
|
|
||||||
ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeSizeLeafKey, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SlotGas returns the amount of gas to be charged for a cold storage access.
|
// SlotGas returns the amount of gas to be charged for a cold storage access.
|
||||||
|
|
@ -275,39 +273,12 @@ func (ae *AccessEvents) CodeChunksRangeGas(contractAddr common.Address, startPC,
|
||||||
return statelessGasCharged
|
return statelessGasCharged
|
||||||
}
|
}
|
||||||
|
|
||||||
// VersionGas adds the account's version to the accessed data, and returns the
|
// BasicDataGas adds the account's basic data to the accessed data, and returns the
|
||||||
// amount of gas that it costs.
|
// amount of gas that it costs.
|
||||||
// Note that an access in write mode implies an access in read mode, whereas an
|
// Note that an access in write mode implies an access in read mode, whereas an
|
||||||
// access in read mode does not imply an access in write mode.
|
// access in read mode does not imply an access in write mode.
|
||||||
func (ae *AccessEvents) VersionGas(addr common.Address, isWrite bool) uint64 {
|
func (ae *AccessEvents) BasicDataGas(addr common.Address, isWrite bool) uint64 {
|
||||||
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, isWrite)
|
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, isWrite)
|
||||||
}
|
|
||||||
|
|
||||||
// BalanceGas adds the account's balance to the accessed data, and returns the
|
|
||||||
// amount of gas that it costs.
|
|
||||||
// in write mode. If false, the charged gas corresponds to an access in read mode.
|
|
||||||
// Note that an access in write mode implies an access in read mode, whereas an access in
|
|
||||||
// read mode does not imply an access in write mode.
|
|
||||||
func (ae *AccessEvents) BalanceGas(addr common.Address, isWrite bool) uint64 {
|
|
||||||
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, isWrite)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NonceGas adds the account's nonce to the accessed data, and returns the
|
|
||||||
// amount of gas that it costs.
|
|
||||||
// in write mode. If false, the charged gas corresponds to an access in read mode.
|
|
||||||
// Note that an access in write mode implies an access in read mode, whereas an access in
|
|
||||||
// read mode does not imply an access in write mode.
|
|
||||||
func (ae *AccessEvents) NonceGas(addr common.Address, isWrite bool) uint64 {
|
|
||||||
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, isWrite)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CodeSizeGas adds the account's code size to the accessed data, and returns the
|
|
||||||
// amount of gas that it costs.
|
|
||||||
// in write mode. If false, the charged gas corresponds to an access in read mode.
|
|
||||||
// Note that an access in write mode implies an access in read mode, whereas an access in
|
|
||||||
// read mode does not imply an access in write mode.
|
|
||||||
func (ae *AccessEvents) CodeSizeGas(addr common.Address, isWrite bool) uint64 {
|
|
||||||
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeSizeLeafKey, isWrite)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CodeHashGas adds the account's code hash to the accessed data, and returns the
|
// CodeHashGas adds the account's code hash to the accessed data, and returns the
|
||||||
|
|
@ -316,5 +287,5 @@ func (ae *AccessEvents) CodeSizeGas(addr common.Address, isWrite bool) uint64 {
|
||||||
// Note that an access in write mode implies an access in read mode, whereas an access in
|
// Note that an access in write mode implies an access in read mode, whereas an access in
|
||||||
// read mode does not imply an access in write mode.
|
// read mode does not imply an access in write mode.
|
||||||
func (ae *AccessEvents) CodeHashGas(addr common.Address, isWrite bool) uint64 {
|
func (ae *AccessEvents) CodeHashGas(addr common.Address, isWrite bool) uint64 {
|
||||||
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeKeccakLeafKey, isWrite)
|
return ae.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeHashLeafKey, isWrite)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,55 +40,43 @@ func TestAccountHeaderGas(t *testing.T) {
|
||||||
ae := NewAccessEvents(utils.NewPointCache(1024))
|
ae := NewAccessEvents(utils.NewPointCache(1024))
|
||||||
|
|
||||||
// Check cold read cost
|
// Check cold read cost
|
||||||
gas := ae.VersionGas(testAddr, false)
|
gas := ae.BasicDataGas(testAddr, false)
|
||||||
if want := params.WitnessBranchReadCost + params.WitnessChunkReadCost; gas != want {
|
if want := params.WitnessBranchReadCost + params.WitnessChunkReadCost; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check warm read cost
|
// Check warm read cost
|
||||||
gas = ae.VersionGas(testAddr, false)
|
gas = ae.BasicDataGas(testAddr, false)
|
||||||
if gas != 0 {
|
if gas != 0 {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check cold read costs in the same group no longer incur the branch read cost
|
// Check cold read costs in the same group no longer incur the branch read cost
|
||||||
gas = ae.BalanceGas(testAddr, false)
|
|
||||||
if gas != params.WitnessChunkReadCost {
|
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
|
|
||||||
}
|
|
||||||
gas = ae.NonceGas(testAddr, false)
|
|
||||||
if gas != params.WitnessChunkReadCost {
|
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
|
|
||||||
}
|
|
||||||
gas = ae.CodeSizeGas(testAddr, false)
|
|
||||||
if gas != params.WitnessChunkReadCost {
|
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
|
|
||||||
}
|
|
||||||
gas = ae.CodeHashGas(testAddr, false)
|
gas = ae.CodeHashGas(testAddr, false)
|
||||||
if gas != params.WitnessChunkReadCost {
|
if gas != params.WitnessChunkReadCost {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessChunkReadCost)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check cold write cost
|
// Check cold write cost
|
||||||
gas = ae.VersionGas(testAddr, true)
|
gas = ae.BasicDataGas(testAddr, true)
|
||||||
if want := params.WitnessBranchWriteCost + params.WitnessChunkWriteCost; gas != want {
|
if want := params.WitnessBranchWriteCost + params.WitnessChunkWriteCost; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check warm write cost
|
// Check warm write cost
|
||||||
gas = ae.VersionGas(testAddr, true)
|
gas = ae.BasicDataGas(testAddr, true)
|
||||||
if gas != 0 {
|
if gas != 0 {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check a write without a read charges both read and write costs
|
// Check a write without a read charges both read and write costs
|
||||||
gas = ae.BalanceGas(testAddr2, true)
|
gas = ae.BasicDataGas(testAddr2, true)
|
||||||
if want := params.WitnessBranchReadCost + params.WitnessBranchWriteCost + params.WitnessChunkWriteCost + params.WitnessChunkReadCost; gas != want {
|
if want := params.WitnessBranchReadCost + params.WitnessBranchWriteCost + params.WitnessChunkWriteCost + params.WitnessChunkReadCost; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that a write followed by a read charges nothing
|
// Check that a write followed by a read charges nothing
|
||||||
gas = ae.BalanceGas(testAddr2, false)
|
gas = ae.BasicDataGas(testAddr2, false)
|
||||||
if gas != 0 {
|
if gas != 0 {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
||||||
}
|
}
|
||||||
|
|
@ -112,13 +100,13 @@ func TestContractCreateInitGas(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check cold read cost, without a value
|
// Check cold read cost, without a value
|
||||||
gas := ae.ContractCreateInitGas(testAddr, false)
|
gas := ae.ContractCreateInitGas(testAddr)
|
||||||
if want := params.WitnessBranchWriteCost + params.WitnessBranchReadCost + params.WitnessChunkWriteCost*2 + params.WitnessChunkReadCost*2; gas != want {
|
if want := params.WitnessBranchWriteCost + params.WitnessBranchReadCost + 2*params.WitnessChunkWriteCost + 2*params.WitnessChunkReadCost; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check warm read cost
|
// Check warm read cost
|
||||||
gas = ae.ContractCreateInitGas(testAddr, false)
|
gas = ae.ContractCreateInitGas(testAddr)
|
||||||
if gas != 0 {
|
if gas != 0 {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
||||||
}
|
}
|
||||||
|
|
@ -131,17 +119,17 @@ func TestMessageCallGas(t *testing.T) {
|
||||||
|
|
||||||
// Check cold read cost, without a value
|
// Check cold read cost, without a value
|
||||||
gas := ae.MessageCallGas(testAddr)
|
gas := ae.MessageCallGas(testAddr)
|
||||||
if want := params.WitnessBranchReadCost + params.WitnessChunkReadCost*2; gas != want {
|
if want := params.WitnessBranchReadCost + params.WitnessChunkReadCost; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that reading the version and code size of the same account does not incur the branch read cost
|
// Check that reading the basic data and code hash of the same account does not incur the branch read cost
|
||||||
gas = ae.VersionGas(testAddr, false)
|
gas = ae.BasicDataGas(testAddr, false)
|
||||||
if gas != 0 {
|
if gas != 0 {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
||||||
}
|
}
|
||||||
gas = ae.CodeSizeGas(testAddr, false)
|
gas = ae.CodeHashGas(testAddr, false)
|
||||||
if gas != 0 {
|
if gas != params.WitnessChunkReadCost {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/lru"
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
|
@ -45,29 +46,29 @@ const (
|
||||||
|
|
||||||
// Database wraps access to tries and contract code.
|
// Database wraps access to tries and contract code.
|
||||||
type Database interface {
|
type Database interface {
|
||||||
|
// Reader returns a state reader associated with the specified state root.
|
||||||
|
Reader(root common.Hash) (Reader, error)
|
||||||
|
|
||||||
// OpenTrie opens the main account trie.
|
// OpenTrie opens the main account trie.
|
||||||
OpenTrie(root common.Hash) (Trie, error)
|
OpenTrie(root common.Hash) (Trie, error)
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error)
|
OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error)
|
||||||
|
|
||||||
// CopyTrie returns an independent copy of the given trie.
|
|
||||||
CopyTrie(Trie) Trie
|
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error)
|
ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error)
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error)
|
ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error)
|
||||||
|
|
||||||
// DiskDB returns the underlying key-value disk database.
|
|
||||||
DiskDB() ethdb.KeyValueStore
|
|
||||||
|
|
||||||
// PointCache returns the cache holding points used in verkle tree key computation
|
// PointCache returns the cache holding points used in verkle tree key computation
|
||||||
PointCache() *utils.PointCache
|
PointCache() *utils.PointCache
|
||||||
|
|
||||||
// TrieDB returns the underlying trie database for managing trie nodes.
|
// TrieDB returns the underlying trie database for managing trie nodes.
|
||||||
TrieDB() *triedb.Database
|
TrieDB() *triedb.Database
|
||||||
|
|
||||||
|
// Snapshot returns the underlying state snapshot.
|
||||||
|
Snapshot() *snapshot.Tree
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trie is a Ethereum Merkle Patricia trie.
|
// Trie is a Ethereum Merkle Patricia trie.
|
||||||
|
|
@ -94,7 +95,7 @@ type Trie interface {
|
||||||
// UpdateAccount abstracts an account write to the trie. It encodes the
|
// UpdateAccount abstracts an account write to the trie. It encodes the
|
||||||
// provided account object with associated algorithm and then updates it
|
// provided account object with associated algorithm and then updates it
|
||||||
// in the trie with provided address.
|
// in the trie with provided address.
|
||||||
UpdateAccount(address common.Address, account *types.StateAccount) error
|
UpdateAccount(address common.Address, account *types.StateAccount, codeLen int) error
|
||||||
|
|
||||||
// UpdateStorage associates key with value in the trie. If value has length zero,
|
// UpdateStorage associates key with value in the trie. If value has length zero,
|
||||||
// any existing value is deleted from the trie. The value bytes must not be modified
|
// any existing value is deleted from the trie. The value bytes must not be modified
|
||||||
|
|
@ -147,47 +148,62 @@ type Trie interface {
|
||||||
IsVerkle() bool
|
IsVerkle() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDatabase creates a backing store for state. The returned database is safe for
|
// CachingDB is an implementation of Database interface. It leverages both trie and
|
||||||
// concurrent use, but does not retain any recent trie nodes in memory. To keep some
|
// state snapshot to provide functionalities for state access. It's meant to be a
|
||||||
// historical state in memory, use the NewDatabaseWithConfig constructor.
|
// long-live object and has a few caches inside for sharing between blocks.
|
||||||
func NewDatabase(db ethdb.Database) Database {
|
type CachingDB struct {
|
||||||
return NewDatabaseWithConfig(db, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDatabaseWithConfig creates a backing store for state. The returned database
|
|
||||||
// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a
|
|
||||||
// large memory cache.
|
|
||||||
func NewDatabaseWithConfig(db ethdb.Database, config *triedb.Config) Database {
|
|
||||||
return &cachingDB{
|
|
||||||
disk: db,
|
|
||||||
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
|
|
||||||
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
|
|
||||||
triedb: triedb.NewDatabase(db, config),
|
|
||||||
pointCache: utils.NewPointCache(pointCacheSize),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDatabaseWithNodeDB creates a state database with an already initialized node database.
|
|
||||||
func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database {
|
|
||||||
return &cachingDB{
|
|
||||||
disk: db,
|
|
||||||
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
|
|
||||||
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
|
|
||||||
triedb: triedb,
|
|
||||||
pointCache: utils.NewPointCache(pointCacheSize),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type cachingDB struct {
|
|
||||||
disk ethdb.KeyValueStore
|
disk ethdb.KeyValueStore
|
||||||
codeSizeCache *lru.Cache[common.Hash, int]
|
|
||||||
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
|
|
||||||
triedb *triedb.Database
|
triedb *triedb.Database
|
||||||
|
snap *snapshot.Tree
|
||||||
|
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
|
||||||
|
codeSizeCache *lru.Cache[common.Hash, int]
|
||||||
pointCache *utils.PointCache
|
pointCache *utils.PointCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDatabase creates a state database with the provided data sources.
|
||||||
|
func NewDatabase(triedb *triedb.Database, snap *snapshot.Tree) *CachingDB {
|
||||||
|
return &CachingDB{
|
||||||
|
disk: triedb.Disk(),
|
||||||
|
triedb: triedb,
|
||||||
|
snap: snap,
|
||||||
|
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
|
||||||
|
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
|
||||||
|
pointCache: utils.NewPointCache(pointCacheSize),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDatabaseForTesting is similar to NewDatabase, but it initializes the caching
|
||||||
|
// db by using an ephemeral memory db with default config for testing.
|
||||||
|
func NewDatabaseForTesting() *CachingDB {
|
||||||
|
return NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader returns a state reader associated with the specified state root.
|
||||||
|
func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
|
||||||
|
var readers []Reader
|
||||||
|
|
||||||
|
// Set up the state snapshot reader if available. This feature
|
||||||
|
// is optional and may be partially useful if it's not fully
|
||||||
|
// generated.
|
||||||
|
if db.snap != nil {
|
||||||
|
sr, err := newStateReader(stateRoot, db.snap)
|
||||||
|
if err == nil {
|
||||||
|
readers = append(readers, sr) // snap reader is optional
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set up the trie reader, which is expected to always be available
|
||||||
|
// as the gatekeeper unless the state is corrupted.
|
||||||
|
tr, err := newTrieReader(stateRoot, db.triedb, db.pointCache)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
readers = append(readers, tr)
|
||||||
|
|
||||||
|
return newMultiReader(readers...)
|
||||||
|
}
|
||||||
|
|
||||||
// OpenTrie opens the main account trie at a specific root hash.
|
// OpenTrie opens the main account trie at a specific root hash.
|
||||||
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||||
if db.triedb.IsVerkle() {
|
if db.triedb.IsVerkle() {
|
||||||
return trie.NewVerkleTrie(root, db.triedb, db.pointCache)
|
return trie.NewVerkleTrie(root, db.triedb, db.pointCache)
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +216,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
|
func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
|
||||||
// In the verkle case, there is only one tree. But the two-tree structure
|
// In the verkle case, there is only one tree. But the two-tree structure
|
||||||
// is hardcoded in the codebase. So we need to return the same trie in this
|
// is hardcoded in the codebase. So we need to return the same trie in this
|
||||||
// case.
|
// case.
|
||||||
|
|
@ -215,20 +231,8 @@ func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre
|
||||||
return tr, nil
|
return tr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyTrie returns an independent copy of the given trie.
|
|
||||||
func (db *cachingDB) CopyTrie(t Trie) Trie {
|
|
||||||
switch t := t.(type) {
|
|
||||||
case *trie.StateTrie:
|
|
||||||
return t.Copy()
|
|
||||||
case *trie.VerkleTrie:
|
|
||||||
return t.Copy()
|
|
||||||
default:
|
|
||||||
panic(fmt.Errorf("unknown trie type %T", t))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) {
|
func (db *CachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) {
|
||||||
code, _ := db.codeCache.Get(codeHash)
|
code, _ := db.codeCache.Get(codeHash)
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
return code, nil
|
return code, nil
|
||||||
|
|
@ -249,7 +253,7 @@ func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash)
|
||||||
// ContractCodeWithPrefix retrieves a particular contract's code. If the
|
// ContractCodeWithPrefix retrieves a particular contract's code. If the
|
||||||
// code can't be found in the cache, then check the existence with **new**
|
// code can't be found in the cache, then check the existence with **new**
|
||||||
// db scheme.
|
// db scheme.
|
||||||
func (db *cachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) {
|
func (db *CachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) {
|
||||||
code, _ := db.codeCache.Get(codeHash)
|
code, _ := db.codeCache.Get(codeHash)
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
return code, nil
|
return code, nil
|
||||||
|
|
@ -268,7 +272,7 @@ func (db *cachingDB) ContractCodeWithPrefix(address common.Address, codeHash com
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
func (db *cachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
|
func (db *CachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
|
||||||
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
|
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
|
||||||
return cached, nil
|
return cached, nil
|
||||||
}
|
}
|
||||||
|
|
@ -276,17 +280,29 @@ func (db *cachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash)
|
||||||
return len(code), err
|
return len(code), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskDB returns the underlying key-value disk database.
|
|
||||||
func (db *cachingDB) DiskDB() ethdb.KeyValueStore {
|
|
||||||
return db.disk
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrieDB retrieves any intermediate trie-node caching layer.
|
// TrieDB retrieves any intermediate trie-node caching layer.
|
||||||
func (db *cachingDB) TrieDB() *triedb.Database {
|
func (db *CachingDB) TrieDB() *triedb.Database {
|
||||||
return db.triedb
|
return db.triedb
|
||||||
}
|
}
|
||||||
|
|
||||||
// PointCache returns the cache of evaluated curve points.
|
// PointCache returns the cache of evaluated curve points.
|
||||||
func (db *cachingDB) PointCache() *utils.PointCache {
|
func (db *CachingDB) PointCache() *utils.PointCache {
|
||||||
return db.pointCache
|
return db.pointCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Snapshot returns the underlying state snapshot.
|
||||||
|
func (db *CachingDB) Snapshot() *snapshot.Tree {
|
||||||
|
return db.snap
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustCopyTrie returns a deep-copied trie.
|
||||||
|
func mustCopyTrie(t Trie) Trie {
|
||||||
|
switch t := t.(type) {
|
||||||
|
case *trie.StateTrie:
|
||||||
|
return t.Copy()
|
||||||
|
case *trie.VerkleTrie:
|
||||||
|
return t.Copy()
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown trie type %T", t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func testNodeIteratorCoverage(t *testing.T, scheme string) {
|
||||||
db, sdb, ndb, root, _ := makeTestState(scheme)
|
db, sdb, ndb, root, _ := makeTestState(scheme)
|
||||||
ndb.Commit(root, false)
|
ndb.Commit(root, false)
|
||||||
|
|
||||||
state, err := New(root, sdb, nil)
|
state, err := New(root, sdb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create state trie at %x: %v", root, err)
|
t.Fatalf("failed to create state trie at %x: %v", root, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,21 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
|
"slices"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/blockstm"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type revision struct {
|
||||||
|
id int
|
||||||
|
journalIndex int
|
||||||
|
}
|
||||||
|
|
||||||
// journalEntry is a modification entry in the state change journal that can be
|
// journalEntry is a modification entry in the state change journal that can be
|
||||||
// reverted on demand.
|
// reverted on demand.
|
||||||
type journalEntry interface {
|
type journalEntry interface {
|
||||||
|
|
@ -43,6 +51,9 @@ type journalEntry interface {
|
||||||
type journal struct {
|
type journal struct {
|
||||||
entries []journalEntry // Current changes tracked by the journal
|
entries []journalEntry // Current changes tracked by the journal
|
||||||
dirties map[common.Address]int // Dirty accounts and the number of changes
|
dirties map[common.Address]int // Dirty accounts and the number of changes
|
||||||
|
|
||||||
|
validRevisions []revision
|
||||||
|
nextRevisionId int
|
||||||
}
|
}
|
||||||
|
|
||||||
// newJournal creates a new initialized journal.
|
// newJournal creates a new initialized journal.
|
||||||
|
|
@ -52,6 +63,40 @@ func newJournal() *journal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset clears the journal, after this operation the journal can be used anew.
|
||||||
|
// It is semantically similar to calling 'newJournal', but the underlying slices
|
||||||
|
// can be reused.
|
||||||
|
func (j *journal) reset() {
|
||||||
|
j.entries = j.entries[:0]
|
||||||
|
j.validRevisions = j.validRevisions[:0]
|
||||||
|
clear(j.dirties)
|
||||||
|
j.nextRevisionId = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// snapshot returns an identifier for the current revision of the state.
|
||||||
|
func (j *journal) snapshot() int {
|
||||||
|
id := j.nextRevisionId
|
||||||
|
j.nextRevisionId++
|
||||||
|
j.validRevisions = append(j.validRevisions, revision{id, j.length()})
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
// revertToSnapshot reverts all state changes made since the given revision.
|
||||||
|
func (j *journal) revertToSnapshot(revid int, s *StateDB) {
|
||||||
|
// Find the snapshot in the stack of valid snapshots.
|
||||||
|
idx := sort.Search(len(j.validRevisions), func(i int) bool {
|
||||||
|
return j.validRevisions[i].id >= revid
|
||||||
|
})
|
||||||
|
if idx == len(j.validRevisions) || j.validRevisions[idx].id != revid {
|
||||||
|
panic(fmt.Errorf("revision id %v cannot be reverted", revid))
|
||||||
|
}
|
||||||
|
snapshot := j.validRevisions[idx].journalIndex
|
||||||
|
|
||||||
|
// Replay the journal to undo changes and remove invalidated snapshots
|
||||||
|
j.revert(s, snapshot)
|
||||||
|
j.validRevisions = j.validRevisions[:idx]
|
||||||
|
}
|
||||||
|
|
||||||
// append inserts a new modification entry to the end of the change journal.
|
// append inserts a new modification entry to the end of the change journal.
|
||||||
func (j *journal) append(entry journalEntry) {
|
func (j *journal) append(entry journalEntry) {
|
||||||
j.entries = append(j.entries, entry)
|
j.entries = append(j.entries, entry)
|
||||||
|
|
@ -99,46 +144,120 @@ func (j *journal) copy() *journal {
|
||||||
return &journal{
|
return &journal{
|
||||||
entries: entries,
|
entries: entries,
|
||||||
dirties: maps.Clone(j.dirties),
|
dirties: maps.Clone(j.dirties),
|
||||||
|
validRevisions: slices.Clone(j.validRevisions),
|
||||||
|
nextRevisionId: j.nextRevisionId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *journal) logChange(txHash common.Hash) {
|
||||||
|
j.append(addLogChange{txhash: txHash})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) createObject(addr common.Address) {
|
||||||
|
j.append(createObjectChange{account: addr})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) createContract(addr common.Address) {
|
||||||
|
j.append(createContractChange{account: addr})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) destruct(addr common.Address) {
|
||||||
|
j.append(selfDestructChange{account: addr})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) storageChange(addr common.Address, key, prev, origin common.Hash) {
|
||||||
|
j.append(storageChange{
|
||||||
|
account: addr,
|
||||||
|
key: key,
|
||||||
|
prevvalue: prev,
|
||||||
|
origvalue: origin,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) transientStateChange(addr common.Address, key, prev common.Hash) {
|
||||||
|
j.append(transientStorageChange{
|
||||||
|
account: addr,
|
||||||
|
key: key,
|
||||||
|
prevalue: prev,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) refundChange(previous uint64) {
|
||||||
|
j.append(refundChange{prev: previous})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) balanceChange(addr common.Address, previous *uint256.Int) {
|
||||||
|
j.append(balanceChange{
|
||||||
|
account: addr,
|
||||||
|
prev: previous.Clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) setCode(address common.Address) {
|
||||||
|
j.append(codeChange{account: address})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) nonceChange(address common.Address, prev uint64) {
|
||||||
|
j.append(nonceChange{
|
||||||
|
account: address,
|
||||||
|
prev: prev,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) touchChange(address common.Address) {
|
||||||
|
j.append(touchChange{
|
||||||
|
account: address,
|
||||||
|
})
|
||||||
|
if address == ripemd {
|
||||||
|
// Explicitly put it in the dirty-cache, which is otherwise generated from
|
||||||
|
// flattened journals.
|
||||||
|
j.dirty(address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) accessListAddAccount(addr common.Address) {
|
||||||
|
j.append(accessListAddAccountChange{addr})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *journal) accessListAddSlot(addr common.Address, slot common.Hash) {
|
||||||
|
j.append(accessListAddSlotChange{
|
||||||
|
address: addr,
|
||||||
|
slot: slot,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Changes to the account trie.
|
// Changes to the account trie.
|
||||||
createObjectChange struct {
|
createObjectChange struct {
|
||||||
account *common.Address
|
account common.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// createContractChange represents an account becoming a contract-account.
|
// createContractChange represents an account becoming a contract-account.
|
||||||
// This event happens prior to executing initcode. The journal-event simply
|
// This event happens prior to executing initcode. The journal-event simply
|
||||||
// manages the created-flag, in order to allow same-tx destruction.
|
// manages the created-flag, in order to allow same-tx destruction.
|
||||||
createContractChange struct {
|
createContractChange struct {
|
||||||
account common.Address
|
account common.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
selfDestructChange struct {
|
selfDestructChange struct {
|
||||||
account *common.Address
|
account common.Address
|
||||||
prev bool // whether account had already self-destructed
|
|
||||||
prevbalance *uint256.Int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes to individual accounts.
|
// Changes to individual accounts.
|
||||||
balanceChange struct {
|
balanceChange struct {
|
||||||
account *common.Address
|
account common.Address
|
||||||
prev *uint256.Int
|
prev *uint256.Int
|
||||||
}
|
}
|
||||||
nonceChange struct {
|
nonceChange struct {
|
||||||
account *common.Address
|
account common.Address
|
||||||
prev uint64
|
prev uint64
|
||||||
}
|
}
|
||||||
storageChange struct {
|
storageChange struct {
|
||||||
account *common.Address
|
account common.Address
|
||||||
key common.Hash
|
key common.Hash
|
||||||
prevvalue common.Hash
|
prevvalue common.Hash
|
||||||
origvalue common.Hash
|
origvalue common.Hash
|
||||||
}
|
}
|
||||||
codeChange struct {
|
codeChange struct {
|
||||||
account *common.Address
|
account common.Address
|
||||||
prevcode, prevhash []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes to other state values.
|
// Changes to other state values.
|
||||||
|
|
@ -148,36 +267,32 @@ type (
|
||||||
addLogChange struct {
|
addLogChange struct {
|
||||||
txhash common.Hash
|
txhash common.Hash
|
||||||
}
|
}
|
||||||
addPreimageChange struct {
|
|
||||||
hash common.Hash
|
|
||||||
}
|
|
||||||
touchChange struct {
|
touchChange struct {
|
||||||
account *common.Address
|
account common.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes to the access list
|
// Changes to the access list
|
||||||
accessListAddAccountChange struct {
|
accessListAddAccountChange struct {
|
||||||
address *common.Address
|
address common.Address
|
||||||
}
|
}
|
||||||
accessListAddSlotChange struct {
|
accessListAddSlotChange struct {
|
||||||
address *common.Address
|
address common.Address
|
||||||
slot *common.Hash
|
slot common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes to transient storage
|
// Changes to transient storage
|
||||||
transientStorageChange struct {
|
transientStorageChange struct {
|
||||||
account *common.Address
|
account common.Address
|
||||||
key, prevalue common.Hash
|
key, prevalue common.Hash
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ch createObjectChange) revert(s *StateDB) {
|
func (ch createObjectChange) revert(s *StateDB) {
|
||||||
delete(s.stateObjects, *ch.account)
|
delete(s.stateObjects, ch.account)
|
||||||
RevertWrite(s, blockstm.NewAddressKey(*ch.account))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch createObjectChange) dirtied() *common.Address {
|
func (ch createObjectChange) dirtied() *common.Address {
|
||||||
return ch.account
|
return &ch.account
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch createObjectChange) copy() journalEntry {
|
func (ch createObjectChange) copy() journalEntry {
|
||||||
|
|
@ -201,23 +316,19 @@ func (ch createContractChange) copy() journalEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch selfDestructChange) revert(s *StateDB) {
|
func (ch selfDestructChange) revert(s *StateDB) {
|
||||||
obj := s.getStateObject(*ch.account)
|
obj := s.getStateObject(ch.account)
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
obj.selfDestructed = ch.prev
|
obj.selfDestructed = false
|
||||||
obj.setBalance(ch.prevbalance)
|
|
||||||
RevertWrite(s, blockstm.NewSubpathKey(*ch.account, SuicidePath))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch selfDestructChange) dirtied() *common.Address {
|
func (ch selfDestructChange) dirtied() *common.Address {
|
||||||
return ch.account
|
return &ch.account
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch selfDestructChange) copy() journalEntry {
|
func (ch selfDestructChange) copy() journalEntry {
|
||||||
return selfDestructChange{
|
return selfDestructChange{
|
||||||
account: ch.account,
|
account: ch.account,
|
||||||
prev: ch.prev,
|
|
||||||
prevbalance: new(uint256.Int).Set(ch.prevbalance),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,7 +338,7 @@ func (ch touchChange) revert(s *StateDB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch touchChange) dirtied() *common.Address {
|
func (ch touchChange) dirtied() *common.Address {
|
||||||
return ch.account
|
return &ch.account
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch touchChange) copy() journalEntry {
|
func (ch touchChange) copy() journalEntry {
|
||||||
|
|
@ -237,11 +348,11 @@ func (ch touchChange) copy() journalEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch balanceChange) revert(s *StateDB) {
|
func (ch balanceChange) revert(s *StateDB) {
|
||||||
s.getStateObject(*ch.account).setBalance(ch.prev)
|
s.getStateObject(ch.account).setBalance(ch.prev)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch balanceChange) dirtied() *common.Address {
|
func (ch balanceChange) dirtied() *common.Address {
|
||||||
return ch.account
|
return &ch.account
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch balanceChange) copy() journalEntry {
|
func (ch balanceChange) copy() journalEntry {
|
||||||
|
|
@ -252,11 +363,11 @@ func (ch balanceChange) copy() journalEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch nonceChange) revert(s *StateDB) {
|
func (ch nonceChange) revert(s *StateDB) {
|
||||||
s.getStateObject(*ch.account).setNonce(ch.prev)
|
s.getStateObject(ch.account).setNonce(ch.prev)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch nonceChange) dirtied() *common.Address {
|
func (ch nonceChange) dirtied() *common.Address {
|
||||||
return ch.account
|
return &ch.account
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch nonceChange) copy() journalEntry {
|
func (ch nonceChange) copy() journalEntry {
|
||||||
|
|
@ -267,29 +378,23 @@ func (ch nonceChange) copy() journalEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch codeChange) revert(s *StateDB) {
|
func (ch codeChange) revert(s *StateDB) {
|
||||||
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
|
s.getStateObject(ch.account).setCode(types.EmptyCodeHash, nil)
|
||||||
RevertWrite(s, blockstm.NewSubpathKey(*ch.account, CodePath))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch codeChange) dirtied() *common.Address {
|
func (ch codeChange) dirtied() *common.Address {
|
||||||
return ch.account
|
return &ch.account
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch codeChange) copy() journalEntry {
|
func (ch codeChange) copy() journalEntry {
|
||||||
return codeChange{
|
return codeChange{account: ch.account}
|
||||||
account: ch.account,
|
|
||||||
prevhash: common.CopyBytes(ch.prevhash),
|
|
||||||
prevcode: common.CopyBytes(ch.prevcode),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch storageChange) revert(s *StateDB) {
|
func (ch storageChange) revert(s *StateDB) {
|
||||||
s.getStateObject(*ch.account).setState(ch.key, ch.prevvalue, ch.origvalue)
|
s.getStateObject(ch.account).setState(ch.key, ch.prevvalue, ch.origvalue)
|
||||||
RevertWrite(s, blockstm.NewStateKey(*ch.account, ch.key))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch storageChange) dirtied() *common.Address {
|
func (ch storageChange) dirtied() *common.Address {
|
||||||
return ch.account
|
return &ch.account
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch storageChange) copy() journalEntry {
|
func (ch storageChange) copy() journalEntry {
|
||||||
|
|
@ -301,7 +406,7 @@ func (ch storageChange) copy() journalEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch transientStorageChange) revert(s *StateDB) {
|
func (ch transientStorageChange) revert(s *StateDB) {
|
||||||
s.setTransientState(*ch.account, ch.key, ch.prevalue)
|
s.setTransientState(ch.account, ch.key, ch.prevalue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch transientStorageChange) dirtied() *common.Address {
|
func (ch transientStorageChange) dirtied() *common.Address {
|
||||||
|
|
@ -351,20 +456,6 @@ func (ch addLogChange) copy() journalEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch addPreimageChange) revert(s *StateDB) {
|
|
||||||
delete(s.preimages, ch.hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ch addPreimageChange) dirtied() *common.Address {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ch addPreimageChange) copy() journalEntry {
|
|
||||||
return addPreimageChange{
|
|
||||||
hash: ch.hash,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ch accessListAddAccountChange) revert(s *StateDB) {
|
func (ch accessListAddAccountChange) revert(s *StateDB) {
|
||||||
/*
|
/*
|
||||||
One important invariant here, is that whenever a (addr, slot) is added, if the
|
One important invariant here, is that whenever a (addr, slot) is added, if the
|
||||||
|
|
@ -375,7 +466,7 @@ func (ch accessListAddAccountChange) revert(s *StateDB) {
|
||||||
(addr) at this point, since no storage adds can remain when come upon
|
(addr) at this point, since no storage adds can remain when come upon
|
||||||
a single (addr) change.
|
a single (addr) change.
|
||||||
*/
|
*/
|
||||||
s.accessList.DeleteAddress(*ch.address)
|
s.accessList.DeleteAddress(ch.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch accessListAddAccountChange) dirtied() *common.Address {
|
func (ch accessListAddAccountChange) dirtied() *common.Address {
|
||||||
|
|
@ -389,7 +480,7 @@ func (ch accessListAddAccountChange) copy() journalEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch accessListAddSlotChange) revert(s *StateDB) {
|
func (ch accessListAddSlotChange) revert(s *StateDB) {
|
||||||
s.accessList.DeleteSlot(*ch.address, *ch.slot)
|
s.accessList.DeleteSlot(ch.address, ch.slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch accessListAddSlotChange) dirtied() *common.Address {
|
func (ch accessListAddSlotChange) dirtied() *common.Address {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ package state
|
||||||
import "github.com/ethereum/go-ethereum/metrics"
|
import "github.com/ethereum/go-ethereum/metrics"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
accountReadMeters = metrics.NewRegisteredMeter("state/read/accounts", nil)
|
||||||
|
storageReadMeters = metrics.NewRegisteredMeter("state/read/storage", nil)
|
||||||
accountUpdatedMeter = metrics.NewRegisteredMeter("state/update/account", nil)
|
accountUpdatedMeter = metrics.NewRegisteredMeter("state/update/account", nil)
|
||||||
storageUpdatedMeter = metrics.NewRegisteredMeter("state/update/storage", nil)
|
storageUpdatedMeter = metrics.NewRegisteredMeter("state/update/storage", nil)
|
||||||
accountDeletedMeter = metrics.NewRegisteredMeter("state/delete/account", nil)
|
accountDeletedMeter = metrics.NewRegisteredMeter("state/delete/account", nil)
|
||||||
|
|
|
||||||
|
|
@ -274,11 +274,10 @@ func (p *Pruner) Prune(root common.Hash) error {
|
||||||
// is the presence of root can indicate the presence of the
|
// is the presence of root can indicate the presence of the
|
||||||
// entire trie.
|
// entire trie.
|
||||||
if !rawdb.HasLegacyTrieNode(p.db, root) {
|
if !rawdb.HasLegacyTrieNode(p.db, root) {
|
||||||
// The special case is for clique based networks(goerli
|
// The special case is for clique based networks, it's possible
|
||||||
// and some other private networks), it's possible that two
|
// that two consecutive blocks will have same root. In this case
|
||||||
// consecutive blocks will have same root. In this case snapshot
|
// snapshot difflayer won't be created. So HEAD-127 may not paired
|
||||||
// difflayer won't be created. So HEAD-127 may not paired with
|
// with head-127 layer. Instead the paired layer is higher than the
|
||||||
// head-127 layer. Instead the paired layer is higher than the
|
|
||||||
// bottom-most diff layer. Try to find the bottom-most snapshot
|
// bottom-most diff layer. Try to find the bottom-most snapshot
|
||||||
// layer with state available.
|
// layer with state available.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
321
core/state/reader.go
Normal file
321
core/state/reader.go
Normal file
|
|
@ -0,0 +1,321 @@
|
||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"maps"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/ethereum/go-ethereum/trie/utils"
|
||||||
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reader defines the interface for accessing accounts and storage slots
|
||||||
|
// associated with a specific state.
|
||||||
|
type Reader interface {
|
||||||
|
// Account retrieves the account associated with a particular address.
|
||||||
|
//
|
||||||
|
// - Returns a nil account if it does not exist
|
||||||
|
// - Returns an error only if an unexpected issue occurs
|
||||||
|
// - The returned account is safe to modify after the call
|
||||||
|
Account(addr common.Address) (*types.StateAccount, error)
|
||||||
|
|
||||||
|
// Storage retrieves the storage slot associated with a particular account
|
||||||
|
// address and slot key.
|
||||||
|
//
|
||||||
|
// - Returns an empty slot if it does not exist
|
||||||
|
// - Returns an error only if an unexpected issue occurs
|
||||||
|
// - The returned storage slot is safe to modify after the call
|
||||||
|
Storage(addr common.Address, slot common.Hash) (common.Hash, error)
|
||||||
|
|
||||||
|
// Copy returns a deep-copied state reader.
|
||||||
|
Copy() Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// stateReader is a wrapper over the state snapshot and implements the Reader
|
||||||
|
// interface. It provides an efficient way to access flat state.
|
||||||
|
type stateReader struct {
|
||||||
|
snap snapshot.Snapshot
|
||||||
|
buff crypto.KeccakState
|
||||||
|
}
|
||||||
|
|
||||||
|
// newStateReader constructs a flat state reader with on the specified state root.
|
||||||
|
func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error) {
|
||||||
|
snap := snaps.Snapshot(root)
|
||||||
|
if snap == nil {
|
||||||
|
return nil, errors.New("snapshot is not available")
|
||||||
|
}
|
||||||
|
return &stateReader{
|
||||||
|
snap: snap,
|
||||||
|
buff: crypto.NewKeccakState(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account implements Reader, retrieving the account specified by the address.
|
||||||
|
//
|
||||||
|
// An error will be returned if the associated snapshot is already stale or
|
||||||
|
// the requested account is not yet covered by the snapshot.
|
||||||
|
//
|
||||||
|
// The returned account might be nil if it's not existent.
|
||||||
|
func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
ret, err := r.snap.Account(crypto.HashData(crypto.NewKeccakState(), addr.Bytes()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ret == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
acct := &types.StateAccount{
|
||||||
|
Nonce: ret.Nonce,
|
||||||
|
Balance: ret.Balance,
|
||||||
|
CodeHash: ret.CodeHash,
|
||||||
|
Root: common.BytesToHash(ret.Root),
|
||||||
|
}
|
||||||
|
if len(acct.CodeHash) == 0 {
|
||||||
|
acct.CodeHash = types.EmptyCodeHash.Bytes()
|
||||||
|
}
|
||||||
|
if acct.Root == (common.Hash{}) {
|
||||||
|
acct.Root = types.EmptyRootHash
|
||||||
|
}
|
||||||
|
return acct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implements Reader, retrieving the storage slot specified by the
|
||||||
|
// address and slot key.
|
||||||
|
//
|
||||||
|
// An error will be returned if the associated snapshot is already stale or
|
||||||
|
// the requested storage slot is not yet covered by the snapshot.
|
||||||
|
//
|
||||||
|
// The returned storage slot might be empty if it's not existent.
|
||||||
|
func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
||||||
|
addrHash := crypto.HashData(crypto.NewKeccakState(), addr.Bytes())
|
||||||
|
slotHash := crypto.HashData(crypto.NewKeccakState(), key.Bytes())
|
||||||
|
ret, err := r.snap.Storage(addrHash, slotHash)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
if len(ret) == 0 {
|
||||||
|
return common.Hash{}, nil
|
||||||
|
}
|
||||||
|
// Perform the rlp-decode as the slot value is RLP-encoded in the state
|
||||||
|
// snapshot.
|
||||||
|
_, content, _, err := rlp.Split(ret)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
var value common.Hash
|
||||||
|
value.SetBytes(content)
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy implements Reader, returning a deep-copied snap reader.
|
||||||
|
func (r *stateReader) Copy() Reader {
|
||||||
|
return &stateReader{
|
||||||
|
snap: r.snap,
|
||||||
|
buff: crypto.NewKeccakState(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trieReader implements the Reader interface, providing functions to access
|
||||||
|
// state from the referenced trie.
|
||||||
|
type trieReader struct {
|
||||||
|
root common.Hash // State root which uniquely represent a state
|
||||||
|
db *triedb.Database // Database for loading trie
|
||||||
|
buff crypto.KeccakState // Buffer for keccak256 hashing
|
||||||
|
mainTrie Trie // Main trie, resolved in constructor
|
||||||
|
subRoots map[common.Address]common.Hash // Set of storage roots, cached when the account is resolved
|
||||||
|
subTries map[common.Address]Trie // Group of storage tries, cached when it's resolved
|
||||||
|
muSubRoot sync.Mutex
|
||||||
|
muSubTries sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// trieReader constructs a trie reader of the specific state. An error will be
|
||||||
|
// returned if the associated trie specified by root is not existent.
|
||||||
|
func newTrieReader(root common.Hash, db *triedb.Database, cache *utils.PointCache) (*trieReader, error) {
|
||||||
|
var (
|
||||||
|
tr Trie
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if !db.IsVerkle() {
|
||||||
|
tr, err = trie.NewStateTrie(trie.StateTrieID(root), db)
|
||||||
|
} else {
|
||||||
|
tr, err = trie.NewVerkleTrie(root, db, cache)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &trieReader{
|
||||||
|
root: root,
|
||||||
|
db: db,
|
||||||
|
buff: crypto.NewKeccakState(),
|
||||||
|
mainTrie: tr,
|
||||||
|
subRoots: make(map[common.Address]common.Hash),
|
||||||
|
subTries: make(map[common.Address]Trie),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account implements Reader, retrieving the account specified by the address.
|
||||||
|
//
|
||||||
|
// An error will be returned if the trie state is corrupted. An nil account
|
||||||
|
// will be returned if it's not existent in the trie.
|
||||||
|
func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
account, err := r.mainTrie.GetAccount(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r.muSubRoot.Lock()
|
||||||
|
if account == nil {
|
||||||
|
r.subRoots[addr] = types.EmptyRootHash
|
||||||
|
} else {
|
||||||
|
r.subRoots[addr] = account.Root
|
||||||
|
}
|
||||||
|
r.muSubRoot.Unlock()
|
||||||
|
|
||||||
|
return account, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implements Reader, retrieving the storage slot specified by the
|
||||||
|
// address and slot key.
|
||||||
|
//
|
||||||
|
// An error will be returned if the trie state is corrupted. An empty storage
|
||||||
|
// slot will be returned if it's not existent in the trie.
|
||||||
|
func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
||||||
|
var (
|
||||||
|
tr Trie
|
||||||
|
found bool
|
||||||
|
value common.Hash
|
||||||
|
)
|
||||||
|
if r.db.IsVerkle() {
|
||||||
|
tr = r.mainTrie
|
||||||
|
} else {
|
||||||
|
tr, found = r.subTries[addr]
|
||||||
|
if !found {
|
||||||
|
root, ok := r.subRoots[addr]
|
||||||
|
|
||||||
|
// The storage slot is accessed without account caching. It's unexpected
|
||||||
|
// behavior but try to resolve the account first anyway.
|
||||||
|
if !ok {
|
||||||
|
_, err := r.Account(addr)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
root = r.subRoots[addr]
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
tr, err = trie.NewStateTrie(trie.StorageTrieID(r.root, crypto.HashData(crypto.NewKeccakState(), addr.Bytes()), root), r.db)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
r.muSubTries.Lock()
|
||||||
|
r.subTries[addr] = tr
|
||||||
|
r.muSubTries.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret, err := tr.GetStorage(addr, key.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
value.SetBytes(ret)
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy implements Reader, returning a deep-copied trie reader.
|
||||||
|
func (r *trieReader) Copy() Reader {
|
||||||
|
tries := make(map[common.Address]Trie)
|
||||||
|
for addr, tr := range r.subTries {
|
||||||
|
tries[addr] = mustCopyTrie(tr)
|
||||||
|
}
|
||||||
|
return &trieReader{
|
||||||
|
root: r.root,
|
||||||
|
db: r.db,
|
||||||
|
buff: crypto.NewKeccakState(),
|
||||||
|
mainTrie: mustCopyTrie(r.mainTrie),
|
||||||
|
subRoots: maps.Clone(r.subRoots),
|
||||||
|
subTries: tries,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiReader is the aggregation of a list of Reader interface, providing state
|
||||||
|
// access by leveraging all readers. The checking priority is determined by the
|
||||||
|
// position in the reader list.
|
||||||
|
type multiReader struct {
|
||||||
|
readers []Reader // List of readers, sorted by checking priority
|
||||||
|
}
|
||||||
|
|
||||||
|
// newMultiReader constructs a multiReader instance with the given readers. The
|
||||||
|
// priority among readers is assumed to be sorted. Note, it must contain at least
|
||||||
|
// one reader for constructing a multiReader.
|
||||||
|
func newMultiReader(readers ...Reader) (*multiReader, error) {
|
||||||
|
if len(readers) == 0 {
|
||||||
|
return nil, errors.New("empty reader set")
|
||||||
|
}
|
||||||
|
return &multiReader{
|
||||||
|
readers: readers,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account implementing Reader interface, retrieving the account associated with
|
||||||
|
// a particular address.
|
||||||
|
//
|
||||||
|
// - Returns a nil account if it does not exist
|
||||||
|
// - Returns an error only if an unexpected issue occurs
|
||||||
|
// - The returned account is safe to modify after the call
|
||||||
|
func (r *multiReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
var errs []error
|
||||||
|
for _, reader := range r.readers {
|
||||||
|
acct, err := reader.Account(addr)
|
||||||
|
if err == nil {
|
||||||
|
return acct, nil
|
||||||
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
return nil, errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implementing Reader interface, retrieving the storage slot associated
|
||||||
|
// with a particular account address and slot key.
|
||||||
|
//
|
||||||
|
// - Returns an empty slot if it does not exist
|
||||||
|
// - Returns an error only if an unexpected issue occurs
|
||||||
|
// - The returned storage slot is safe to modify after the call
|
||||||
|
func (r *multiReader) Storage(addr common.Address, slot common.Hash) (common.Hash, error) {
|
||||||
|
var errs []error
|
||||||
|
for _, reader := range r.readers {
|
||||||
|
slot, err := reader.Storage(addr, slot)
|
||||||
|
if err == nil {
|
||||||
|
return slot, nil
|
||||||
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
return common.Hash{}, errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy implementing Reader interface, returning a deep-copied state reader.
|
||||||
|
func (r *multiReader) Copy() Reader {
|
||||||
|
var readers []Reader
|
||||||
|
for _, reader := range r.readers {
|
||||||
|
readers = append(readers, reader.Copy())
|
||||||
|
}
|
||||||
|
return &multiReader{readers: readers}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue