mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
Merge branch 'develop' of github.com:maticnetwork/bor into block-commit-stats
This commit is contained in:
commit
abed2a501a
89 changed files with 2894 additions and 913 deletions
23
.github/CODEOWNERS
vendored
23
.github/CODEOWNERS
vendored
|
|
@ -1,23 +0,0 @@
|
|||
# Lines starting with '#' are comments.
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
|
||||
accounts/usbwallet @karalabe
|
||||
accounts/scwallet @gballet
|
||||
accounts/abi @gballet @MariusVanDerWijden
|
||||
cmd/clef @holiman
|
||||
cmd/puppeth @karalabe
|
||||
consensus @karalabe
|
||||
core/ @karalabe @holiman @rjl493456442
|
||||
eth/ @karalabe @holiman @rjl493456442
|
||||
eth/catalyst/ @gballet
|
||||
graphql/ @gballet
|
||||
les/ @zsfelfoldi @rjl493456442
|
||||
light/ @zsfelfoldi @rjl493456442
|
||||
mobile/ @karalabe @ligi
|
||||
node/ @fjl @renaynay
|
||||
p2p/ @fjl @zsfelfoldi
|
||||
rpc/ @fjl @holiman
|
||||
p2p/simulations @fjl
|
||||
p2p/protocols @fjl
|
||||
p2p/testing @fjl
|
||||
signer/ @holiman
|
||||
4
.github/matic-cli-config.yml
vendored
4
.github/matic-cli-config.yml
vendored
|
|
@ -3,9 +3,13 @@ defaultFee: 2000
|
|||
borChainId: "15001"
|
||||
heimdallChainId: heimdall-15001
|
||||
contractsBranch: jc/v0.3.1-backport
|
||||
sprintSize: 64
|
||||
blockNumber: '0'
|
||||
blockTime: '2'
|
||||
numOfValidators: 3
|
||||
numOfNonValidators: 0
|
||||
ethURL: http://ganache:9545
|
||||
ethHostUser: ubuntu
|
||||
devnetType: docker
|
||||
borDockerBuildContext: "../../bor"
|
||||
heimdallDockerBuildContext: "https://github.com/maticnetwork/heimdall.git#develop"
|
||||
|
|
|
|||
44
.github/pull_request_template.md
vendored
Normal file
44
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Description
|
||||
|
||||
Please provide a detailed description of what was done in this PR
|
||||
|
||||
# Changes
|
||||
|
||||
- [ ] Bugfix (non-breaking change that solves an issue)
|
||||
- [ ] Hotfix (change that solves an urgent issue, and requires immediate attention)
|
||||
- [ ] New feature (non-breaking change that adds functionality)
|
||||
- [ ] Breaking change (change that is not backwards-compatible and/or changes current functionality)
|
||||
|
||||
# Breaking changes
|
||||
|
||||
Please complete this section if any breaking changes have been made, otherwise delete it
|
||||
|
||||
# Checklist
|
||||
|
||||
- [ ] I have added at least 2 reviewer or the whole pos-v1 team
|
||||
- [ ] I have added sufficient documentation in code
|
||||
- [ ] I will be resolving comments - if any - by pushing each fix in a separate commit and linking the commit hash in the comment reply
|
||||
|
||||
# Cross repository changes
|
||||
|
||||
- [ ] This PR requires changes to heimdall
|
||||
- In case link the PR here:
|
||||
- [ ] This PR requires changes to matic-cli
|
||||
- In case link the PR here:
|
||||
|
||||
## Testing
|
||||
|
||||
- [ ] I have added unit tests
|
||||
- [ ] I have added tests to CI
|
||||
- [ ] 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 mumbai
|
||||
- [ ] I have created new e2e tests into express-cli
|
||||
|
||||
### Manual tests
|
||||
|
||||
Please complete this section with the steps you performed if you ran manual tests for this functionality, otherwise delete it
|
||||
|
||||
# Additional comments
|
||||
|
||||
Please post additional comments in this section if you have them, otherwise delete it
|
||||
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
|
|
@ -104,7 +104,7 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: maticnetwork/matic-cli
|
||||
ref: v0.3.0-dev
|
||||
ref: arpit/pos-655-2
|
||||
path: matic-cli
|
||||
|
||||
- name: Install dependencies on Linux
|
||||
|
|
@ -142,11 +142,11 @@ jobs:
|
|||
bash docker-heimdall-start-all.sh
|
||||
bash docker-bor-setup.sh
|
||||
bash docker-bor-start-all.sh
|
||||
sleep 120 && bash ganache-deployment-bor.sh
|
||||
sleep 120 && bash ganache-deployment-sync.sh
|
||||
sleep 120
|
||||
docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'admin.peers'"
|
||||
docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'eth.blockNumber'"
|
||||
cd -
|
||||
timeout 2m bash bor/integration-tests/bor_health.sh
|
||||
cd -
|
||||
bash ganache-deployment-bor.sh
|
||||
bash ganache-deployment-sync.sh
|
||||
|
||||
- name: Run smoke tests
|
||||
run: |
|
||||
|
|
@ -154,7 +154,7 @@ jobs:
|
|||
cd matic-cli/devnet/code/contracts
|
||||
npm run truffle exec scripts/deposit.js -- --network development $(jq -r .root.tokens.MaticToken contractAddresses.json) 100000000000000000000
|
||||
cd -
|
||||
bash bor/integration-tests/smoke_test.sh
|
||||
timeout 20m bash bor/integration-tests/smoke_test.sh
|
||||
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
|
|
|
|||
64
.github/workflows/security-ci.yml
vendored
Normal file
64
.github/workflows/security-ci.yml
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
name: Security CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
snyk:
|
||||
name: Snyk and Publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@master
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
uses: snyk/actions/golang@master
|
||||
continue-on-error: true
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
args: --org=${{ secrets.SNYK_ORG }} --severity-threshold=medium --sarif-file-output=snyk.sarif
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: snyk.sarif
|
||||
|
||||
snyk-code:
|
||||
name: Snyk Code and Publish
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@master
|
||||
- name: Run Snyk SAST to check for code vulnerabilities
|
||||
uses: snyk/actions/golang@master
|
||||
continue-on-error: true
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
args: --org=${{ secrets.SNYK_ORG }} --sarif-file-output=snyk.sarif
|
||||
command: code test
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: snyk.sarif
|
||||
|
||||
govuln:
|
||||
name: Run govuln check and Publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Running govulncheck
|
||||
uses: Templum/govulncheck-action@v0.0.8
|
||||
continue-on-error: true
|
||||
env:
|
||||
DEBUG: "true"
|
||||
with:
|
||||
go-version: 1.19
|
||||
vulncheck-version: latest
|
||||
package: ./...
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fail-on-vuln: true
|
||||
|
||||
- name: Upload govulncheck report
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: raw-report
|
||||
path: raw-report.json
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -53,3 +53,7 @@ profile.cov
|
|||
./bor-debug-*
|
||||
|
||||
dist
|
||||
|
||||
.dccache
|
||||
|
||||
*.csv
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ linters:
|
|||
- gocognit
|
||||
- gofmt
|
||||
# - gomnd
|
||||
- gomoddirectives
|
||||
# - gomoddirectives
|
||||
- gosec
|
||||
- makezero
|
||||
- nestif
|
||||
|
|
@ -65,10 +65,10 @@ linters-settings:
|
|||
|
||||
goimports:
|
||||
local-prefixes: github.com/ethereum/go-ethereum
|
||||
|
||||
|
||||
nestif:
|
||||
min-complexity: 5
|
||||
|
||||
|
||||
prealloc:
|
||||
for-loops: true
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ linters-settings:
|
|||
# By default list of stable checks is used.
|
||||
enabled-checks:
|
||||
- badLock
|
||||
- filepathJoin
|
||||
- filepathJoin
|
||||
- sortSlice
|
||||
- sprintfQuotedString
|
||||
- syncMapLoadAndDelete
|
||||
|
|
@ -185,4 +185,4 @@ issues:
|
|||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
#new: true
|
||||
new-from-rev: origin/master
|
||||
new-from-rev: origin/master
|
||||
|
|
|
|||
37
.snyk
Normal file
37
.snyk
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||
version: v1.25.0
|
||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
||||
ignore:
|
||||
'snyk:lic:golang:github.com:karalabe:usb:LGPL-3.0':
|
||||
- '*':
|
||||
reason: 'As open source org, we have no issues with licenses'
|
||||
created: 2022-11-11T08:06:37.028Z
|
||||
'snyk:lic:golang:github.com:mitchellh:cli:MPL-2.0':
|
||||
- '*':
|
||||
reason: 'As open source org, we have no issues with licenses'
|
||||
created: 2022-11-11T08:07:42.661Z
|
||||
'snyk:lic:golang:github.com:hashicorp:hcl:v2:MPL-2.0':
|
||||
- '*':
|
||||
reason: 'As open source org, we have no issues with licenses'
|
||||
created: 2022-11-11T08:09:08.112Z
|
||||
'snyk:lic:golang:github.com:hashicorp:go-multierror:MPL-2.0':
|
||||
- '*':
|
||||
reason: 'As open source org, we have no issues with licenses'
|
||||
created: 2022-11-11T08:09:14.673Z
|
||||
'snyk:lic:golang:github.com:hashicorp:go-bexpr:MPL-2.0':
|
||||
- '*':
|
||||
reason: 'As open source org, we have no issues with licenses'
|
||||
created: 2022-11-11T08:09:21.843Z
|
||||
'snyk:lic:golang:github.com:hashicorp:errwrap:MPL-2.0':
|
||||
- '*':
|
||||
reason: 'As open source org, we have no issues with licenses'
|
||||
created: 2022-11-11T08:09:28.257Z
|
||||
'snyk:lic:golang:github.com:ethereum:go-ethereum:LGPL-3.0':
|
||||
- '*':
|
||||
reason: 'As open source org, we have no issues with licenses'
|
||||
created: 2022-11-11T08:09:35.273Z
|
||||
'snyk:lic:golang:github.com:maticnetwork:polyproto:GPL-3.0':
|
||||
- '*':
|
||||
reason: 'As open source org, we have no issues with licenses'
|
||||
created: 2022-11-11T08:09:41.635Z
|
||||
patch: {}
|
||||
2
Makefile
2
Makefile
|
|
@ -65,7 +65,7 @@ test-race:
|
|||
$(GOTEST) --timeout 15m -race -shuffle=on $(TESTALL)
|
||||
|
||||
test-integration:
|
||||
$(GOTEST) --timeout 30m -tags integration $(TESTE2E)
|
||||
$(GOTEST) --timeout 60m -tags integration $(TESTE2E)
|
||||
|
||||
escape:
|
||||
cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out
|
||||
|
|
|
|||
181
SECURITY.md
181
SECURITY.md
|
|
@ -1,175 +1,14 @@
|
|||
# Security Policy
|
||||
# Polygon Technology Security Information
|
||||
|
||||
## Supported Versions
|
||||
## Link to vulnerability disclosure details (Bug Bounty)
|
||||
- Websites and Applications: https://hackerone.com/polygon-technology
|
||||
- Smart Contracts: https://immunefi.com/bounty/polygon
|
||||
|
||||
Please see [Releases](https://github.com/ethereum/go-ethereum/releases). We recommend using the [most recently released version](https://github.com/ethereum/go-ethereum/releases/latest).
|
||||
## Languages that our team speaks and understands.
|
||||
Preferred-Languages: en
|
||||
|
||||
## Audit reports
|
||||
## Security-related job openings at Polygon.
|
||||
https://polygon.technology/careers
|
||||
|
||||
Audit reports are published in the `docs` folder: https://github.com/ethereum/go-ethereum/tree/master/docs/audits
|
||||
|
||||
| Scope | Date | Report Link |
|
||||
| ------- | ------- | ----------- |
|
||||
| `geth` | 20170425 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2017-04-25_Geth-audit_Truesec.pdf) |
|
||||
| `clef` | 20180914 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf) |
|
||||
| `Discv5` | 20191015 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf) |
|
||||
| `Discv5` | 20200124 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf) |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
**Please do not file a public ticket** mentioning the vulnerability.
|
||||
|
||||
To find out how to disclose a vulnerability in Ethereum visit [https://bounty.ethereum.org](https://bounty.ethereum.org) or email bounty@ethereum.org. Please read the [disclosure page](https://github.com/ethereum/go-ethereum/security/advisories?state=published) for more information about publicly disclosed security vulnerabilities.
|
||||
|
||||
Use the built-in `geth version-check` feature to check whether the software is affected by any known vulnerability. This command will fetch the latest [`vulnerabilities.json`](https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json) file which contains known security vulnerabilities concerning `geth`, and cross-check the data against its own version number.
|
||||
|
||||
The following key may be used to communicate sensitive information to developers.
|
||||
|
||||
Fingerprint: `AE96 ED96 9E47 9B00 84F3 E17F E88D 3334 FA5F 6A0A`
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: SKS 1.1.6
|
||||
Comment: Hostname: pgp.mit.edu
|
||||
|
||||
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
|
||||
=arte
|
||||
-----END PGP PUBLIC KEY BLOCK------
|
||||
```
|
||||
## Polygon security contact details
|
||||
security@polygon.technology
|
||||
|
|
|
|||
38
build/ci.go
38
build/ci.go
|
|
@ -24,19 +24,18 @@ Usage: go run build/ci.go <command> <command flags/arguments>
|
|||
|
||||
Available commands are:
|
||||
|
||||
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
||||
test [ -coverage ] [ packages... ] -- runs the tests
|
||||
lint -- runs certain pre-selected linters
|
||||
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
|
||||
importkeys -- imports signing keys from env
|
||||
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
||||
nsis -- creates a Windows NSIS installer
|
||||
aar [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive
|
||||
xcode [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework
|
||||
purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore
|
||||
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
||||
test [ -coverage ] [ packages... ] -- runs the tests
|
||||
lint -- runs certain pre-selected linters
|
||||
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
|
||||
importkeys -- imports signing keys from env
|
||||
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
||||
nsis -- creates a Windows NSIS installer
|
||||
aar [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive
|
||||
xcode [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework
|
||||
purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore
|
||||
|
||||
For all commands, -n prevents execution of external programs (dry run mode).
|
||||
|
||||
*/
|
||||
package main
|
||||
|
||||
|
|
@ -59,6 +58,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cespare/cp"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto/signify"
|
||||
"github.com/ethereum/go-ethereum/internal/build"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
|
|
@ -674,21 +674,27 @@ func doDebianSource(cmdline []string) {
|
|||
meta := newDebMetadata(distro, goboot, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables)
|
||||
pkgdir := stageDebianSource(*workdir, meta)
|
||||
|
||||
canonicalPath, err := common.VerifyPath(pkgdir)
|
||||
if err != nil {
|
||||
fmt.Println("path not verified: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Add Go source code
|
||||
if err := build.ExtractArchive(gobundle, pkgdir); err != nil {
|
||||
if err := build.ExtractArchive(gobundle, canonicalPath); err != nil {
|
||||
log.Fatalf("Failed to extract Go sources: %v", err)
|
||||
}
|
||||
if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil {
|
||||
if err := os.Rename(filepath.Join(canonicalPath, "go"), filepath.Join(canonicalPath, ".go")); err != nil {
|
||||
log.Fatalf("Failed to rename Go source folder: %v", err)
|
||||
}
|
||||
// Add all dependency modules in compressed form
|
||||
os.MkdirAll(filepath.Join(pkgdir, ".mod", "cache"), 0755)
|
||||
if err := cp.CopyAll(filepath.Join(pkgdir, ".mod", "cache", "download"), filepath.Join(*workdir, "modgopath", "pkg", "mod", "cache", "download")); err != nil {
|
||||
os.MkdirAll(filepath.Join(canonicalPath, ".mod", "cache"), 0755)
|
||||
if err := cp.CopyAll(filepath.Join(canonicalPath, ".mod", "cache", "download"), filepath.Join(*workdir, "modgopath", "pkg", "mod", "cache", "download")); err != nil {
|
||||
log.Fatalf("Failed to copy Go module dependencies: %v", err)
|
||||
}
|
||||
// Run the packaging and upload to the PPA
|
||||
debuild := exec.Command("debuild", "-S", "-sa", "-us", "-uc", "-d", "-Zxz", "-nc")
|
||||
debuild.Dir = pkgdir
|
||||
debuild.Dir = canonicalPath
|
||||
build.MustRun(debuild)
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -78,8 +78,7 @@ syncmode = "full"
|
|||
# prefix = ""
|
||||
# host = "localhost"
|
||||
# api = ["web3", "net"]
|
||||
# vhosts = ["*"]
|
||||
# corsdomain = ["*"]
|
||||
# origins = ["*"]
|
||||
# [jsonrpc.graphql]
|
||||
# enabled = false
|
||||
# port = 0
|
||||
|
|
@ -122,6 +121,7 @@ syncmode = "full"
|
|||
# noprefetch = false
|
||||
# preimages = false
|
||||
# txlookuplimit = 2350000
|
||||
# triesinmemory = 128
|
||||
|
||||
[accounts]
|
||||
# allow-insecure-unlock = true
|
||||
|
|
|
|||
|
|
@ -18,8 +18,12 @@
|
|||
"period": {
|
||||
"0": 2
|
||||
},
|
||||
"producerDelay": 6,
|
||||
"sprint": 64,
|
||||
"producerDelay": {
|
||||
"0": 6
|
||||
},
|
||||
"sprint": {
|
||||
"0": 64
|
||||
},
|
||||
"backupMultiplier": {
|
||||
"0": 2
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,15 +15,24 @@
|
|||
"londonBlock": 22640000,
|
||||
"bor": {
|
||||
"jaipurBlock": 22770000,
|
||||
"delhiBlock": 29638656,
|
||||
"period": {
|
||||
"0": 2,
|
||||
"25275000": 5
|
||||
"25275000": 5,
|
||||
"29638656": 2
|
||||
},
|
||||
"producerDelay": {
|
||||
"0": 6,
|
||||
"29638656": 4
|
||||
},
|
||||
"sprint": {
|
||||
"0": 64,
|
||||
"29638656": 16
|
||||
},
|
||||
"producerDelay": 6,
|
||||
"sprint": 64,
|
||||
"backupMultiplier": {
|
||||
"0": 2,
|
||||
"25275000": 5
|
||||
"25275000": 5,
|
||||
"29638656": 2
|
||||
},
|
||||
"validatorContract": "0x0000000000000000000000000000000000001000",
|
||||
"stateReceiverContract": "0x0000000000000000000000000000000000001001",
|
||||
|
|
|
|||
|
|
@ -162,9 +162,16 @@ func main() {
|
|||
}
|
||||
}
|
||||
// Load up the account key and decrypt its password
|
||||
blob, err := ioutil.ReadFile(*accPassFlag)
|
||||
|
||||
canonicalPath, err := common.VerifyPath(*accPassFlag)
|
||||
if err != nil {
|
||||
log.Crit("Failed to read account password contents", "file", *accPassFlag, "err", err)
|
||||
fmt.Println("path not verified: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
blob, err := ioutil.ReadFile(canonicalPath)
|
||||
if err != nil {
|
||||
log.Crit("Failed to read account password contents", "file", canonicalPath, "err", err)
|
||||
}
|
||||
pass := strings.TrimSuffix(string(blob), "\n")
|
||||
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ func setDefaultMumbaiGethConfig(ctx *cli.Context, config *gethConfig) {
|
|||
config.Eth.TxPool.AccountQueue = 64
|
||||
config.Eth.TxPool.GlobalQueue = 131072
|
||||
config.Eth.TxPool.Lifetime = 90 * time.Minute
|
||||
config.Node.P2P.MaxPeers = 200
|
||||
config.Node.P2P.MaxPeers = 50
|
||||
config.Metrics.Enabled = true
|
||||
// --pprof is enabled in 'internal/debug/flags.go'
|
||||
}
|
||||
|
|
@ -350,7 +350,7 @@ func setDefaultBorMainnetGethConfig(ctx *cli.Context, config *gethConfig) {
|
|||
config.Eth.TxPool.AccountQueue = 64
|
||||
config.Eth.TxPool.GlobalQueue = 131072
|
||||
config.Eth.TxPool.Lifetime = 90 * time.Minute
|
||||
config.Node.P2P.MaxPeers = 200
|
||||
config.Node.P2P.MaxPeers = 50
|
||||
config.Metrics.Enabled = true
|
||||
// --pprof is enabled in 'internal/debug/flags.go'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1504,7 +1504,7 @@ func setPeerRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
|
|||
|
||||
if peerRequiredBlocks == "" {
|
||||
if ctx.GlobalIsSet(LegacyWhitelistFlag.Name) {
|
||||
log.Warn("The flag --rpc is deprecated and will be removed, please use --peer.requiredblocks")
|
||||
log.Warn("The flag --whitelist is deprecated and will be removed, please use --eth.requiredblocks")
|
||||
peerRequiredBlocks = ctx.GlobalString(LegacyWhitelistFlag.Name)
|
||||
} else {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -47,3 +47,32 @@ func AbsolutePath(datadir string, filename string) string {
|
|||
}
|
||||
return filepath.Join(datadir, filename)
|
||||
}
|
||||
|
||||
// VerifyPath sanitizes the path to avoid Path Traversal vulnerability
|
||||
func VerifyPath(path string) (string, error) {
|
||||
c := filepath.Clean(path)
|
||||
|
||||
r, err := filepath.EvalSymlinks(c)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("unsafe or invalid path specified: %s", path)
|
||||
} else {
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyCrasher sanitizes the path to avoid Path Traversal vulnerability and reads the file from that path, returning its content
|
||||
func VerifyCrasher(crasher string) []byte {
|
||||
canonicalPath, err := VerifyPath(crasher)
|
||||
if err != nil {
|
||||
fmt.Println("path not verified: " + err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(canonicalPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", canonicalPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ const (
|
|||
|
||||
// Bor protocol constants.
|
||||
var (
|
||||
defaultSprintLength = uint64(64) // Default number of blocks after which to checkpoint and reset the pending votes
|
||||
defaultSprintLength = map[string]uint64{
|
||||
"0": 64,
|
||||
} // Default number of blocks after which to checkpoint and reset the pending votes
|
||||
|
||||
extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
|
||||
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
||||
|
|
@ -167,7 +169,7 @@ func encodeSigHeader(w io.Writer, header *types.Header, c *params.BorConfig) {
|
|||
header.Nonce,
|
||||
}
|
||||
|
||||
if c.IsJaipur(header.Number.Uint64()) {
|
||||
if c.IsJaipur(header.Number) {
|
||||
if header.BaseFee != nil {
|
||||
enc = append(enc, header.BaseFee)
|
||||
}
|
||||
|
|
@ -183,8 +185,8 @@ func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint6
|
|||
// When the block is the first block of the sprint, it is expected to be delayed by `producerDelay`.
|
||||
// That is to allow time for block propagation in the last sprint
|
||||
delay := c.CalculatePeriod(number)
|
||||
if number%c.Sprint == 0 {
|
||||
delay = c.ProducerDelay
|
||||
if number%c.CalculateSprint(number) == 0 {
|
||||
delay = c.CalculateProducerDelay(number)
|
||||
}
|
||||
|
||||
if succession > 0 {
|
||||
|
|
@ -248,7 +250,7 @@ func New(
|
|||
borConfig := chainConfig.Bor
|
||||
|
||||
// Set any missing consensus parameters to their defaults
|
||||
if borConfig != nil && borConfig.Sprint == 0 {
|
||||
if borConfig != nil && borConfig.CalculateSprint(0) == 0 {
|
||||
borConfig.Sprint = defaultSprintLength
|
||||
}
|
||||
// Allocate the snapshot caches and create the engine
|
||||
|
|
@ -339,7 +341,7 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
|
|||
}
|
||||
|
||||
// check extr adata
|
||||
isSprintEnd := IsSprintStart(number+1, c.config.Sprint)
|
||||
isSprintEnd := IsSprintStart(number+1, c.config.CalculateSprint(number))
|
||||
|
||||
// Ensure that the extra-data contains a signer list on checkpoint, but none otherwise
|
||||
signersBytes := len(header.Extra) - extraVanity - extraSeal
|
||||
|
|
@ -453,7 +455,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
|
|||
}
|
||||
|
||||
// verify the validator list in the last sprint block
|
||||
if IsSprintStart(number, c.config.Sprint) {
|
||||
if IsSprintStart(number, c.config.CalculateSprint(number)) {
|
||||
parentValidatorBytes := parent.Extra[extraVanity : len(parent.Extra)-extraSeal]
|
||||
validatorsBytes := make([]byte, len(snap.ValidatorSet.Validators)*validatorHeaderBytesLength)
|
||||
|
||||
|
|
@ -685,7 +687,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
|
|||
header.Extra = header.Extra[:extraVanity]
|
||||
|
||||
// get validator set if number
|
||||
if IsSprintStart(number+1, c.config.Sprint) {
|
||||
if IsSprintStart(number+1, c.config.CalculateSprint(number)) {
|
||||
newValidators, err := c.spanner.GetCurrentValidators(context.Background(), header.ParentHash, number+1)
|
||||
if err != nil {
|
||||
return errUnknownValidators
|
||||
|
|
@ -738,9 +740,8 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
|
|||
|
||||
headerNumber := header.Number.Uint64()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if IsSprintStart(headerNumber, c.config.Sprint) {
|
||||
if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) {
|
||||
ctx := context.Background()
|
||||
cx := statefull.ChainContext{Chain: chain, Bor: c}
|
||||
// check and commit span
|
||||
if err := c.checkAndCommitSpan(ctx, state, header, cx); err != nil {
|
||||
|
|
@ -817,7 +818,7 @@ func (c *Bor) FinalizeAndAssemble(ctx context.Context, chain consensus.ChainHead
|
|||
|
||||
var err error
|
||||
|
||||
if IsSprintStart(headerNumber, c.config.Sprint) {
|
||||
if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) {
|
||||
cx := statefull.ChainContext{Chain: chain, Bor: c}
|
||||
|
||||
tracing.Exec(finalizeCtx, "bor.checkAndCommitSpan", func(ctx context.Context, span trace.Span) {
|
||||
|
|
@ -1077,7 +1078,7 @@ func (c *Bor) needToCommitSpan(currentSpan *span.Span, headerNumber uint64) bool
|
|||
}
|
||||
|
||||
// if current block is first block of last sprint in current span
|
||||
if currentSpan.EndBlock > c.config.Sprint && currentSpan.EndBlock-c.config.Sprint+1 == headerNumber {
|
||||
if currentSpan.EndBlock > c.config.CalculateSprint(headerNumber) && currentSpan.EndBlock-c.config.CalculateSprint(headerNumber)+1 == headerNumber {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -1137,7 +1138,7 @@ func (c *Bor) CommitStates(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
to := time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.Sprint).Time), 0)
|
||||
to := time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.CalculateSprint(number)).Time), 0)
|
||||
lastStateID := _lastStateID.Uint64()
|
||||
|
||||
log.Info(
|
||||
|
|
@ -1253,7 +1254,7 @@ func (c *Bor) getNextHeimdallSpanForTest(
|
|||
spanBor.StartBlock = spanBor.EndBlock + 1
|
||||
}
|
||||
|
||||
spanBor.EndBlock = spanBor.StartBlock + (100 * c.config.Sprint) - 1
|
||||
spanBor.EndBlock = spanBor.StartBlock + (100 * c.config.CalculateSprint(headerNumber)) - 1
|
||||
|
||||
selectedProducers := make([]valset.Validator, len(snap.ValidatorSet.Validators))
|
||||
for i, v := range snap.ValidatorSet.Validators {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ func TestGenesisContractChange(t *testing.T) {
|
|||
|
||||
b := &Bor{
|
||||
config: ¶ms.BorConfig{
|
||||
Sprint: 10, // skip sprint transactions in sprint
|
||||
Sprint: map[string]uint64{
|
||||
"0": 10,
|
||||
}, // skip sprint transactions in sprint
|
||||
BlockAlloc: map[string]interface{}{
|
||||
// write as interface since that is how it is decoded in genesis
|
||||
"2": map[string]interface{}{
|
||||
|
|
@ -123,20 +125,20 @@ func TestEncodeSigHeaderJaipur(t *testing.T) {
|
|||
)
|
||||
|
||||
// Jaipur NOT enabled and BaseFee not set
|
||||
hash := SealHash(h, ¶ms.BorConfig{JaipurBlock: 10})
|
||||
hash := SealHash(h, ¶ms.BorConfig{JaipurBlock: big.NewInt(10)})
|
||||
require.Equal(t, hash, hashWithoutBaseFee)
|
||||
|
||||
// Jaipur enabled (Jaipur=0) and BaseFee not set
|
||||
hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: 0})
|
||||
hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: common.Big0})
|
||||
require.Equal(t, hash, hashWithoutBaseFee)
|
||||
|
||||
h.BaseFee = big.NewInt(2)
|
||||
|
||||
// Jaipur enabled (Jaipur=Header block) and BaseFee set
|
||||
hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: 1})
|
||||
hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: common.Big1})
|
||||
require.Equal(t, hash, hashWithBaseFee)
|
||||
|
||||
// Jaipur NOT enabled and BaseFee set
|
||||
hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: 10})
|
||||
hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: big.NewInt(10)})
|
||||
require.Equal(t, hash, hashWithoutBaseFee)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
|||
number := header.Number.Uint64()
|
||||
|
||||
// Delete the oldest signer from the recent list to allow it signing again
|
||||
if number >= s.config.Sprint {
|
||||
delete(snap.Recents, number-s.config.Sprint)
|
||||
if number >= s.config.CalculateSprint(number) {
|
||||
delete(snap.Recents, number-s.config.CalculateSprint(number))
|
||||
}
|
||||
|
||||
// Resolve the authorization key and check against signers
|
||||
|
|
@ -145,7 +145,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
|||
snap.Recents[number] = signer
|
||||
|
||||
// change validator set and change proposer
|
||||
if number > 0 && (number+1)%s.config.Sprint == 0 {
|
||||
if number > 0 && (number+1)%s.config.CalculateSprint(number) == 0 {
|
||||
if err := validateHeaderExtraField(header.Extra); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/JekaMas/crand"
|
||||
"github.com/maticnetwork/crand"
|
||||
"github.com/stretchr/testify/require"
|
||||
"pgregory.net/rapid"
|
||||
|
||||
|
|
|
|||
|
|
@ -31,22 +31,22 @@ func (c ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
|
|||
}
|
||||
|
||||
// callmsg implements core.Message to allow passing it as a transaction simulator.
|
||||
type callmsg struct {
|
||||
type Callmsg struct {
|
||||
ethereum.CallMsg
|
||||
}
|
||||
|
||||
func (m callmsg) From() common.Address { return m.CallMsg.From }
|
||||
func (m callmsg) Nonce() uint64 { return 0 }
|
||||
func (m callmsg) CheckNonce() bool { return false }
|
||||
func (m callmsg) To() *common.Address { return m.CallMsg.To }
|
||||
func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
||||
func (m callmsg) Gas() uint64 { return m.CallMsg.Gas }
|
||||
func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
|
||||
func (m callmsg) Data() []byte { return m.CallMsg.Data }
|
||||
func (m Callmsg) From() common.Address { return m.CallMsg.From }
|
||||
func (m Callmsg) Nonce() uint64 { return 0 }
|
||||
func (m Callmsg) CheckNonce() bool { return false }
|
||||
func (m Callmsg) To() *common.Address { return m.CallMsg.To }
|
||||
func (m Callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
||||
func (m Callmsg) Gas() uint64 { return m.CallMsg.Gas }
|
||||
func (m Callmsg) Value() *big.Int { return m.CallMsg.Value }
|
||||
func (m Callmsg) Data() []byte { return m.CallMsg.Data }
|
||||
|
||||
// get system message
|
||||
func GetSystemMessage(toAddress common.Address, data []byte) callmsg {
|
||||
return callmsg{
|
||||
func GetSystemMessage(toAddress common.Address, data []byte) Callmsg {
|
||||
return Callmsg{
|
||||
ethereum.CallMsg{
|
||||
From: systemAddress,
|
||||
Gas: math.MaxUint64 / 2,
|
||||
|
|
@ -61,7 +61,7 @@ func GetSystemMessage(toAddress common.Address, data []byte) callmsg {
|
|||
// apply message
|
||||
func ApplyMessage(
|
||||
_ context.Context,
|
||||
msg callmsg,
|
||||
msg Callmsg,
|
||||
state *state.StateDB,
|
||||
header *types.Header,
|
||||
chainConfig *params.ChainConfig,
|
||||
|
|
@ -93,3 +93,28 @@ func ApplyMessage(
|
|||
|
||||
return gasUsed, nil
|
||||
}
|
||||
|
||||
func ApplyBorMessage(vmenv vm.EVM, msg Callmsg) (*core.ExecutionResult, error) {
|
||||
initialGas := msg.Gas()
|
||||
|
||||
// Apply the transaction to the current state (included in the env)
|
||||
ret, gasLeft, err := vmenv.Call(
|
||||
vm.AccountRef(msg.From()),
|
||||
*msg.To(),
|
||||
msg.Data(),
|
||||
msg.Gas(),
|
||||
msg.Value(),
|
||||
)
|
||||
// Update the state with pending changes
|
||||
if err != nil {
|
||||
vmenv.StateDB.Finalise(true)
|
||||
}
|
||||
|
||||
gasUsed := initialGas - gasLeft
|
||||
|
||||
return &core.ExecutionResult{
|
||||
UsedGas: gasUsed,
|
||||
Err: err,
|
||||
ReturnData: ret,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,10 +180,6 @@ func TestRemoteMultiNotify(t *testing.T) {
|
|||
// Tests that pushing work packages fast to the miner doesn't cause any data race
|
||||
// issues in the notifications. Full pending block body / --miner.notify.full)
|
||||
func TestRemoteMultiNotifyFull(t *testing.T) {
|
||||
// TODO: Understand the test case and Identify the reason for failing tests.
|
||||
// Also, make it more deterministic.
|
||||
t.Skip("skipping - non-deterministic test, no dependency on this test for now and not directly relevant to bor")
|
||||
|
||||
// Start a simple web server to capture notifications.
|
||||
sink := make(chan map[string]interface{}, 64)
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
|
|
@ -197,6 +193,9 @@ func TestRemoteMultiNotifyFull(t *testing.T) {
|
|||
}
|
||||
sink <- work
|
||||
}))
|
||||
|
||||
// Allowing the server to start listening.
|
||||
time.Sleep(2 * time.Second)
|
||||
defer server.Close()
|
||||
|
||||
// Create the custom ethash engine.
|
||||
|
|
|
|||
|
|
@ -59,9 +59,10 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
|||
}
|
||||
|
||||
var (
|
||||
parentGasTarget = parent.GasLimit / params.ElasticityMultiplier
|
||||
parentGasTargetBig = new(big.Int).SetUint64(parentGasTarget)
|
||||
baseFeeChangeDenominator = new(big.Int).SetUint64(params.BaseFeeChangeDenominator)
|
||||
parentGasTarget = parent.GasLimit / params.ElasticityMultiplier
|
||||
parentGasTargetBig = new(big.Int).SetUint64(parentGasTarget)
|
||||
baseFeeChangeDenominatorUint64 = params.BaseFeeChangeDenominator(config.Bor, parent.Number)
|
||||
baseFeeChangeDenominator = new(big.Int).SetUint64(baseFeeChangeDenominatorUint64)
|
||||
)
|
||||
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
|
||||
if parent.GasUsed == parentGasTarget {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import (
|
|||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
|
@ -47,12 +46,14 @@ func copyConfig(original *params.ChainConfig) *params.ChainConfig {
|
|||
TerminalTotalDifficulty: original.TerminalTotalDifficulty,
|
||||
Ethash: original.Ethash,
|
||||
Clique: original.Clique,
|
||||
Bor: original.Bor,
|
||||
}
|
||||
}
|
||||
|
||||
func config() *params.ChainConfig {
|
||||
config := copyConfig(params.TestChainConfig)
|
||||
config.LondonBlock = big.NewInt(5)
|
||||
config.Bor.DelhiBlock = big.NewInt(8)
|
||||
return config
|
||||
}
|
||||
|
||||
|
|
@ -108,6 +109,8 @@ func TestBlockGasLimits(t *testing.T) {
|
|||
|
||||
// TestCalcBaseFee assumes all blocks are 1559-blocks
|
||||
func TestCalcBaseFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
parentBaseFee int64
|
||||
parentGasLimit uint64
|
||||
|
|
@ -117,10 +120,12 @@ func TestCalcBaseFee(t *testing.T) {
|
|||
{params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFee}, // usage == target
|
||||
{params.InitialBaseFee, 20000000, 9000000, 987500000}, // usage below target
|
||||
{params.InitialBaseFee, 20000000, 11000000, 1012500000}, // usage above target
|
||||
{params.InitialBaseFee, 20000000, 20000000, 1125000000}, // usage full
|
||||
{params.InitialBaseFee, 20000000, 0, 875000000}, // usage 0
|
||||
}
|
||||
for i, test := range tests {
|
||||
parent := &types.Header{
|
||||
Number: common.Big32,
|
||||
Number: big.NewInt(6),
|
||||
GasLimit: test.parentGasLimit,
|
||||
GasUsed: test.parentGasUsed,
|
||||
BaseFee: big.NewInt(test.parentBaseFee),
|
||||
|
|
@ -130,3 +135,38 @@ func TestCalcBaseFee(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestCalcBaseFee assumes all blocks are 1559-blocks post Delhi Hard Fork
|
||||
func TestCalcBaseFeeDelhi(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testConfig := copyConfig(config())
|
||||
|
||||
// Test Delhi Hard Fork
|
||||
// Hard fork kicks in at block 8
|
||||
|
||||
tests := []struct {
|
||||
parentBaseFee int64
|
||||
parentGasLimit uint64
|
||||
parentGasUsed uint64
|
||||
expectedBaseFee int64
|
||||
}{
|
||||
{params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFee}, // usage == target
|
||||
{params.InitialBaseFee, 20000000, 9000000, 993750000}, // usage below target
|
||||
{params.InitialBaseFee, 20000000, 11000000, 1006250000}, // usage above target
|
||||
{params.InitialBaseFee, 20000000, 20000000, 1062500000}, // usage full
|
||||
{params.InitialBaseFee, 20000000, 0, 937500000}, // usage 0
|
||||
|
||||
}
|
||||
for i, test := range tests {
|
||||
parent := &types.Header{
|
||||
Number: big.NewInt(8),
|
||||
GasLimit: test.parentGasLimit,
|
||||
GasUsed: test.parentGasUsed,
|
||||
BaseFee: big.NewInt(test.parentBaseFee),
|
||||
}
|
||||
if have, want := CalcBaseFee(testConfig, parent), big.NewInt(test.expectedBaseFee); have.Cmp(want) != 0 {
|
||||
t.Errorf("test %d: have %d want %d, ", i, have, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
|
|||
|
||||
// genUncles generates blocks with two uncle headers.
|
||||
func genUncles(i int, gen *BlockGen) {
|
||||
if i >= 6 {
|
||||
if i >= 7 {
|
||||
b2 := gen.PrevBlock(i - 6).Header()
|
||||
b2.Extra = []byte("foo")
|
||||
gen.AddUncle(b2)
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@ const (
|
|||
txLookupCacheLimit = 1024
|
||||
maxFutureBlocks = 256
|
||||
maxTimeFutureBlocks = 30
|
||||
TriesInMemory = 128
|
||||
|
||||
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
|
||||
//
|
||||
|
|
@ -132,6 +131,7 @@ type CacheConfig struct {
|
|||
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
||||
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
||||
Preimages bool // Whether to store preimage of trie key to the disk
|
||||
TriesInMemory uint64 // Number of recent tries to keep in memory
|
||||
|
||||
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
||||
}
|
||||
|
|
@ -144,6 +144,7 @@ var DefaultCacheConfig = &CacheConfig{
|
|||
TrieTimeLimit: 5 * time.Minute,
|
||||
SnapshotLimit: 256,
|
||||
SnapshotWait: true,
|
||||
TriesInMemory: 128,
|
||||
}
|
||||
|
||||
// BlockChain represents the canonical chain given a database with a genesis
|
||||
|
|
@ -229,6 +230,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
|||
if cacheConfig == nil {
|
||||
cacheConfig = DefaultCacheConfig
|
||||
}
|
||||
|
||||
if cacheConfig.TriesInMemory <= 0 {
|
||||
cacheConfig.TriesInMemory = DefaultCacheConfig.TriesInMemory
|
||||
}
|
||||
bodyCache, _ := lru.New(bodyCacheLimit)
|
||||
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
||||
receiptsCache, _ := lru.New(receiptsCacheLimit)
|
||||
|
|
@ -829,7 +834,7 @@ func (bc *BlockChain) Stop() {
|
|||
if !bc.cacheConfig.TrieDirtyDisabled {
|
||||
triedb := bc.stateCache.TrieDB()
|
||||
|
||||
for _, offset := range []uint64{0, 1, TriesInMemory - 1} {
|
||||
for _, offset := range []uint64{0, 1, bc.cacheConfig.TriesInMemory - 1} {
|
||||
if number := bc.CurrentBlock().NumberU64(); number > offset {
|
||||
recent := bc.GetBlockByNumber(number - offset)
|
||||
|
||||
|
|
@ -1297,7 +1302,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||
triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive
|
||||
bc.triegc.Push(root, -int64(block.NumberU64()))
|
||||
|
||||
if current := block.NumberU64(); current > TriesInMemory {
|
||||
if current := block.NumberU64(); current > bc.cacheConfig.TriesInMemory {
|
||||
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
||||
var (
|
||||
nodes, imgs = triedb.Size()
|
||||
|
|
@ -1307,7 +1312,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||
triedb.Cap(limit - ethdb.IdealBatchSize)
|
||||
}
|
||||
// Find the next state trie we need to commit
|
||||
chosen := current - TriesInMemory
|
||||
chosen := current - bc.cacheConfig.TriesInMemory
|
||||
|
||||
// If we exceeded out time allowance, flush an entire trie to disk
|
||||
if bc.gcproc > bc.cacheConfig.TrieTimeLimit {
|
||||
|
|
@ -1319,8 +1324,8 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||
} else {
|
||||
// If we're exceeding limits but haven't reached a large enough memory gap,
|
||||
// warn the user that the system is becoming unstable.
|
||||
if chosen < lastWrite+TriesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
|
||||
log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/TriesInMemory)
|
||||
if chosen < lastWrite+bc.cacheConfig.TriesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
|
||||
log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TriesInMemory, "optimum", float64(chosen-lastWrite)/float64((bc.cacheConfig.TriesInMemory)))
|
||||
}
|
||||
// Flush an entire trie and restart the counters
|
||||
triedb.Commit(header.Root, true, nil)
|
||||
|
|
|
|||
|
|
@ -1652,7 +1652,7 @@ func TestTrieForkGC(t *testing.T) {
|
|||
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
|
||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
|
||||
|
||||
// Generate a bunch of fork blocks, each side forking from the canonical chain
|
||||
forks := make([]*types.Block, len(blocks))
|
||||
|
|
@ -1681,7 +1681,7 @@ func TestTrieForkGC(t *testing.T) {
|
|||
}
|
||||
}
|
||||
// Dereference all the recent tries and ensure no past trie is left in
|
||||
for i := 0; i < TriesInMemory; i++ {
|
||||
for i := 0; i < int(chain.cacheConfig.TriesInMemory); i++ {
|
||||
chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
|
||||
chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
|
||||
}
|
||||
|
|
@ -1700,8 +1700,8 @@ func TestLargeReorgTrieGC(t *testing.T) {
|
|||
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
||||
|
||||
shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
|
||||
original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
|
||||
competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
|
||||
original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
|
||||
competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*int(DefaultCacheConfig.TriesInMemory)+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
|
||||
|
||||
// Import the shared chain and the original canonical one
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
|
|
@ -1736,7 +1736,8 @@ func TestLargeReorgTrieGC(t *testing.T) {
|
|||
if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil {
|
||||
t.Fatalf("failed to finalize competitor chain: %v", err)
|
||||
}
|
||||
for i, block := range competitor[:len(competitor)-TriesInMemory] {
|
||||
|
||||
for i, block := range competitor[:len(competitor)-int(chain.cacheConfig.TriesInMemory)] {
|
||||
if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
|
||||
t.Fatalf("competitor %d: competing chain state missing", i)
|
||||
}
|
||||
|
|
@ -1882,8 +1883,8 @@ func TestInsertReceiptChainRollback(t *testing.T) {
|
|||
// overtake the 'canon' chain until after it's passed canon by about 200 blocks.
|
||||
//
|
||||
// Details at:
|
||||
// - https://github.com/ethereum/go-ethereum/issues/18977
|
||||
// - https://github.com/ethereum/go-ethereum/pull/18988
|
||||
// - https://github.com/ethereum/go-ethereum/issues/18977
|
||||
// - https://github.com/ethereum/go-ethereum/pull/18988
|
||||
func TestLowDiffLongChain(t *testing.T) {
|
||||
// Generate a canonical chain to act as the main dataset
|
||||
engine := ethash.NewFaker()
|
||||
|
|
@ -1892,7 +1893,7 @@ func TestLowDiffLongChain(t *testing.T) {
|
|||
|
||||
// We must use a pretty long chain to ensure that the fork doesn't overtake us
|
||||
// until after at least 128 blocks post tip
|
||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*TriesInMemory, func(i int, b *BlockGen) {
|
||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
||||
b.SetCoinbase(common.Address{1})
|
||||
b.OffsetTime(-9)
|
||||
})
|
||||
|
|
@ -1910,7 +1911,7 @@ func TestLowDiffLongChain(t *testing.T) {
|
|||
}
|
||||
// Generate fork chain, starting from an early block
|
||||
parent := blocks[10]
|
||||
fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*TriesInMemory, func(i int, b *BlockGen) {
|
||||
fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
||||
b.SetCoinbase(common.Address{2})
|
||||
})
|
||||
|
||||
|
|
@ -1979,7 +1980,8 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
|||
// Set the terminal total difficulty in the config
|
||||
gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
|
||||
}
|
||||
blocks, _ := GenerateChain(&chainConfig, genesis, genEngine, db, 2*TriesInMemory, func(i int, gen *BlockGen) {
|
||||
|
||||
blocks, _ := GenerateChain(&chainConfig, genesis, genEngine, db, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, gen *BlockGen) {
|
||||
tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create tx: %v", err)
|
||||
|
|
@ -1991,9 +1993,9 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
|||
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||
}
|
||||
|
||||
lastPrunedIndex := len(blocks) - TriesInMemory - 1
|
||||
lastPrunedIndex := len(blocks) - int(chain.cacheConfig.TriesInMemory) - 1
|
||||
lastPrunedBlock := blocks[lastPrunedIndex]
|
||||
firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory]
|
||||
firstNonPrunedBlock := blocks[len(blocks)-int(chain.cacheConfig.TriesInMemory)]
|
||||
|
||||
// Verify pruning of lastPrunedBlock
|
||||
if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
|
||||
|
|
@ -2019,7 +2021,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
|||
// Generate fork chain, make it longer than canon
|
||||
parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock
|
||||
parent := blocks[parentIndex]
|
||||
fork, _ := GenerateChain(&chainConfig, parent, genEngine, db, 2*TriesInMemory, func(i int, b *BlockGen) {
|
||||
fork, _ := GenerateChain(&chainConfig, parent, genEngine, db, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
||||
b.SetCoinbase(common.Address{2})
|
||||
})
|
||||
// Prepend the parent(s)
|
||||
|
|
@ -2046,7 +2048,8 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
|||
// That is: the sidechain for import contains some blocks already present in canon chain.
|
||||
// So the blocks are
|
||||
// [ Cn, Cn+1, Cc, Sn+3 ... Sm]
|
||||
// ^ ^ ^ pruned
|
||||
//
|
||||
// ^ ^ ^ pruned
|
||||
func TestPrunedImportSide(t *testing.T) {
|
||||
//glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
|
||||
//glogger.Verbosity(3)
|
||||
|
|
@ -2841,9 +2844,9 @@ func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
|
|||
// This internally leads to a sidechain import, since the blocks trigger an
|
||||
// ErrPrunedAncestor error.
|
||||
// This may e.g. happen if
|
||||
// 1. Downloader rollbacks a batch of inserted blocks and exits
|
||||
// 2. Downloader starts to sync again
|
||||
// 3. The blocks fetched are all known and canonical blocks
|
||||
// 1. Downloader rollbacks a batch of inserted blocks and exits
|
||||
// 2. Downloader starts to sync again
|
||||
// 3. The blocks fetched are all known and canonical blocks
|
||||
func TestSideImportPrunedBlocks(t *testing.T) {
|
||||
// Generate a canonical chain to act as the main dataset
|
||||
engine := ethash.NewFaker()
|
||||
|
|
@ -2851,7 +2854,7 @@ func TestSideImportPrunedBlocks(t *testing.T) {
|
|||
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
||||
|
||||
// Generate and import the canonical chain
|
||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil)
|
||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*int(DefaultCacheConfig.TriesInMemory), nil)
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
|
||||
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
|
||||
|
|
@ -2863,14 +2866,15 @@ func TestSideImportPrunedBlocks(t *testing.T) {
|
|||
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||
}
|
||||
|
||||
lastPrunedIndex := len(blocks) - TriesInMemory - 1
|
||||
lastPrunedIndex := len(blocks) - int(chain.cacheConfig.TriesInMemory) - 1
|
||||
lastPrunedBlock := blocks[lastPrunedIndex]
|
||||
|
||||
// Verify pruning of lastPrunedBlock
|
||||
if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
|
||||
t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64())
|
||||
}
|
||||
firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory]
|
||||
|
||||
firstNonPrunedBlock := blocks[len(blocks)-int(chain.cacheConfig.TriesInMemory)]
|
||||
// Verify firstNonPrunedBlock is not pruned
|
||||
if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
|
||||
t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
|
||||
|
|
@ -3356,20 +3360,19 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) {
|
|||
|
||||
// TestInitThenFailCreateContract tests a pretty notorious case that happened
|
||||
// on mainnet over blocks 7338108, 7338110 and 7338115.
|
||||
// - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated
|
||||
// with 0.001 ether (thus created but no code)
|
||||
// - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on
|
||||
// the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the
|
||||
// deployment fails due to OOG during initcode execution
|
||||
// - Block 7338115: another tx checks the balance of
|
||||
// e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as
|
||||
// zero.
|
||||
// - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated
|
||||
// with 0.001 ether (thus created but no code)
|
||||
// - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on
|
||||
// the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the
|
||||
// deployment fails due to OOG during initcode execution
|
||||
// - Block 7338115: another tx checks the balance of
|
||||
// e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as
|
||||
// zero.
|
||||
//
|
||||
// The problem being that the snapshotter maintains a destructset, and adds items
|
||||
// to the destructset in case something is created "onto" an existing item.
|
||||
// We need to either roll back the snapDestructs, or not place it into snapDestructs
|
||||
// in the first place.
|
||||
//
|
||||
func TestInitThenFailCreateContract(t *testing.T) {
|
||||
var (
|
||||
// Generate a canonical chain to act as the main dataset
|
||||
|
|
@ -3558,13 +3561,13 @@ func TestEIP2718Transition(t *testing.T) {
|
|||
|
||||
// TestEIP1559Transition tests the following:
|
||||
//
|
||||
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
|
||||
// 2. Gas accounting for access lists on EIP-1559 transactions is correct.
|
||||
// 3. Only the transaction's tip will be received by the coinbase.
|
||||
// 4. The transaction sender pays for both the tip and baseFee.
|
||||
// 5. The coinbase receives only the partially realized tip when
|
||||
// gasFeeCap - gasTipCap < baseFee.
|
||||
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
|
||||
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
|
||||
// 2. Gas accounting for access lists on EIP-1559 transactions is correct.
|
||||
// 3. Only the transaction's tip will be received by the coinbase.
|
||||
// 4. The transaction sender pays for both the tip and baseFee.
|
||||
// 5. The coinbase receives only the partially realized tip when
|
||||
// gasFeeCap - gasTipCap < baseFee.
|
||||
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
|
||||
func TestEIP1559Transition(t *testing.T) {
|
||||
var (
|
||||
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import (
|
|||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/JekaMas/crand"
|
||||
"github.com/maticnetwork/crand"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
|
|||
|
|
@ -1826,7 +1826,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
|
|||
sideblocks, _ = core.GenerateChain(params.BorUnittestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *core.BlockGen) {
|
||||
b.SetCoinbase(testAddress1)
|
||||
|
||||
if bor.IsSprintStart(b.Number().Uint64(), params.BorUnittestChainConfig.Bor.Sprint) {
|
||||
if bor.IsSprintStart(b.Number().Uint64(), params.BorUnittestChainConfig.Bor.CalculateSprint(b.Number().Uint64())) {
|
||||
b.SetExtra(back.Genesis.ExtraData)
|
||||
} else {
|
||||
b.SetExtra(make([]byte, 32+crypto.SignatureLength))
|
||||
|
|
@ -1841,7 +1841,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
|
|||
b.SetCoinbase(miner.TestBankAddress)
|
||||
b.SetDifficulty(big.NewInt(1000000))
|
||||
|
||||
if bor.IsSprintStart(b.Number().Uint64(), params.BorUnittestChainConfig.Bor.Sprint) {
|
||||
if bor.IsSprintStart(b.Number().Uint64(), params.BorUnittestChainConfig.Bor.CalculateSprint(b.Number().Uint64())) {
|
||||
b.SetExtra(back.Genesis.ExtraData)
|
||||
} else {
|
||||
b.SetExtra(make([]byte, 32+crypto.SignatureLength))
|
||||
|
|
|
|||
|
|
@ -2082,6 +2082,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
|
|||
|
||||
// verifyNoGaps checks that there are no gaps after the initial set of blocks in
|
||||
// the database and errors if found.
|
||||
//
|
||||
//nolint:gocognit
|
||||
func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks) {
|
||||
t.Helper()
|
||||
|
|
@ -2135,6 +2136,7 @@ func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted
|
|||
|
||||
// verifyCutoff checks that there are no chain data available in the chain after
|
||||
// the specified limit, but that it is available before.
|
||||
//
|
||||
//nolint:gocognit
|
||||
func verifyCutoff(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks, head int) {
|
||||
t.Helper()
|
||||
|
|
|
|||
|
|
@ -2715,6 +2715,8 @@ func defaultTxPoolRapidConfig() txPoolRapidConfig {
|
|||
// TestSmallTxPool is not something to run in parallel as far it uses all CPUs
|
||||
// nolint:paralleltest
|
||||
func TestSmallTxPool(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Skip("a red test to be fixed")
|
||||
|
||||
cfg := defaultTxPoolRapidConfig()
|
||||
|
|
@ -2734,6 +2736,8 @@ func TestSmallTxPool(t *testing.T) {
|
|||
// This test is not something to run in parallel as far it uses all CPUs
|
||||
// nolint:paralleltest
|
||||
func TestBigTxPool(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Skip("a red test to be fixed")
|
||||
|
||||
cfg := defaultTxPoolRapidConfig()
|
||||
|
|
@ -2743,6 +2747,8 @@ func TestBigTxPool(t *testing.T) {
|
|||
|
||||
//nolint:gocognit,thelper
|
||||
func testPoolBatchInsert(t *testing.T, cfg txPoolRapidConfig) {
|
||||
t.Helper()
|
||||
|
||||
t.Parallel()
|
||||
|
||||
const debug = false
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ type StateDB interface {
|
|||
AddPreimage(common.Hash, []byte)
|
||||
|
||||
ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error
|
||||
|
||||
Finalise(bool)
|
||||
}
|
||||
|
||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
||||
|
|
|
|||
|
|
@ -5,18 +5,16 @@
|
|||
|
||||
- [Configuration file](./config.md)
|
||||
|
||||
## Deprecation notes
|
||||
## Additional notes
|
||||
|
||||
- The new entrypoint to run the Bor client is ```server```.
|
||||
|
||||
```
|
||||
$ bor server
|
||||
```
|
||||
```
|
||||
$ bor server <flags>
|
||||
```
|
||||
|
||||
- Toml files to configure nodes are being deprecated. Currently, we only allow for static and trusted nodes to be configured using toml files.
|
||||
- Toml files used earlier just to configure static/trusted nodes are being deprecated. Instead, a toml file now can be used instead of flags and can contain all configuration for the node to run. The link to a sample config file is given above. To simply run bor with a configuration file, the following command can be used.
|
||||
|
||||
```
|
||||
$ bor server --config ./legacy.toml
|
||||
```
|
||||
|
||||
- ```Admin```, ```Personal``` and account related endpoints in ```Eth``` are being removed from the JsonRPC interface. Some of this functionality will be moved to the new GRPC server for operational tasks.
|
||||
```
|
||||
$ bor server --config <path_to_config.toml>
|
||||
```
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ The ```bor server``` command runs the Bor client.
|
|||
|
||||
- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys
|
||||
|
||||
- ```cache.triesinmemory```: Number of block states (tries) to keep in memory (default = 128)
|
||||
|
||||
- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)
|
||||
|
||||
### JsonRPC Options
|
||||
|
|
@ -96,9 +98,7 @@ The ```bor server``` command runs the Bor client.
|
|||
|
||||
- ```http.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
|
||||
|
||||
- ```ws.corsdomain```: Comma separated list of domains from which to accept cross origin requests (browser enforced)
|
||||
|
||||
- ```ws.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
|
||||
- ```ws.origins```: Origins from which to accept websockets requests
|
||||
|
||||
- ```graphql.corsdomain```: Comma separated list of domains from which to accept cross origin requests (browser enforced)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ ethstats = ""
|
|||
["eth.requiredblocks"]
|
||||
|
||||
[p2p]
|
||||
maxpeers = 30
|
||||
maxpeers = 50
|
||||
maxpendpeers = 50
|
||||
bind = "0.0.0.0"
|
||||
port = 30303
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
TrieTimeLimit: config.TrieTimeout,
|
||||
SnapshotLimit: config.SnapshotCache,
|
||||
Preimages: config.Preimages,
|
||||
TriesInMemory: config.TriesInMemory,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -176,6 +176,7 @@ type Config struct {
|
|||
TrieTimeout time.Duration
|
||||
SnapshotCache int
|
||||
Preimages bool
|
||||
TriesInMemory uint64
|
||||
|
||||
// Mining options
|
||||
Miner miner.Config
|
||||
|
|
|
|||
|
|
@ -337,8 +337,7 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([
|
|||
return nil, errors.New("No chain config found. Proper PublicFilterAPI initialization required")
|
||||
}
|
||||
|
||||
// get sprint from bor config
|
||||
sprint := api.chainConfig.Bor.Sprint
|
||||
borConfig := api.chainConfig.Bor
|
||||
|
||||
var filter *Filter
|
||||
var borLogsFilter *BorBlockLogsFilter
|
||||
|
|
@ -347,7 +346,7 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([
|
|||
filter = NewBlockFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
|
||||
// Block bor filter
|
||||
if api.borLogs {
|
||||
borLogsFilter = NewBorBlockLogsFilter(api.backend, sprint, *crit.BlockHash, crit.Addresses, crit.Topics)
|
||||
borLogsFilter = NewBorBlockLogsFilter(api.backend, borConfig, *crit.BlockHash, crit.Addresses, crit.Topics)
|
||||
}
|
||||
} else {
|
||||
// Convert the RPC block numbers into internal representations
|
||||
|
|
@ -363,7 +362,7 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([
|
|||
filter = NewRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics)
|
||||
// Block bor filter
|
||||
if api.borLogs {
|
||||
borLogsFilter = NewBorBlockLogsRangeFilter(api.backend, sprint, begin, end, crit.Addresses, crit.Topics)
|
||||
borLogsFilter = NewBorBlockLogsRangeFilter(api.backend, borConfig, begin, end, crit.Addresses, crit.Topics)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -417,10 +416,20 @@ func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ty
|
|||
return nil, fmt.Errorf("filter not found")
|
||||
}
|
||||
|
||||
borConfig := api.chainConfig.Bor
|
||||
|
||||
var filter *Filter
|
||||
|
||||
var borLogsFilter *BorBlockLogsFilter
|
||||
|
||||
if f.crit.BlockHash != nil {
|
||||
// Block filter requested, construct a single-shot filter
|
||||
filter = NewBlockFilter(api.backend, *f.crit.BlockHash, f.crit.Addresses, f.crit.Topics)
|
||||
|
||||
// Block bor filter
|
||||
if api.borLogs {
|
||||
borLogsFilter = NewBorBlockLogsFilter(api.backend, borConfig, *f.crit.BlockHash, f.crit.Addresses, f.crit.Topics)
|
||||
}
|
||||
} else {
|
||||
// Convert the RPC block numbers into internal representations
|
||||
begin := rpc.LatestBlockNumber.Int64()
|
||||
|
|
@ -433,12 +442,27 @@ func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ty
|
|||
}
|
||||
// Construct the range filter
|
||||
filter = NewRangeFilter(api.backend, begin, end, f.crit.Addresses, f.crit.Topics)
|
||||
|
||||
if api.borLogs {
|
||||
borLogsFilter = NewBorBlockLogsRangeFilter(api.backend, borConfig, begin, end, f.crit.Addresses, f.crit.Topics)
|
||||
}
|
||||
}
|
||||
// Run the filter and return all the logs
|
||||
logs, err := filter.Logs(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if borLogsFilter != nil {
|
||||
// Run the filter and return all the logs
|
||||
borBlockLogs, err := borLogsFilter.Logs(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return returnLogs(types.MergeBorLogs(logs, borBlockLogs)), nil
|
||||
}
|
||||
|
||||
return returnLogs(logs), nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ func (api *PublicFilterAPI) GetBorBlockLogs(ctx context.Context, crit FilterCrit
|
|||
}
|
||||
|
||||
// get sprint from bor config
|
||||
sprint := api.chainConfig.Bor.Sprint
|
||||
borConfig := api.chainConfig.Bor
|
||||
|
||||
var filter *BorBlockLogsFilter
|
||||
if crit.BlockHash != nil {
|
||||
// Block filter requested, construct a single-shot filter
|
||||
filter = NewBorBlockLogsFilter(api.backend, sprint, *crit.BlockHash, crit.Addresses, crit.Topics)
|
||||
filter = NewBorBlockLogsFilter(api.backend, borConfig, *crit.BlockHash, crit.Addresses, crit.Topics)
|
||||
} else {
|
||||
// Convert the RPC block numbers into internal representations
|
||||
begin := rpc.LatestBlockNumber.Int64()
|
||||
|
|
@ -40,7 +40,7 @@ func (api *PublicFilterAPI) GetBorBlockLogs(ctx context.Context, crit FilterCrit
|
|||
end = crit.ToBlock.Int64()
|
||||
}
|
||||
// Construct the range filter
|
||||
filter = NewBorBlockLogsRangeFilter(api.backend, sprint, begin, end, crit.Addresses, crit.Topics)
|
||||
filter = NewBorBlockLogsRangeFilter(api.backend, borConfig, begin, end, crit.Addresses, crit.Topics)
|
||||
}
|
||||
|
||||
// Run the filter and return all the logs
|
||||
|
|
|
|||
|
|
@ -22,13 +22,14 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
// BorBlockLogsFilter can be used to retrieve and filter logs.
|
||||
type BorBlockLogsFilter struct {
|
||||
backend Backend
|
||||
sprint uint64
|
||||
backend Backend
|
||||
borConfig *params.BorConfig
|
||||
|
||||
db ethdb.Database
|
||||
addresses []common.Address
|
||||
|
|
@ -40,9 +41,9 @@ type BorBlockLogsFilter struct {
|
|||
|
||||
// NewBorBlockLogsRangeFilter creates a new filter which uses a bloom filter on blocks to
|
||||
// figure out whether a particular block is interesting or not.
|
||||
func NewBorBlockLogsRangeFilter(backend Backend, sprint uint64, begin, end int64, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||
func NewBorBlockLogsRangeFilter(backend Backend, borConfig *params.BorConfig, begin, end int64, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||
// Create a generic filter and convert it into a range filter
|
||||
filter := newBorBlockLogsFilter(backend, sprint, addresses, topics)
|
||||
filter := newBorBlockLogsFilter(backend, borConfig, addresses, topics)
|
||||
filter.begin = begin
|
||||
filter.end = end
|
||||
|
||||
|
|
@ -51,19 +52,19 @@ func NewBorBlockLogsRangeFilter(backend Backend, sprint uint64, begin, end int64
|
|||
|
||||
// NewBorBlockLogsFilter creates a new filter which directly inspects the contents of
|
||||
// a block to figure out whether it is interesting or not.
|
||||
func NewBorBlockLogsFilter(backend Backend, sprint uint64, block common.Hash, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||
func NewBorBlockLogsFilter(backend Backend, borConfig *params.BorConfig, block common.Hash, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||
// Create a generic filter and convert it into a block filter
|
||||
filter := newBorBlockLogsFilter(backend, sprint, addresses, topics)
|
||||
filter := newBorBlockLogsFilter(backend, borConfig, addresses, topics)
|
||||
filter.block = block
|
||||
return filter
|
||||
}
|
||||
|
||||
// newBorBlockLogsFilter creates a generic filter that can either filter based on a block hash,
|
||||
// or based on range queries. The search criteria needs to be explicitly set.
|
||||
func newBorBlockLogsFilter(backend Backend, sprint uint64, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||
func newBorBlockLogsFilter(backend Backend, borConfig *params.BorConfig, addresses []common.Address, topics [][]common.Hash) *BorBlockLogsFilter {
|
||||
return &BorBlockLogsFilter{
|
||||
backend: backend,
|
||||
sprint: sprint,
|
||||
borConfig: borConfig,
|
||||
addresses: addresses,
|
||||
topics: topics,
|
||||
db: backend.ChainDb(),
|
||||
|
|
@ -94,7 +95,7 @@ func (f *BorBlockLogsFilter) Logs(ctx context.Context) ([]*types.Log, error) {
|
|||
}
|
||||
|
||||
// adjust begin for sprint
|
||||
f.begin = currentSprintEnd(f.sprint, f.begin)
|
||||
f.begin = currentSprintEnd(f.borConfig.CalculateSprint(uint64(f.begin)), f.begin)
|
||||
|
||||
end := f.end
|
||||
if f.end == -1 {
|
||||
|
|
@ -110,7 +111,9 @@ func (f *BorBlockLogsFilter) Logs(ctx context.Context) ([]*types.Log, error) {
|
|||
func (f *BorBlockLogsFilter) unindexedLogs(ctx context.Context, end uint64) ([]*types.Log, error) {
|
||||
var logs []*types.Log
|
||||
|
||||
for ; f.begin <= int64(end); f.begin = f.begin + int64(f.sprint) {
|
||||
sprintLength := f.borConfig.CalculateSprint(uint64(f.begin))
|
||||
|
||||
for ; f.begin <= int64(end); f.begin = f.begin + int64(sprintLength) {
|
||||
header, err := f.backend.HeaderByNumber(ctx, rpc.BlockNumber(f.begin))
|
||||
if header == nil || err != nil {
|
||||
return logs, err
|
||||
|
|
@ -128,6 +131,7 @@ func (f *BorBlockLogsFilter) unindexedLogs(ctx context.Context, end uint64) ([]*
|
|||
return logs, err
|
||||
}
|
||||
logs = append(logs, found...)
|
||||
sprintLength = f.borConfig.CalculateSprint(uint64(f.begin))
|
||||
}
|
||||
return logs, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ func TestBorFilters(t *testing.T) {
|
|||
hash4 = common.BytesToHash([]byte("topic4"))
|
||||
db = NewMockDatabase(ctrl)
|
||||
|
||||
sprint = params.TestChainConfig.Bor.Sprint
|
||||
testBorConfig = params.TestChainConfig.Bor
|
||||
)
|
||||
|
||||
backend := NewMockBackend(ctrl)
|
||||
|
|
@ -74,7 +74,7 @@ func TestBorFilters(t *testing.T) {
|
|||
// Block 1
|
||||
backend.expectBorReceiptsFromMock([]*common.Hash{nil, &hash1, &hash2, &hash3, &hash4})
|
||||
|
||||
filter := NewBorBlockLogsRangeFilter(backend, sprint, 0, 18, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}})
|
||||
filter := NewBorBlockLogsRangeFilter(backend, testBorConfig, 0, 18, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}})
|
||||
logs, err := filter.Logs(context.Background())
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -88,7 +88,7 @@ func TestBorFilters(t *testing.T) {
|
|||
// Block 2
|
||||
backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash3})
|
||||
|
||||
filter = NewBorBlockLogsRangeFilter(backend, sprint, 990, 999, []common.Address{addr}, [][]common.Hash{{hash3}})
|
||||
filter = NewBorBlockLogsRangeFilter(backend, testBorConfig, 990, 999, []common.Address{addr}, [][]common.Hash{{hash3}})
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
|
||||
if len(logs) != 1 {
|
||||
|
|
@ -102,7 +102,7 @@ func TestBorFilters(t *testing.T) {
|
|||
// Block 3
|
||||
backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, &hash3})
|
||||
|
||||
filter = NewBorBlockLogsRangeFilter(backend, sprint, 992, 1000, []common.Address{addr}, [][]common.Hash{{hash3}})
|
||||
filter = NewBorBlockLogsRangeFilter(backend, testBorConfig, 992, 1000, []common.Address{addr}, [][]common.Hash{{hash3}})
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
|
||||
if len(logs) != 1 {
|
||||
|
|
@ -116,7 +116,7 @@ func TestBorFilters(t *testing.T) {
|
|||
// Block 4
|
||||
backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, nil, &hash3})
|
||||
|
||||
filter = NewBorBlockLogsRangeFilter(backend, sprint, 1, 16, []common.Address{addr}, [][]common.Hash{{hash1, hash2}})
|
||||
filter = NewBorBlockLogsRangeFilter(backend, testBorConfig, 1, 16, []common.Address{addr}, [][]common.Hash{{hash1, hash2}})
|
||||
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ func TestBorFilters(t *testing.T) {
|
|||
backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, nil, &hash3, &hash4, nil})
|
||||
|
||||
failHash := common.BytesToHash([]byte("fail"))
|
||||
filter = NewBorBlockLogsRangeFilter(backend, sprint, 0, 20, nil, [][]common.Hash{{failHash}})
|
||||
filter = NewBorBlockLogsRangeFilter(backend, testBorConfig, 0, 20, nil, [][]common.Hash{{failHash}})
|
||||
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
if len(logs) != 0 {
|
||||
|
|
@ -139,7 +139,7 @@ func TestBorFilters(t *testing.T) {
|
|||
backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, nil, &hash3, &hash4, nil})
|
||||
|
||||
failAddr := common.BytesToAddress([]byte("failmenow"))
|
||||
filter = NewBorBlockLogsRangeFilter(backend, sprint, 0, 20, []common.Address{failAddr}, nil)
|
||||
filter = NewBorBlockLogsRangeFilter(backend, testBorConfig, 0, 20, []common.Address{failAddr}, nil)
|
||||
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
if len(logs) != 0 {
|
||||
|
|
@ -149,7 +149,7 @@ func TestBorFilters(t *testing.T) {
|
|||
// Block 7
|
||||
backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, nil, &hash3, &hash4, nil})
|
||||
|
||||
filter = NewBorBlockLogsRangeFilter(backend, sprint, 0, 20, nil, [][]common.Hash{{failHash}, {hash1}})
|
||||
filter = NewBorBlockLogsRangeFilter(backend, testBorConfig, 0, 20, nil, [][]common.Hash{{failHash}, {hash1}})
|
||||
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
if len(logs) != 0 {
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
|
|||
// return downloader.SnapSync, td
|
||||
// }
|
||||
// }
|
||||
// Nope, we're really full syncing
|
||||
// // Nope, we're really full syncing
|
||||
// head := cs.handler.chain.CurrentBlock()
|
||||
// td := cs.handler.chain.GetTd(head.Hash(), head.NumberU64())
|
||||
// return downloader.FullSync, td
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/consensus/bor/statefull"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
|
|
@ -63,6 +65,8 @@ const (
|
|||
defaultTracechainMemLimit = common.StorageSize(500 * 1024 * 1024)
|
||||
)
|
||||
|
||||
var defaultBorTraceEnabled = newBoolPtr(false)
|
||||
|
||||
// Backend interface provides the common API services (that are provided by
|
||||
// both full and light clients) with access to necessary functions.
|
||||
type Backend interface {
|
||||
|
|
@ -80,6 +84,9 @@ type Backend interface {
|
|||
// so this method should be called with the parent.
|
||||
StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error)
|
||||
StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error)
|
||||
|
||||
// Bor related APIs
|
||||
GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
||||
}
|
||||
|
||||
// API is the collection of tracing APIs exposed over the private debugging endpoint.
|
||||
|
|
@ -164,12 +171,33 @@ func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber
|
|||
return api.blockByHash(ctx, hash)
|
||||
}
|
||||
|
||||
// returns block transactions along with state-sync transaction if present
|
||||
func (api *API) getAllBlockTransactions(ctx context.Context, block *types.Block) (types.Transactions, bool) {
|
||||
txs := block.Transactions()
|
||||
|
||||
stateSyncPresent := false
|
||||
|
||||
borReceipt := rawdb.ReadBorReceipt(api.backend.ChainDb(), block.Hash(), block.NumberU64())
|
||||
if borReceipt != nil {
|
||||
txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash()))
|
||||
if txHash != (common.Hash{}) {
|
||||
borTx, _, _, _, _ := api.backend.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash())
|
||||
txs = append(txs, borTx)
|
||||
stateSyncPresent = true
|
||||
}
|
||||
}
|
||||
|
||||
return txs, stateSyncPresent
|
||||
}
|
||||
|
||||
// TraceConfig holds extra parameters to trace functions.
|
||||
type TraceConfig struct {
|
||||
*logger.Config
|
||||
Tracer *string
|
||||
Timeout *string
|
||||
Reexec *uint64
|
||||
Tracer *string
|
||||
Timeout *string
|
||||
Reexec *uint64
|
||||
BorTraceEnabled *bool
|
||||
BorTx *bool
|
||||
}
|
||||
|
||||
// TraceCallConfig is the config for traceCall API. It holds one more
|
||||
|
|
@ -185,8 +213,9 @@ type TraceCallConfig struct {
|
|||
// StdTraceConfig holds extra parameters to standard-json trace functions.
|
||||
type StdTraceConfig struct {
|
||||
logger.Config
|
||||
Reexec *uint64
|
||||
TxHash common.Hash
|
||||
Reexec *uint64
|
||||
TxHash common.Hash
|
||||
BorTraceEnabled *bool
|
||||
}
|
||||
|
||||
// txTraceResult is the result of a single transaction trace.
|
||||
|
|
@ -240,6 +269,16 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf
|
|||
// executes all the transactions contained within. The return value will be one item
|
||||
// per transaction, dependent on the requested tracer.
|
||||
func (api *API) traceChain(ctx context.Context, start, end *types.Block, config *TraceConfig) (*rpc.Subscription, error) {
|
||||
if config == nil {
|
||||
config = &TraceConfig{
|
||||
BorTraceEnabled: defaultBorTraceEnabled,
|
||||
BorTx: newBoolPtr(false),
|
||||
}
|
||||
}
|
||||
|
||||
if config.BorTraceEnabled == nil {
|
||||
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||
}
|
||||
// Tracing a chain is a **long** operation, only do with subscriptions
|
||||
notifier, supported := rpc.NotifierFromContext(ctx)
|
||||
if !supported {
|
||||
|
|
@ -274,19 +313,39 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
|
|||
signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number())
|
||||
blockCtx := core.NewEVMBlockContext(task.block.Header(), api.chainContext(localctx), nil)
|
||||
// Trace all the transactions contained within
|
||||
for i, tx := range task.block.Transactions() {
|
||||
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, task.block)
|
||||
if !*config.BorTraceEnabled && stateSyncPresent {
|
||||
txs = txs[:len(txs)-1]
|
||||
stateSyncPresent = false
|
||||
}
|
||||
|
||||
for i, tx := range txs {
|
||||
msg, _ := tx.AsMessage(signer, task.block.BaseFee())
|
||||
txctx := &Context{
|
||||
BlockHash: task.block.Hash(),
|
||||
TxIndex: i,
|
||||
TxHash: tx.Hash(),
|
||||
}
|
||||
res, err := api.traceTx(localctx, msg, txctx, blockCtx, task.statedb, config)
|
||||
|
||||
var res interface{}
|
||||
|
||||
var err error
|
||||
|
||||
if stateSyncPresent && i == len(txs)-1 {
|
||||
if *config.BorTraceEnabled {
|
||||
config.BorTx = newBoolPtr(true)
|
||||
res, err = api.traceTx(localctx, msg, txctx, blockCtx, task.statedb, config)
|
||||
}
|
||||
} else {
|
||||
res, err = api.traceTx(localctx, msg, txctx, blockCtx, task.statedb, config)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
task.results[i] = &txTraceResult{Error: err.Error()}
|
||||
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
||||
break
|
||||
}
|
||||
|
||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||
task.statedb.Finalise(api.backend.ChainConfig().IsEIP158(task.block.Number()))
|
||||
task.results[i] = &txTraceResult{Result: res}
|
||||
|
|
@ -430,6 +489,11 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
|
|||
return sub, nil
|
||||
}
|
||||
|
||||
func newBoolPtr(bb bool) *bool {
|
||||
b := bb
|
||||
return &b
|
||||
}
|
||||
|
||||
// TraceBlockByNumber returns the structured logs created during the execution of
|
||||
// EVM and returns them as a JSON object.
|
||||
func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) {
|
||||
|
|
@ -492,9 +556,35 @@ func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash,
|
|||
return api.standardTraceBlockToFile(ctx, block, config)
|
||||
}
|
||||
|
||||
func prepareCallMessage(msg core.Message) statefull.Callmsg {
|
||||
return statefull.Callmsg{
|
||||
CallMsg: ethereum.CallMsg{
|
||||
From: msg.From(),
|
||||
To: msg.To(),
|
||||
Gas: msg.Gas(),
|
||||
GasPrice: msg.GasPrice(),
|
||||
GasFeeCap: msg.GasFeeCap(),
|
||||
GasTipCap: msg.GasTipCap(),
|
||||
Value: msg.Value(),
|
||||
Data: msg.Data(),
|
||||
AccessList: msg.AccessList(),
|
||||
}}
|
||||
}
|
||||
|
||||
// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
|
||||
// of intermediate roots: the stateroot after each transaction.
|
||||
func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
|
||||
if config == nil {
|
||||
config = &TraceConfig{
|
||||
BorTraceEnabled: defaultBorTraceEnabled,
|
||||
BorTx: newBoolPtr(false),
|
||||
}
|
||||
}
|
||||
|
||||
if config.BorTraceEnabled == nil {
|
||||
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||
}
|
||||
|
||||
block, _ := api.blockByHash(ctx, hash)
|
||||
if block == nil {
|
||||
// Check in the bad blocks
|
||||
|
|
@ -525,23 +615,47 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
|||
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
||||
)
|
||||
for i, tx := range block.Transactions() {
|
||||
|
||||
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, block)
|
||||
for i, tx := range txs {
|
||||
var (
|
||||
msg, _ = tx.AsMessage(signer, block.BaseFee())
|
||||
txContext = core.NewEVMTxContext(msg)
|
||||
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
|
||||
)
|
||||
statedb.Prepare(tx.Hash(), i)
|
||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
||||
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
||||
// We intentionally don't return the error here: if we do, then the RPC server will not
|
||||
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
||||
// be included, but still want the intermediate roots that led to that point.
|
||||
// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
|
||||
// executable.
|
||||
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
|
||||
return roots, nil
|
||||
//nolint: nestif
|
||||
if stateSyncPresent && i == len(txs)-1 {
|
||||
if *config.BorTraceEnabled {
|
||||
callmsg := prepareCallMessage(msg)
|
||||
|
||||
if _, err := statefull.ApplyMessage(ctx, callmsg, statedb, block.Header(), api.backend.ChainConfig(), api.chainContext(ctx)); err != nil {
|
||||
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
||||
// We intentionally don't return the error here: if we do, then the RPC server will not
|
||||
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
||||
// be included, but still want the intermediate roots that led to that point.
|
||||
// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
|
||||
// executable.
|
||||
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
|
||||
return roots, nil
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
||||
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
||||
// We intentionally don't return the error here: if we do, then the RPC server will not
|
||||
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
||||
// be included, but still want the intermediate roots that led to that point.
|
||||
// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
|
||||
// executable.
|
||||
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// calling IntermediateRoot will internally call Finalize on the state
|
||||
// so any modifications are written to the trie
|
||||
roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects))
|
||||
|
|
@ -564,6 +678,18 @@ func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Has
|
|||
// executes all the transactions contained within. The return value will be one item
|
||||
// per transaction, dependent on the requestd tracer.
|
||||
func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) {
|
||||
|
||||
if config == nil {
|
||||
config = &TraceConfig{
|
||||
BorTraceEnabled: defaultBorTraceEnabled,
|
||||
BorTx: newBoolPtr(false),
|
||||
}
|
||||
}
|
||||
|
||||
if config.BorTraceEnabled == nil {
|
||||
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||
}
|
||||
|
||||
if block.NumberU64() == 0 {
|
||||
return nil, errors.New("genesis is not traceable")
|
||||
}
|
||||
|
|
@ -581,9 +707,9 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
|||
}
|
||||
// Execute all the transaction contained within the block concurrently
|
||||
var (
|
||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
||||
txs = block.Transactions()
|
||||
results = make([]*txTraceResult, len(txs))
|
||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
||||
txs, stateSyncPresent = api.getAllBlockTransactions(ctx, block)
|
||||
results = make([]*txTraceResult, len(txs))
|
||||
|
||||
pend = new(sync.WaitGroup)
|
||||
jobs = make(chan *txTraceTask, len(txs))
|
||||
|
|
@ -606,7 +732,21 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
|||
TxIndex: task.index,
|
||||
TxHash: txs[task.index].Hash(),
|
||||
}
|
||||
res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
||||
|
||||
var res interface{}
|
||||
|
||||
var err error
|
||||
|
||||
if stateSyncPresent && task.index == len(txs)-1 {
|
||||
if *config.BorTraceEnabled {
|
||||
config.BorTx = newBoolPtr(true)
|
||||
res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
||||
}
|
||||
if err != nil {
|
||||
results[task.index] = &txTraceResult{Error: err.Error()}
|
||||
continue
|
||||
|
|
@ -625,11 +765,26 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
|||
// Generate the next state snapshot fast without tracing
|
||||
msg, _ := tx.AsMessage(signer, block.BaseFee())
|
||||
statedb.Prepare(tx.Hash(), i)
|
||||
|
||||
vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{})
|
||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
||||
failed = err
|
||||
break
|
||||
//nolint: nestif
|
||||
if stateSyncPresent && i == len(txs)-1 {
|
||||
if *config.BorTraceEnabled {
|
||||
callmsg := prepareCallMessage(msg)
|
||||
if _, err := statefull.ApplyBorMessage(*vmenv, callmsg); err != nil {
|
||||
failed = err
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
||||
failed = err
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the state so any modifications are written to the trie
|
||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
||||
|
|
@ -641,16 +796,30 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
|||
if failed != nil {
|
||||
return nil, failed
|
||||
}
|
||||
return results, nil
|
||||
|
||||
if !*config.BorTraceEnabled && stateSyncPresent {
|
||||
return results[:len(results)-1], nil
|
||||
} else {
|
||||
return results, nil
|
||||
}
|
||||
}
|
||||
|
||||
// standardTraceBlockToFile configures a new tracer which uses standard JSON output,
|
||||
// and traces either a full block or an individual transaction. The return value will
|
||||
// be one filename per transaction traced.
|
||||
func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) {
|
||||
if config == nil {
|
||||
config = &StdTraceConfig{
|
||||
BorTraceEnabled: defaultBorTraceEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
if config.BorTraceEnabled == nil {
|
||||
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||
}
|
||||
// If we're tracing a single transaction, make sure it's present
|
||||
if config != nil && config.TxHash != (common.Hash{}) {
|
||||
if !containsTx(block, config.TxHash) {
|
||||
if !api.containsTx(ctx, block, config.TxHash) {
|
||||
return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash)
|
||||
}
|
||||
}
|
||||
|
|
@ -705,7 +874,14 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
|||
canon = false
|
||||
}
|
||||
}
|
||||
for i, tx := range block.Transactions() {
|
||||
|
||||
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, block)
|
||||
if !*config.BorTraceEnabled && stateSyncPresent {
|
||||
txs = txs[:len(txs)-1]
|
||||
stateSyncPresent = false
|
||||
}
|
||||
|
||||
for i, tx := range txs {
|
||||
// Prepare the trasaction for un-traced execution
|
||||
var (
|
||||
msg, _ = tx.AsMessage(signer, block.BaseFee())
|
||||
|
|
@ -739,10 +915,23 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
|||
// Execute the transaction and flush any traces to disk
|
||||
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
||||
statedb.Prepare(tx.Hash(), i)
|
||||
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
|
||||
if writer != nil {
|
||||
writer.Flush()
|
||||
//nolint: nestif
|
||||
if stateSyncPresent && i == len(txs)-1 {
|
||||
if *config.BorTraceEnabled {
|
||||
callmsg := prepareCallMessage(msg)
|
||||
_, err = statefull.ApplyBorMessage(*vmenv, callmsg)
|
||||
|
||||
if writer != nil {
|
||||
writer.Flush()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
|
||||
if writer != nil {
|
||||
writer.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
if dump != nil {
|
||||
dump.Close()
|
||||
log.Info("Wrote standard trace", "file", dump.Name())
|
||||
|
|
@ -764,8 +953,9 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
|||
|
||||
// containsTx reports whether the transaction with a certain hash
|
||||
// is contained within the specified block.
|
||||
func containsTx(block *types.Block, hash common.Hash) bool {
|
||||
for _, tx := range block.Transactions() {
|
||||
func (api *API) containsTx(ctx context.Context, block *types.Block, hash common.Hash) bool {
|
||||
txs, _ := api.getAllBlockTransactions(ctx, block)
|
||||
for _, tx := range txs {
|
||||
if tx.Hash() == hash {
|
||||
return true
|
||||
}
|
||||
|
|
@ -776,6 +966,17 @@ func containsTx(block *types.Block, hash common.Hash) bool {
|
|||
// TraceTransaction returns the structured logs created during the execution of EVM
|
||||
// and returns them as a JSON object.
|
||||
func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
|
||||
if config == nil {
|
||||
config = &TraceConfig{
|
||||
BorTraceEnabled: defaultBorTraceEnabled,
|
||||
BorTx: newBoolPtr(false),
|
||||
}
|
||||
}
|
||||
|
||||
if config.BorTraceEnabled == nil {
|
||||
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||
}
|
||||
|
||||
tx, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
|
||||
if tx == nil {
|
||||
// For BorTransaction, there will be no trace available
|
||||
|
|
@ -811,6 +1012,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
|
|||
TxIndex: int(index),
|
||||
TxHash: hash,
|
||||
}
|
||||
|
||||
return api.traceTx(ctx, msg, txctx, vmctx, statedb, config)
|
||||
}
|
||||
|
||||
|
|
@ -865,6 +1067,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
|||
Reexec: config.Reexec,
|
||||
}
|
||||
}
|
||||
|
||||
return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig)
|
||||
}
|
||||
|
||||
|
|
@ -872,6 +1075,18 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
|||
// executes the given message in the provided environment. The return value will
|
||||
// be tracer dependent.
|
||||
func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
|
||||
|
||||
if config == nil {
|
||||
config = &TraceConfig{
|
||||
BorTraceEnabled: defaultBorTraceEnabled,
|
||||
BorTx: newBoolPtr(false),
|
||||
}
|
||||
}
|
||||
|
||||
if config.BorTraceEnabled == nil {
|
||||
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||
}
|
||||
|
||||
// Assemble the structured logger or the JavaScript tracer
|
||||
var (
|
||||
tracer vm.EVMLogger
|
||||
|
|
@ -911,9 +1126,22 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex
|
|||
// Call Prepare to clear out the statedb access list
|
||||
statedb.Prepare(txctx.TxHash, txctx.TxIndex)
|
||||
|
||||
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||
var result *core.ExecutionResult
|
||||
|
||||
if config.BorTx == nil {
|
||||
config.BorTx = newBoolPtr(false)
|
||||
}
|
||||
|
||||
if *config.BorTx {
|
||||
callmsg := prepareCallMessage(message)
|
||||
if result, err = statefull.ApplyBorMessage(*vmenv, callmsg); err != nil {
|
||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||
}
|
||||
} else {
|
||||
result, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Depending on the tracer type, format and return the output.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus/bor/statefull"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
|
@ -68,14 +69,14 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
|||
|
||||
// Execute all the transaction contained within the block concurrently
|
||||
var (
|
||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
||||
txs = block.Transactions()
|
||||
deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number())
|
||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
||||
txs, stateSyncPresent = api.getAllBlockTransactions(ctx, block)
|
||||
deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number())
|
||||
)
|
||||
|
||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||
|
||||
traceTxn := func(indx int, tx *types.Transaction) *TxTraceResult {
|
||||
traceTxn := func(indx int, tx *types.Transaction, borTx bool) *TxTraceResult {
|
||||
message, _ := tx.AsMessage(signer, block.BaseFee())
|
||||
txContext := core.NewEVMTxContext(message)
|
||||
|
||||
|
|
@ -88,7 +89,15 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
|||
// Not sure if we need to do this
|
||||
statedb.Prepare(tx.Hash(), indx)
|
||||
|
||||
execRes, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
||||
var execRes *core.ExecutionResult
|
||||
|
||||
if borTx {
|
||||
callmsg := prepareCallMessage(message)
|
||||
execRes, err = statefull.ApplyBorMessage(*vmenv, callmsg)
|
||||
} else {
|
||||
execRes, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return &TxTraceResult{
|
||||
Error: err.Error(),
|
||||
|
|
@ -115,7 +124,11 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
|||
}
|
||||
|
||||
for indx, tx := range txs {
|
||||
res.Transactions = append(res.Transactions, traceTxn(indx, tx))
|
||||
if stateSyncPresent && indx == len(txs)-1 {
|
||||
res.Transactions = append(res.Transactions, traceTxn(indx, tx, true))
|
||||
} else {
|
||||
res.Transactions = append(res.Transactions, traceTxn(indx, tx, false))
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
|
|
|||
|
|
@ -176,6 +176,11 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
|
|||
return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
||||
}
|
||||
|
||||
func (b *testBackend) GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
||||
tx, blockHash, blockNumber, index := rawdb.ReadBorTransactionWithBlockHash(b.ChainDb(), txHash, blockHash)
|
||||
return tx, blockHash, blockNumber, index, nil
|
||||
}
|
||||
|
||||
func TestTraceCall(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
|||
6
go.mod
6
go.mod
|
|
@ -5,7 +5,6 @@ go 1.19
|
|||
require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0
|
||||
github.com/BurntSushi/toml v1.1.0
|
||||
github.com/JekaMas/crand v1.0.1
|
||||
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d
|
||||
github.com/VictoriaMetrics/fastcache v1.6.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.2.0
|
||||
|
|
@ -47,6 +46,7 @@ require (
|
|||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
github.com/karalabe/usb v0.0.2
|
||||
github.com/maticnetwork/crand v1.0.2
|
||||
github.com/maticnetwork/polyproto v0.0.2
|
||||
github.com/mattn/go-colorable v0.1.8
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
|
|
@ -71,7 +71,7 @@ require (
|
|||
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10
|
||||
golang.org/x/text v0.3.7
|
||||
golang.org/x/text v0.3.8
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||
golang.org/x/tools v0.1.12
|
||||
gonum.org/v1/gonum v0.11.0
|
||||
|
|
@ -141,3 +141,5 @@ require (
|
|||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/Masterminds/goutils => github.com/Masterminds/goutils v1.1.1
|
||||
|
|
|
|||
11
go.sum
11
go.sum
|
|
@ -29,12 +29,10 @@ github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I
|
|||
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/JekaMas/crand v1.0.1 h1:FMPxkUQqH/hExl0aUXsr0UCGYZ4lJH9IJ5H/KbM6Y9A=
|
||||
github.com/JekaMas/crand v1.0.1/go.mod h1:GGzGpMCht/tbaNQ5A4kSiKSqEoNAhhyTfSDQyIENBQU=
|
||||
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d h1:RO27lgfZF8s9lZ3pWyzc0gCE0RZC+6/PXbRjAa0CNp8=
|
||||
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d/go.mod h1:romz7UPgSYhfJkKOalzEEyV6sWtt/eAEm0nX2aOrod0=
|
||||
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
|
||||
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
|
||||
|
|
@ -345,6 +343,8 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2
|
|||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/maticnetwork/crand v1.0.2 h1:Af0tAivC8zrxXDpGWNWVT/0s1fOz8w0eRbahZgURS8I=
|
||||
github.com/maticnetwork/crand v1.0.2/go.mod h1:/NRNL3bj2eYdqpWmoIP5puxndTpi0XRxpj5ZKxfHjyg=
|
||||
github.com/maticnetwork/polyproto v0.0.2 h1:cPxuxbIDItdwGnucc3lZB58U8Zfe1mH73PWTGd15554=
|
||||
github.com/maticnetwork/polyproto v0.0.2/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
|
||||
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||
|
|
@ -667,8 +667,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
|
|
|||
15
integration-tests/bor_health.sh
Normal file
15
integration-tests/bor_health.sh
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
while true
|
||||
do
|
||||
peers=$(docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'admin.peers'")
|
||||
block=$(docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'eth.blockNumber'")
|
||||
|
||||
if [[ -n "$peers" ]] && [[ -n "$block" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo $peers
|
||||
echo $block
|
||||
|
|
@ -3,33 +3,42 @@ set -e
|
|||
|
||||
balanceInit=$(docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'Math.round(web3.fromWei(eth.getBalance(eth.accounts[0])))'")
|
||||
|
||||
delay=600
|
||||
stateSyncFound="false"
|
||||
checkpointFound="false"
|
||||
SECONDS=0
|
||||
start_time=$SECONDS
|
||||
|
||||
echo "Wait ${delay} seconds for state-sync..."
|
||||
sleep $delay
|
||||
while true
|
||||
do
|
||||
|
||||
balance=$(docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'Math.round(web3.fromWei(eth.getBalance(eth.accounts[0])))'")
|
||||
|
||||
if ! [[ "$balance" =~ ^[0-9]+$ ]]; then
|
||||
echo "Something is wrong! Can't find the balance of first account in bor network."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
balance=$(docker exec bor0 bash -c "bor attach /root/.bor/data/bor.ipc -exec 'Math.round(web3.fromWei(eth.getBalance(eth.accounts[0])))'")
|
||||
if (( $balance > $balanceInit )); then
|
||||
if [ $stateSyncFound != "true" ]; then
|
||||
stateSyncTime=$(( SECONDS - start_time ))
|
||||
stateSyncFound="true"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [[ "$balance" =~ ^[0-9]+$ ]]; then
|
||||
echo "Something is wrong! Can't find the balance of first account in bor network."
|
||||
exit 1
|
||||
fi
|
||||
checkpointID=$(curl -sL http://localhost:1317/checkpoints/latest | jq .result.id)
|
||||
|
||||
echo "Found matic balance on account[0]: " $balance
|
||||
if [ $checkpointID != "null" ]; then
|
||||
if [ $checkpointFound != "true" ]; then
|
||||
checkpointTime=$(( SECONDS - start_time ))
|
||||
checkpointFound="true"
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( $balance <= $balanceInit )); then
|
||||
echo "Balance in bor network has not increased. This indicates that something is wrong with state sync."
|
||||
exit 1
|
||||
fi
|
||||
if [ $stateSyncFound == "true" ] && [ $checkpointFound == "true" ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
checkpointID=$(curl -sL http://localhost:1317/checkpoints/latest | jq .result.id)
|
||||
|
||||
if [ $checkpointID == "null" ]; then
|
||||
echo "Something is wrong! Could not find any checkpoint."
|
||||
exit 1
|
||||
else
|
||||
echo "Found checkpoint ID:" $checkpointID
|
||||
fi
|
||||
|
||||
echo "All tests have passed!"
|
||||
done
|
||||
echo "Both state sync and checkpoint went through. All tests have passed!"
|
||||
echo "Time taken for state sync: $(printf '%02dm:%02ds\n' $(($stateSyncTime%3600/60)) $(($stateSyncTime%60)))"
|
||||
echo "Time taken for checkpoint: $(printf '%02dm:%02ds\n' $(($checkpointTime%3600/60)) $(($checkpointTime%60)))"
|
||||
|
|
|
|||
|
|
@ -29,12 +29,16 @@ var mainnetBor = &Chain{
|
|||
BerlinBlock: big.NewInt(14750000),
|
||||
LondonBlock: big.NewInt(23850000),
|
||||
Bor: ¶ms.BorConfig{
|
||||
JaipurBlock: 23850000,
|
||||
JaipurBlock: big.NewInt(23850000),
|
||||
Period: map[string]uint64{
|
||||
"0": 2,
|
||||
},
|
||||
ProducerDelay: 6,
|
||||
Sprint: 64,
|
||||
ProducerDelay: map[string]uint64{
|
||||
"0": 6,
|
||||
},
|
||||
Sprint: map[string]uint64{
|
||||
"0": 64,
|
||||
},
|
||||
BackupMultiplier: map[string]uint64{
|
||||
"0": 2,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,16 +29,25 @@ var mumbaiTestnet = &Chain{
|
|||
BerlinBlock: big.NewInt(13996000),
|
||||
LondonBlock: big.NewInt(22640000),
|
||||
Bor: ¶ms.BorConfig{
|
||||
JaipurBlock: 22770000,
|
||||
JaipurBlock: big.NewInt(22770000),
|
||||
DelhiBlock: big.NewInt(29638656),
|
||||
Period: map[string]uint64{
|
||||
"0": 2,
|
||||
"25275000": 5,
|
||||
"29638656": 2,
|
||||
},
|
||||
ProducerDelay: map[string]uint64{
|
||||
"0": 6,
|
||||
"29638656": 4,
|
||||
},
|
||||
Sprint: map[string]uint64{
|
||||
"0": 64,
|
||||
"29638656": 16,
|
||||
},
|
||||
ProducerDelay: 6,
|
||||
Sprint: 64,
|
||||
BackupMultiplier: map[string]uint64{
|
||||
"0": 2,
|
||||
"25275000": 5,
|
||||
"29638656": 2,
|
||||
},
|
||||
ValidatorContract: "0x0000000000000000000000000000000000001000",
|
||||
StateReceiverContract: "0x0000000000000000000000000000000000001001",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -18,12 +18,22 @@
|
|||
"londonBlock":13996000,
|
||||
"bor":{
|
||||
"period":{
|
||||
"0":2
|
||||
"0":2,
|
||||
"25275000": 5,
|
||||
"29638656": 2
|
||||
},
|
||||
"producerDelay":{
|
||||
"0": 6,
|
||||
"29638656": 4
|
||||
},
|
||||
"sprint":{
|
||||
"0": 64,
|
||||
"29638656": 16
|
||||
},
|
||||
"producerDelay":6,
|
||||
"sprint":64,
|
||||
"backupMultiplier":{
|
||||
"0":2
|
||||
"0": 2,
|
||||
"25275000": 5,
|
||||
"29638656": 2
|
||||
},
|
||||
"validatorContract":"0x0000000000000000000000000000000000001000",
|
||||
"stateReceiverContract":"0x0000000000000000000000000000000000001001",
|
||||
|
|
@ -39,7 +49,8 @@
|
|||
"burntContract":{
|
||||
"22640000":"0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"
|
||||
},
|
||||
"jaipurBlock":22770000
|
||||
"jaipurBlock":22770000,
|
||||
"delhiBlock": 29638656
|
||||
}
|
||||
},
|
||||
"nonce":"0x0",
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func (c *Command) MarkDown() string {
|
|||
// Help implements the cli.Command interface
|
||||
func (c *Command) Help() string {
|
||||
return `Usage: bor [options]
|
||||
|
||||
|
||||
Run the Bor server.
|
||||
` + c.Flags().Help()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,6 +266,9 @@ type APIConfig struct {
|
|||
|
||||
// Cors is the list of Cors endpoints
|
||||
Cors []string `hcl:"corsdomain,optional" toml:"corsdomain,optional"`
|
||||
|
||||
// Origins is the list of endpoints to accept requests from (only consumed for websockets)
|
||||
Origins []string `hcl:"origins,optional" toml:"origins,optional"`
|
||||
}
|
||||
|
||||
type GpoConfig struct {
|
||||
|
|
@ -364,6 +367,9 @@ type CacheConfig struct {
|
|||
|
||||
// TxLookupLimit sets the maximum number of blocks from head whose tx indices are reserved.
|
||||
TxLookupLimit uint64 `hcl:"txlookuplimit,optional" toml:"txlookuplimit,optional"`
|
||||
|
||||
// Number of block states to keep in memory (default = 128)
|
||||
TriesInMemory uint64 `hcl:"triesinmemory,optional" toml:"triesinmemory,optional"`
|
||||
}
|
||||
|
||||
type AccountsConfig struct {
|
||||
|
|
@ -399,7 +405,7 @@ func DefaultConfig() *Config {
|
|||
LogLevel: "INFO",
|
||||
DataDir: DefaultDataDir(),
|
||||
P2P: &P2PConfig{
|
||||
MaxPeers: 30,
|
||||
MaxPeers: 50,
|
||||
MaxPendPeers: 50,
|
||||
Bind: "0.0.0.0",
|
||||
Port: 30303,
|
||||
|
|
@ -470,8 +476,7 @@ func DefaultConfig() *Config {
|
|||
Prefix: "",
|
||||
Host: "localhost",
|
||||
API: []string{"net", "web3"},
|
||||
Cors: []string{"localhost"},
|
||||
VHost: []string{"localhost"},
|
||||
Origins: []string{"localhost"},
|
||||
},
|
||||
Graphql: &APIConfig{
|
||||
Enabled: false,
|
||||
|
|
@ -509,6 +514,7 @@ func DefaultConfig() *Config {
|
|||
NoPrefetch: false,
|
||||
Preimages: false,
|
||||
TxLookupLimit: 2350000,
|
||||
TriesInMemory: 128,
|
||||
},
|
||||
Accounts: &AccountsConfig{
|
||||
Unlock: []string{},
|
||||
|
|
@ -926,7 +932,7 @@ func (c *Config) buildNode() (*node.Config, error) {
|
|||
HTTPVirtualHosts: c.JsonRPC.Http.VHost,
|
||||
HTTPPathPrefix: c.JsonRPC.Http.Prefix,
|
||||
WSModules: c.JsonRPC.Ws.API,
|
||||
WSOrigins: c.JsonRPC.Ws.Cors,
|
||||
WSOrigins: c.JsonRPC.Ws.Origins,
|
||||
WSPathPrefix: c.JsonRPC.Ws.Prefix,
|
||||
GraphQLCors: c.JsonRPC.Graphql.Cors,
|
||||
GraphQLVirtualHosts: c.JsonRPC.Graphql.VHost,
|
||||
|
|
|
|||
|
|
@ -304,6 +304,13 @@ func (c *Command) Flags() *flagset.Flagset {
|
|||
Default: c.cliConfig.Cache.Preimages,
|
||||
Group: "Cache",
|
||||
})
|
||||
f.Uint64Flag(&flagset.Uint64Flag{
|
||||
Name: "cache.triesinmemory",
|
||||
Usage: "Number of block states (tries) to keep in memory (default = 128)",
|
||||
Value: &c.cliConfig.Cache.TriesInMemory,
|
||||
Default: c.cliConfig.Cache.TriesInMemory,
|
||||
Group: "Cache",
|
||||
})
|
||||
f.Uint64Flag(&flagset.Uint64Flag{
|
||||
Name: "txlookuplimit",
|
||||
Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)",
|
||||
|
|
@ -356,17 +363,10 @@ func (c *Command) Flags() *flagset.Flagset {
|
|||
Group: "JsonRPC",
|
||||
})
|
||||
f.SliceStringFlag(&flagset.SliceStringFlag{
|
||||
Name: "ws.corsdomain",
|
||||
Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
|
||||
Value: &c.cliConfig.JsonRPC.Ws.Cors,
|
||||
Default: c.cliConfig.JsonRPC.Ws.Cors,
|
||||
Group: "JsonRPC",
|
||||
})
|
||||
f.SliceStringFlag(&flagset.SliceStringFlag{
|
||||
Name: "ws.vhosts",
|
||||
Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
|
||||
Value: &c.cliConfig.JsonRPC.Ws.VHost,
|
||||
Default: c.cliConfig.JsonRPC.Ws.VHost,
|
||||
Name: "ws.origins",
|
||||
Usage: "Origins from which to accept websockets requests",
|
||||
Value: &c.cliConfig.JsonRPC.Ws.Origins,
|
||||
Default: c.cliConfig.JsonRPC.Ws.Origins,
|
||||
Group: "JsonRPC",
|
||||
})
|
||||
f.SliceStringFlag(&flagset.SliceStringFlag{
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@ import (
|
|||
"github.com/ethereum/go-ethereum/metrics/influxdb"
|
||||
"github.com/ethereum/go-ethereum/metrics/prometheus"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
|
||||
// Force-load the tracer engines to trigger registration
|
||||
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
||||
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
|
|
@ -253,6 +257,12 @@ func (s *Server) Stop() {
|
|||
}
|
||||
|
||||
func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error {
|
||||
// Check the global metrics if they're matching with the provided config
|
||||
if metrics.Enabled != config.Enabled || metrics.EnabledExpensive != config.Expensive {
|
||||
log.Warn("Metric misconfiguration, some of them might not be visible")
|
||||
}
|
||||
|
||||
// Update the values anyways (for services which don't need immediate attention)
|
||||
metrics.Enabled = config.Enabled
|
||||
metrics.EnabledExpensive = config.Expensive
|
||||
|
||||
|
|
@ -263,6 +273,10 @@ func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error
|
|||
|
||||
log.Info("Enabling metrics collection")
|
||||
|
||||
if metrics.EnabledExpensive {
|
||||
log.Info("Enabling expensive metrics collection")
|
||||
}
|
||||
|
||||
// influxdb
|
||||
if v1Enabled, v2Enabled := config.InfluxDB.V1Enabled, config.InfluxDB.V2Enabled; v1Enabled || v2Enabled {
|
||||
if v1Enabled && v2Enabled {
|
||||
|
|
|
|||
|
|
@ -1615,6 +1615,26 @@ type PublicTransactionPoolAPI struct {
|
|||
signer types.Signer
|
||||
}
|
||||
|
||||
// returns block transactions along with state-sync transaction if present
|
||||
// nolint: unparam
|
||||
func (api *PublicTransactionPoolAPI) getAllBlockTransactions(ctx context.Context, block *types.Block) (types.Transactions, bool) {
|
||||
txs := block.Transactions()
|
||||
|
||||
stateSyncPresent := false
|
||||
|
||||
borReceipt := rawdb.ReadBorReceipt(api.b.ChainDb(), block.Hash(), block.NumberU64())
|
||||
if borReceipt != nil {
|
||||
txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash()))
|
||||
if txHash != (common.Hash{}) {
|
||||
borTx, _, _, _, _ := api.b.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash())
|
||||
txs = append(txs, borTx)
|
||||
stateSyncPresent = true
|
||||
}
|
||||
}
|
||||
|
||||
return txs, stateSyncPresent
|
||||
}
|
||||
|
||||
// NewPublicTransactionPoolAPI creates a new RPC service with methods specific for the transaction pool.
|
||||
func NewPublicTransactionPoolAPI(b Backend, nonceLock *AddrLocker) *PublicTransactionPoolAPI {
|
||||
// The signer used by the API should always be the 'latest' known one because we expect
|
||||
|
|
@ -1626,7 +1646,8 @@ func NewPublicTransactionPoolAPI(b Backend, nonceLock *AddrLocker) *PublicTransa
|
|||
// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
|
||||
func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
|
||||
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
|
||||
n := hexutil.Uint(len(block.Transactions()))
|
||||
txs, _ := s.getAllBlockTransactions(ctx, block)
|
||||
n := hexutil.Uint(len(txs))
|
||||
return &n
|
||||
}
|
||||
return nil
|
||||
|
|
@ -1635,7 +1656,8 @@ func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.
|
|||
// GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash.
|
||||
func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
|
||||
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
|
||||
n := hexutil.Uint(len(block.Transactions()))
|
||||
txs, _ := s.getAllBlockTransactions(ctx, block)
|
||||
n := hexutil.Uint(len(txs))
|
||||
return &n
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ func TestGetStaleCodeLes4(t *testing.T) { testGetStaleCode(t, 4) }
|
|||
|
||||
func testGetStaleCode(t *testing.T, protocol int) {
|
||||
netconfig := testnetConfig{
|
||||
blocks: core.TriesInMemory + 4,
|
||||
blocks: int(core.DefaultCacheConfig.TriesInMemory) + 4,
|
||||
protocol: protocol,
|
||||
nopruning: true,
|
||||
}
|
||||
|
|
@ -430,7 +430,7 @@ func TestGetStaleProofLes4(t *testing.T) { testGetStaleProof(t, 4) }
|
|||
|
||||
func testGetStaleProof(t *testing.T, protocol int) {
|
||||
netconfig := testnetConfig{
|
||||
blocks: core.TriesInMemory + 4,
|
||||
blocks: int(core.DefaultCacheConfig.TriesInMemory) + 4,
|
||||
protocol: protocol,
|
||||
nopruning: true,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1058,7 +1058,7 @@ func (p *clientPeer) Handshake(td *big.Int, head common.Hash, headNum uint64, ge
|
|||
|
||||
// If local ethereum node is running in archive mode, advertise ourselves we have
|
||||
// all version state data. Otherwise only recent state is available.
|
||||
stateRecent := uint64(core.TriesInMemory - blockSafetyMargin)
|
||||
stateRecent := core.DefaultCacheConfig.TriesInMemory - blockSafetyMargin
|
||||
if server.archiveMode {
|
||||
stateRecent = 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ func handleGetCode(msg Decoder) (serveRequestFn, uint64, uint64, error) {
|
|||
// Refuse to search stale state data in the database since looking for
|
||||
// a non-exist key is kind of expensive.
|
||||
local := bc.CurrentHeader().Number.Uint64()
|
||||
if !backend.ArchiveMode() && header.Number.Uint64()+core.TriesInMemory <= local {
|
||||
if !backend.ArchiveMode() && header.Number.Uint64()+core.DefaultCacheConfig.TriesInMemory <= local {
|
||||
p.Log().Debug("Reject stale code request", "number", header.Number.Uint64(), "head", local)
|
||||
p.bumpInvalid()
|
||||
continue
|
||||
|
|
@ -396,7 +396,7 @@ func handleGetProofs(msg Decoder) (serveRequestFn, uint64, uint64, error) {
|
|||
// Refuse to search stale state data in the database since looking for
|
||||
// a non-exist key is kind of expensive.
|
||||
local := bc.CurrentHeader().Number.Uint64()
|
||||
if !backend.ArchiveMode() && header.Number.Uint64()+core.TriesInMemory <= local {
|
||||
if !backend.ArchiveMode() && header.Number.Uint64()+core.DefaultCacheConfig.TriesInMemory <= local {
|
||||
p.Log().Debug("Reject stale trie request", "number", header.Number.Uint64(), "head", local)
|
||||
p.bumpInvalid()
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ func (p *testPeer) handshakeWithClient(t *testing.T, td *big.Int, head common.Ha
|
|||
sendList = sendList.add("serveHeaders", nil)
|
||||
sendList = sendList.add("serveChainSince", uint64(0))
|
||||
sendList = sendList.add("serveStateSince", uint64(0))
|
||||
sendList = sendList.add("serveRecentState", uint64(core.TriesInMemory-4))
|
||||
sendList = sendList.add("serveRecentState", core.DefaultCacheConfig.TriesInMemory-4)
|
||||
sendList = sendList.add("txRelay", nil)
|
||||
sendList = sendList.add("flowControl/BL", testBufLimit)
|
||||
sendList = sendList.add("flowControl/MRR", testBufRecharge)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,15 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
// Enabled is checked by the constructor functions for all of the
|
||||
|
|
@ -32,26 +35,77 @@ var enablerFlags = []string{"metrics"}
|
|||
// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections.
|
||||
var expensiveEnablerFlags = []string{"metrics.expensive"}
|
||||
|
||||
// configFlag is the CLI flag name to use to start node by providing a toml based config
|
||||
var configFlag = "config"
|
||||
|
||||
// Init enables or disables the metrics system. Since we need this to run before
|
||||
// any other code gets to create meters and timers, we'll actually do an ugly hack
|
||||
// and peek into the command line args for the metrics flag.
|
||||
func init() {
|
||||
for _, arg := range os.Args {
|
||||
var configFile string
|
||||
|
||||
for i := 0; i < len(os.Args); i++ {
|
||||
arg := os.Args[i]
|
||||
|
||||
flag := strings.TrimLeft(arg, "-")
|
||||
|
||||
// check for existence of `config` flag
|
||||
if flag == configFlag && i < len(os.Args)-1 {
|
||||
configFile = strings.TrimLeft(os.Args[i+1], "-") // find the value of flag
|
||||
}
|
||||
|
||||
for _, enabler := range enablerFlags {
|
||||
if !Enabled && flag == enabler {
|
||||
log.Info("Enabling metrics collection")
|
||||
Enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, enabler := range expensiveEnablerFlags {
|
||||
if !EnabledExpensive && flag == enabler {
|
||||
log.Info("Enabling expensive metrics collection")
|
||||
EnabledExpensive = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the global metrics value, if they're provided in the config file
|
||||
updateMetricsFromConfig(configFile)
|
||||
}
|
||||
|
||||
func updateMetricsFromConfig(path string) {
|
||||
// Don't act upon any errors here. They're already taken into
|
||||
// consideration when the toml config file will be parsed in the cli.
|
||||
canonicalPath, err := common.VerifyPath(path)
|
||||
if err != nil {
|
||||
fmt.Println("path not verified: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(canonicalPath)
|
||||
tomlData := string(data)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Create a minimal config to decode
|
||||
type TelemetryConfig struct {
|
||||
Enabled bool `hcl:"metrics,optional" toml:"metrics,optional"`
|
||||
Expensive bool `hcl:"expensive,optional" toml:"expensive,optional"`
|
||||
}
|
||||
|
||||
type CliConfig struct {
|
||||
Telemetry *TelemetryConfig `hcl:"telemetry,block" toml:"telemetry,block"`
|
||||
}
|
||||
|
||||
conf := &CliConfig{}
|
||||
|
||||
if _, err := toml.Decode(tomlData, &conf); err != nil || conf == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// We have the values now, update them
|
||||
Enabled = conf.Telemetry.Enabled
|
||||
EnabledExpensive = conf.Telemetry.Expensive
|
||||
}
|
||||
|
||||
// CollectProcessMetrics periodically collects various metrics about the running
|
||||
|
|
|
|||
|
|
@ -138,6 +138,9 @@ func NewDBForFakes(t TensingObject) (ethdb.Database, *core.Genesis, *params.Chai
|
|||
chainConfig.Bor.Period = map[string]uint64{
|
||||
"0": 1,
|
||||
}
|
||||
chainConfig.Bor.Sprint = map[string]uint64{
|
||||
"0": 64,
|
||||
}
|
||||
|
||||
return chainDB, genesis, chainConfig
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,8 +278,12 @@ var (
|
|||
Period: map[string]uint64{
|
||||
"0": 2,
|
||||
},
|
||||
ProducerDelay: 6,
|
||||
Sprint: 64,
|
||||
ProducerDelay: map[string]uint64{
|
||||
"0": 6,
|
||||
},
|
||||
Sprint: map[string]uint64{
|
||||
"0": 64,
|
||||
},
|
||||
BackupMultiplier: map[string]uint64{
|
||||
"0": 2,
|
||||
},
|
||||
|
|
@ -310,8 +314,12 @@ var (
|
|||
Period: map[string]uint64{
|
||||
"0": 1,
|
||||
},
|
||||
ProducerDelay: 3,
|
||||
Sprint: 32,
|
||||
ProducerDelay: map[string]uint64{
|
||||
"0": 3,
|
||||
},
|
||||
Sprint: map[string]uint64{
|
||||
"0": 32,
|
||||
},
|
||||
BackupMultiplier: map[string]uint64{
|
||||
"0": 2,
|
||||
},
|
||||
|
|
@ -341,16 +349,25 @@ var (
|
|||
BerlinBlock: big.NewInt(13996000),
|
||||
LondonBlock: big.NewInt(22640000),
|
||||
Bor: &BorConfig{
|
||||
JaipurBlock: 22770000,
|
||||
JaipurBlock: big.NewInt(22770000),
|
||||
DelhiBlock: big.NewInt(29638656),
|
||||
Period: map[string]uint64{
|
||||
"0": 2,
|
||||
"25275000": 5,
|
||||
"29638656": 2,
|
||||
},
|
||||
ProducerDelay: map[string]uint64{
|
||||
"0": 6,
|
||||
"29638656": 4,
|
||||
},
|
||||
Sprint: map[string]uint64{
|
||||
"0": 64,
|
||||
"29638656": 16,
|
||||
},
|
||||
ProducerDelay: 6,
|
||||
Sprint: 64,
|
||||
BackupMultiplier: map[string]uint64{
|
||||
"0": 2,
|
||||
"25275000": 5,
|
||||
"29638656": 2,
|
||||
},
|
||||
ValidatorContract: "0x0000000000000000000000000000000000001000",
|
||||
StateReceiverContract: "0x0000000000000000000000000000000000001001",
|
||||
|
|
@ -386,12 +403,16 @@ var (
|
|||
BerlinBlock: big.NewInt(14750000),
|
||||
LondonBlock: big.NewInt(23850000),
|
||||
Bor: &BorConfig{
|
||||
JaipurBlock: 23850000,
|
||||
JaipurBlock: big.NewInt(23850000),
|
||||
Period: map[string]uint64{
|
||||
"0": 2,
|
||||
},
|
||||
ProducerDelay: 6,
|
||||
Sprint: 64,
|
||||
ProducerDelay: map[string]uint64{
|
||||
"0": 6,
|
||||
},
|
||||
Sprint: map[string]uint64{
|
||||
"0": 64,
|
||||
},
|
||||
BackupMultiplier: map[string]uint64{
|
||||
"0": 2,
|
||||
},
|
||||
|
|
@ -436,8 +457,10 @@ var (
|
|||
// adding flags to the config to also have to set these fields.
|
||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, &BorConfig{BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}}
|
||||
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, &BorConfig{Sprint: 4, BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}}
|
||||
TestRules = TestChainConfig.Rules(new(big.Int), false)
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, &BorConfig{Sprint: map[string]uint64{
|
||||
"0": 4,
|
||||
}, BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}}
|
||||
TestRules = TestChainConfig.Rules(new(big.Int), false)
|
||||
)
|
||||
|
||||
// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
|
||||
|
|
@ -550,15 +573,16 @@ func (c *CliqueConfig) String() string {
|
|||
// BorConfig is the consensus engine configs for Matic bor based sealing.
|
||||
type BorConfig struct {
|
||||
Period map[string]uint64 `json:"period"` // Number of seconds between blocks to enforce
|
||||
ProducerDelay uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval
|
||||
Sprint uint64 `json:"sprint"` // Epoch length to proposer
|
||||
ProducerDelay map[string]uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval
|
||||
Sprint map[string]uint64 `json:"sprint"` // Epoch length to proposer
|
||||
BackupMultiplier map[string]uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time
|
||||
ValidatorContract string `json:"validatorContract"` // Validator set contract
|
||||
StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract
|
||||
OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count
|
||||
BlockAlloc map[string]interface{} `json:"blockAlloc"`
|
||||
BurntContract map[string]string `json:"burntContract"` // governance contract where the token will be sent to and burnt in london fork
|
||||
JaipurBlock uint64 `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur)
|
||||
JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur)
|
||||
DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi)
|
||||
}
|
||||
|
||||
// String implements the stringer interface, returning the consensus engine details.
|
||||
|
|
@ -566,6 +590,14 @@ func (b *BorConfig) String() string {
|
|||
return "bor"
|
||||
}
|
||||
|
||||
func (c *BorConfig) CalculateProducerDelay(number uint64) uint64 {
|
||||
return c.calculateSprintSizeHelper(c.ProducerDelay, number)
|
||||
}
|
||||
|
||||
func (c *BorConfig) CalculateSprint(number uint64) uint64 {
|
||||
return c.calculateSprintSizeHelper(c.Sprint, number)
|
||||
}
|
||||
|
||||
func (c *BorConfig) CalculateBackupMultiplier(number uint64) uint64 {
|
||||
return c.calculateBorConfigHelper(c.BackupMultiplier, number)
|
||||
}
|
||||
|
|
@ -574,8 +606,12 @@ func (c *BorConfig) CalculatePeriod(number uint64) uint64 {
|
|||
return c.calculateBorConfigHelper(c.Period, number)
|
||||
}
|
||||
|
||||
func (c *BorConfig) IsJaipur(number uint64) bool {
|
||||
return number >= c.JaipurBlock
|
||||
func (c *BorConfig) IsJaipur(number *big.Int) bool {
|
||||
return isForked(c.JaipurBlock, number)
|
||||
}
|
||||
|
||||
func (c *BorConfig) IsDelhi(number *big.Int) bool {
|
||||
return isForked(c.DelhiBlock, number)
|
||||
}
|
||||
|
||||
func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uint64) uint64 {
|
||||
|
|
@ -589,6 +625,7 @@ func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uin
|
|||
for i := 0; i < len(keys)-1; i++ {
|
||||
valUint, _ := strconv.ParseUint(keys[i], 10, 64)
|
||||
valUintNext, _ := strconv.ParseUint(keys[i+1], 10, 64)
|
||||
|
||||
if number > valUint && number < valUintNext {
|
||||
return field[keys[i]]
|
||||
}
|
||||
|
|
@ -597,6 +634,26 @@ func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uin
|
|||
return field[keys[len(keys)-1]]
|
||||
}
|
||||
|
||||
func (c *BorConfig) calculateSprintSizeHelper(field map[string]uint64, number uint64) uint64 {
|
||||
keys := make([]string, 0, len(field))
|
||||
for k := range field {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
|
||||
for i := 0; i < len(keys)-1; i++ {
|
||||
valUint, _ := strconv.ParseUint(keys[i], 10, 64)
|
||||
valUintNext, _ := strconv.ParseUint(keys[i+1], 10, 64)
|
||||
|
||||
if number >= valUint && number < valUintNext {
|
||||
return field[keys[i]]
|
||||
}
|
||||
}
|
||||
|
||||
return field[keys[len(keys)-1]]
|
||||
}
|
||||
|
||||
func (c *BorConfig) CalculateBurntContract(number uint64) string {
|
||||
keys := make([]string, 0, len(c.BurntContract))
|
||||
for k := range c.BurntContract {
|
||||
|
|
|
|||
|
|
@ -119,9 +119,11 @@ const (
|
|||
// Introduced in Tangerine Whistle (Eip 150)
|
||||
CreateBySelfdestructGas uint64 = 25000
|
||||
|
||||
BaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks.
|
||||
ElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
|
||||
InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks.
|
||||
BaseFeeChangeDenominatorPreDelhi = 8 // Bounds the amount the base fee can change between blocks before Delhi Hard Fork.
|
||||
BaseFeeChangeDenominatorPostDelhi = 16 // Bounds the amount the base fee can change between blocks after Delhi Hard Fork.
|
||||
|
||||
ElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
|
||||
InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks.
|
||||
|
||||
MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
|
||||
|
||||
|
|
@ -168,3 +170,11 @@ var (
|
|||
MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
|
||||
DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
|
||||
)
|
||||
|
||||
func BaseFeeChangeDenominator(borConfig *BorConfig, number *big.Int) uint64 {
|
||||
if borConfig.IsDelhi(number) {
|
||||
return BaseFeeChangeDenominatorPostDelhi
|
||||
} else {
|
||||
return BaseFeeChangeDenominatorPreDelhi
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
VersionMajor = 0 // Major version component of the current release
|
||||
VersionMinor = 3 // Minor version component of the current release
|
||||
VersionPatch = 0 // Patch version component of the current release
|
||||
VersionMeta = "beta" // Version metadata to append to the version string
|
||||
VersionMajor = 0 // Major version component of the current release
|
||||
VersionMinor = 3 // Minor version component of the current release
|
||||
VersionPatch = 1 // Patch version component of the current release
|
||||
VersionMeta = "mumbai" // Version metadata to append to the version string
|
||||
)
|
||||
|
||||
// Version holds the textual version string.
|
||||
|
|
@ -43,7 +43,8 @@ var VersionWithMeta = func() string {
|
|||
|
||||
// ArchiveVersion holds the textual version string used for Geth archives.
|
||||
// e.g. "1.8.11-dea1ce05" for stable releases, or
|
||||
// "1.8.13-unstable-21c059b6" for unstable releases
|
||||
//
|
||||
// "1.8.13-unstable-21c059b6" for unstable releases
|
||||
func ArchiveVersion(gitCommit string) string {
|
||||
vsn := Version
|
||||
if VersionMeta != "stable" {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import (
|
|||
"os"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
const pathOfPackageRLP = "github.com/ethereum/go-ethereum/rlp"
|
||||
|
|
@ -52,8 +54,15 @@ func main() {
|
|||
}
|
||||
if *output == "-" {
|
||||
os.Stdout.Write(code)
|
||||
} else if err := ioutil.WriteFile(*output, code, 0644); err != nil {
|
||||
fatal(err)
|
||||
} else {
|
||||
canonicalPath, err := common.VerifyPath(*output)
|
||||
if err != nil {
|
||||
fmt.Println("path not verified: " + err.Error())
|
||||
fatal(err)
|
||||
}
|
||||
if err := ioutil.WriteFile(canonicalPath, code, 0600); err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/pelletier/go-toml"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/internal/cli/server"
|
||||
)
|
||||
|
||||
|
|
@ -95,7 +96,7 @@ var flagMap = map[string][]string{
|
|||
"override.arrowglacier": {"notABoolFlag", "No"},
|
||||
"override.terminaltotaldifficulty": {"notABoolFlag", "No"},
|
||||
"verbosity": {"notABoolFlag", "YesFV"},
|
||||
"ws.origins": {"notABoolFlag", "YesF"},
|
||||
"ws.origins": {"notABoolFlag", "No"},
|
||||
}
|
||||
|
||||
// map from cli flags to corresponding toml tags
|
||||
|
|
@ -150,8 +151,7 @@ var nameTagMap = map[string]string{
|
|||
"ipcpath": "ipcpath",
|
||||
"1-corsdomain": "http.corsdomain",
|
||||
"1-vhosts": "http.vhosts",
|
||||
"2-corsdomain": "ws.corsdomain",
|
||||
"2-vhosts": "ws.vhosts",
|
||||
"origins": "ws.origins",
|
||||
"3-corsdomain": "graphql.corsdomain",
|
||||
"3-vhosts": "graphql.vhosts",
|
||||
"1-enabled": "http",
|
||||
|
|
@ -226,9 +226,8 @@ var replacedFlagsMapFlagAndValue = map[string]map[string]map[string]string{
|
|||
},
|
||||
}
|
||||
|
||||
var replacedFlagsMapFlag = map[string]string{
|
||||
"ws.origins": "ws.corsdomain",
|
||||
}
|
||||
// Do not remove
|
||||
var replacedFlagsMapFlag = map[string]string{}
|
||||
|
||||
var currentBoolFlags = []string{
|
||||
"snapshot",
|
||||
|
|
@ -516,7 +515,13 @@ func commentFlags(path string, updatedArgs []string) {
|
|||
|
||||
ignoreLineFlag := false
|
||||
|
||||
input, err := os.ReadFile(path)
|
||||
canonicalPath, err := common.VerifyPath(path)
|
||||
if err != nil {
|
||||
fmt.Println("path not verified: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
input, err := os.ReadFile(canonicalPath)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
|
@ -596,7 +601,7 @@ func commentFlags(path string, updatedArgs []string) {
|
|||
|
||||
output := strings.Join(newLines, "\n")
|
||||
|
||||
err = os.WriteFile(path, []byte(output), 0600)
|
||||
err = os.WriteFile(canonicalPath, []byte(output), 0600)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Instructions:
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ func TestAPIs(t *testing.T) {
|
|||
}()
|
||||
|
||||
genesis := core.GenesisBlockForTesting(db, addrr, big.NewInt(1000000))
|
||||
sprint := params.TestChainConfig.Bor.Sprint
|
||||
testBorConfig := params.TestChainConfig.Bor
|
||||
|
||||
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 6, func(i int, gen *core.BlockGen) {
|
||||
switch i {
|
||||
|
|
@ -208,7 +208,7 @@ func TestAPIs(t *testing.T) {
|
|||
|
||||
blockBatch := db.NewBatch()
|
||||
|
||||
if i%int(sprint-1) != 0 {
|
||||
if i%int(testBorConfig.CalculateSprint(block.NumberU64())-1) != 0 {
|
||||
// if it is not sprint start write all the transactions as normal transactions.
|
||||
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), receipts[i])
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -31,12 +31,17 @@ func TestBorFilters(t *testing.T) {
|
|||
hash2 = common.BytesToHash([]byte("topic2"))
|
||||
hash3 = common.BytesToHash([]byte("topic3"))
|
||||
hash4 = common.BytesToHash([]byte("topic4"))
|
||||
hash5 = common.BytesToHash([]byte("topic5"))
|
||||
)
|
||||
|
||||
defer db.Close()
|
||||
|
||||
genesis := core.GenesisBlockForTesting(db, addr, big.NewInt(1000000))
|
||||
sprint := params.TestChainConfig.Bor.Sprint
|
||||
testBorConfig := params.TestChainConfig.Bor
|
||||
testBorConfig.Sprint = map[string]uint64{
|
||||
"0": 4,
|
||||
"8": 2,
|
||||
}
|
||||
|
||||
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {
|
||||
switch i {
|
||||
|
|
@ -73,7 +78,7 @@ func TestBorFilters(t *testing.T) {
|
|||
gen.AddUncheckedReceipt(receipt)
|
||||
gen.AddUncheckedTx(types.NewTransaction(992, common.HexToAddress("0x992"), big.NewInt(992), 992, gen.BaseFee(), nil))
|
||||
|
||||
case 999: //state-sync tx at block 1000
|
||||
case 993: //state-sync tx at block 994
|
||||
receipt := types.NewReceipt(nil, false, 0)
|
||||
receipt.Logs = []*types.Log{
|
||||
{
|
||||
|
|
@ -82,6 +87,17 @@ func TestBorFilters(t *testing.T) {
|
|||
},
|
||||
}
|
||||
gen.AddUncheckedReceipt(receipt)
|
||||
gen.AddUncheckedTx(types.NewTransaction(994, common.HexToAddress("0x994"), big.NewInt(994), 994, gen.BaseFee(), nil))
|
||||
|
||||
case 999: //state-sync tx at block 1000
|
||||
receipt := types.NewReceipt(nil, false, 0)
|
||||
receipt.Logs = []*types.Log{
|
||||
{
|
||||
Address: addr,
|
||||
Topics: []common.Hash{hash5},
|
||||
},
|
||||
}
|
||||
gen.AddUncheckedReceipt(receipt)
|
||||
gen.AddUncheckedTx(types.NewTransaction(1000, common.HexToAddress("0x1000"), big.NewInt(1000), 1000, gen.BaseFee(), nil))
|
||||
}
|
||||
})
|
||||
|
|
@ -122,14 +138,14 @@ func TestBorFilters(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
filter := filters.NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}})
|
||||
filter := filters.NewBorBlockLogsRangeFilter(backend, testBorConfig, 0, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4, hash5}})
|
||||
|
||||
logs, _ := filter.Logs(context.Background())
|
||||
if len(logs) != 4 {
|
||||
t.Error("expected 4 log, got", len(logs))
|
||||
if len(logs) != 5 {
|
||||
t.Error("expected 5 log, got", len(logs))
|
||||
}
|
||||
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 900, 999, []common.Address{addr}, [][]common.Hash{{hash3}})
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, testBorConfig, 900, 999, []common.Address{addr}, [][]common.Hash{{hash3}})
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
|
||||
if len(logs) != 1 {
|
||||
|
|
@ -140,7 +156,7 @@ func TestBorFilters(t *testing.T) {
|
|||
t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0])
|
||||
}
|
||||
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 992, -1, []common.Address{addr}, [][]common.Hash{{hash3}})
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, testBorConfig, 992, -1, []common.Address{addr}, [][]common.Hash{{hash3}})
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
|
||||
if len(logs) != 1 {
|
||||
|
|
@ -151,7 +167,7 @@ func TestBorFilters(t *testing.T) {
|
|||
t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0])
|
||||
}
|
||||
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 1, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2}})
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, testBorConfig, 1, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2}})
|
||||
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
if len(logs) != 2 {
|
||||
|
|
@ -159,7 +175,7 @@ func TestBorFilters(t *testing.T) {
|
|||
}
|
||||
|
||||
failHash := common.BytesToHash([]byte("fail"))
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, nil, [][]common.Hash{{failHash}})
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, testBorConfig, 0, -1, nil, [][]common.Hash{{failHash}})
|
||||
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
if len(logs) != 0 {
|
||||
|
|
@ -167,14 +183,14 @@ func TestBorFilters(t *testing.T) {
|
|||
}
|
||||
|
||||
failAddr := common.BytesToAddress([]byte("failmenow"))
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, []common.Address{failAddr}, nil)
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, testBorConfig, 0, -1, []common.Address{failAddr}, nil)
|
||||
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
if len(logs) != 0 {
|
||||
t.Error("expected 0 log, got", len(logs))
|
||||
}
|
||||
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, nil, [][]common.Hash{{failHash}, {hash1}})
|
||||
filter = filters.NewBorBlockLogsRangeFilter(backend, testBorConfig, 0, -1, nil, [][]common.Hash{{failHash}, {hash1}})
|
||||
|
||||
logs, _ = filter.Logs(context.Background())
|
||||
if len(logs) != 0 {
|
||||
|
|
|
|||
|
|
@ -1,278 +0,0 @@
|
|||
//go:build integration
|
||||
|
||||
package bor
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
// addr1 = 0x71562b71999873DB5b286dF957af199Ec94617F7
|
||||
pkey1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
// addr2 = 0x9fB29AAc15b9A4B7F17c3385939b007540f4d791
|
||||
pkey2, _ = crypto.HexToECDSA("9b28f36fbd67381120752d6172ecdcf10e06ab2d9a1367aac00cdcd6ac7855d3")
|
||||
keys = []*ecdsa.PrivateKey{pkey1, pkey2}
|
||||
)
|
||||
|
||||
func initMiner(genesis *core.Genesis, privKey *ecdsa.PrivateKey) (*node.Node, *eth.Ethereum, error) {
|
||||
// Define the basic configurations for the Ethereum node
|
||||
datadir, _ := ioutil.TempDir("", "")
|
||||
|
||||
config := &node.Config{
|
||||
Name: "geth",
|
||||
Version: params.Version,
|
||||
DataDir: datadir,
|
||||
P2P: p2p.Config{
|
||||
ListenAddr: "0.0.0.0:0",
|
||||
NoDiscovery: true,
|
||||
MaxPeers: 25,
|
||||
},
|
||||
UseLightweightKDF: true,
|
||||
}
|
||||
// Create the node and configure a full Ethereum node on it
|
||||
stack, err := node.New(config)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ethBackend, err := eth.New(stack, ðconfig.Config{
|
||||
Genesis: genesis,
|
||||
NetworkId: genesis.Config.ChainID.Uint64(),
|
||||
SyncMode: downloader.FullSync,
|
||||
DatabaseCache: 256,
|
||||
DatabaseHandles: 256,
|
||||
TxPool: core.DefaultTxPoolConfig,
|
||||
GPO: ethconfig.Defaults.GPO,
|
||||
Ethash: ethconfig.Defaults.Ethash,
|
||||
Miner: miner.Config{
|
||||
Etherbase: crypto.PubkeyToAddress(privKey.PublicKey),
|
||||
GasCeil: genesis.GasLimit * 11 / 10,
|
||||
GasPrice: big.NewInt(1),
|
||||
Recommit: time.Second,
|
||||
},
|
||||
WithoutHeimdall: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// register backend to account manager with keystore for signing
|
||||
keydir := stack.KeyStoreDir()
|
||||
|
||||
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
||||
kStore := keystore.NewKeyStore(keydir, n, p)
|
||||
|
||||
kStore.ImportECDSA(privKey, "")
|
||||
acc := kStore.Accounts()[0]
|
||||
kStore.Unlock(acc, "")
|
||||
// proceed to authorize the local account manager in any case
|
||||
ethBackend.AccountManager().AddBackend(kStore)
|
||||
|
||||
// ethBackend.AccountManager().AddBackend()
|
||||
err = stack.Start()
|
||||
return stack, ethBackend, err
|
||||
}
|
||||
|
||||
func initGenesis(t *testing.T, faucets []*ecdsa.PrivateKey) *core.Genesis {
|
||||
|
||||
// sprint size = 8 in genesis
|
||||
genesisData, err := ioutil.ReadFile("./testdata/genesis_2val.json")
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
genesis := &core.Genesis{}
|
||||
|
||||
if err := json.Unmarshal(genesisData, genesis); err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
genesis.Config.ChainID = big.NewInt(15001)
|
||||
genesis.Config.EIP150Hash = common.Hash{}
|
||||
|
||||
return genesis
|
||||
}
|
||||
|
||||
func TestValidatorWentOffline(t *testing.T) {
|
||||
|
||||
log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
fdlimit.Raise(2048)
|
||||
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
faucets := make([]*ecdsa.PrivateKey, 128)
|
||||
for i := 0; i < len(faucets); i++ {
|
||||
faucets[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
|
||||
// Create an Ethash network based off of the Ropsten config
|
||||
genesis := initGenesis(t, faucets)
|
||||
|
||||
var (
|
||||
stacks []*node.Node
|
||||
nodes []*eth.Ethereum
|
||||
enodes []*enode.Node
|
||||
)
|
||||
for i := 0; i < 2; i++ {
|
||||
// Start the node and wait until it's up
|
||||
stack, ethBackend, err := initMiner(genesis, keys[i])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stack.Close()
|
||||
|
||||
for stack.Server().NodeInfo().Ports.Listener == 0 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
// Connect the node to all the previous ones
|
||||
for _, n := range enodes {
|
||||
stack.Server().AddPeer(n)
|
||||
}
|
||||
// Start tracking the node and its enode
|
||||
stacks = append(stacks, stack)
|
||||
nodes = append(nodes, ethBackend)
|
||||
enodes = append(enodes, stack.Server().Self())
|
||||
}
|
||||
|
||||
// Iterate over all the nodes and start mining
|
||||
time.Sleep(3 * time.Second)
|
||||
for _, node := range nodes {
|
||||
if err := node.StartMining(1); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
|
||||
// for block 1 to 8, the primary validator is node0
|
||||
// for block 9 to 16, the primary validator is node1
|
||||
// for block 17 to 24, the primary validator is node0
|
||||
// for block 25 to 32, the primary validator is node1
|
||||
blockHeaderVal0 := nodes[0].BlockChain().CurrentHeader()
|
||||
|
||||
// we remove peer connection between node0 and node1
|
||||
if blockHeaderVal0.Number.Uint64() == 9 {
|
||||
stacks[0].Server().RemovePeer(enodes[1])
|
||||
}
|
||||
|
||||
// here, node1 is the primary validator, node0 will sign out-of-turn
|
||||
|
||||
// we add peer connection between node1 and node0
|
||||
if blockHeaderVal0.Number.Uint64() == 14 {
|
||||
stacks[0].Server().AddPeer(enodes[1])
|
||||
}
|
||||
|
||||
// reorg happens here, node1 has higher difficulty, it will replace blocks by node0
|
||||
|
||||
if blockHeaderVal0.Number.Uint64() == 30 {
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check block 10 miner ; expected author is node1 signer
|
||||
blockHeaderVal0 := nodes[0].BlockChain().GetHeaderByNumber(10)
|
||||
blockHeaderVal1 := nodes[1].BlockChain().GetHeaderByNumber(10)
|
||||
authorVal0, err := nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
authorVal1, err := nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 10
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check node0 has block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check node1 has block mined by node1
|
||||
assert.Equal(t, authorVal1, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 11 miner ; expected author is node1 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(11)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(11)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 11
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check node0 has block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check node1 has block mined by node1
|
||||
assert.Equal(t, authorVal1, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 12 miner ; expected author is node1 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(12)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(12)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 12
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check node0 has block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check node1 has block mined by node1
|
||||
assert.Equal(t, authorVal1, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 17 miner ; expected author is node0 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(17)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(17)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 17
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check node0 has block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[0].AccountManager().Accounts()[0])
|
||||
|
||||
// check node1 has block mined by node1
|
||||
assert.Equal(t, authorVal1, nodes[0].AccountManager().Accounts()[0])
|
||||
|
||||
}
|
||||
855
tests/bor/bor_sprint_length_change_test.go
Normal file
855
tests/bor/bor_sprint_length_change_test.go
Normal file
|
|
@ -0,0 +1,855 @@
|
|||
package bor
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil" // nolint: staticcheck
|
||||
_log "log"
|
||||
"math/big"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gotest.tools/assert"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
// Only this account is a validator for the 0th span
|
||||
keySprintLength, _ = crypto.HexToECDSA(privKeySprintLength)
|
||||
|
||||
// This account is one the validators for 1st span (0-indexed)
|
||||
keySprintLength2, _ = crypto.HexToECDSA(privKeySprintLength2)
|
||||
|
||||
keysSprintLength = []*ecdsa.PrivateKey{keySprintLength, keySprintLength2}
|
||||
)
|
||||
|
||||
const (
|
||||
privKeySprintLength = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
|
||||
privKeySprintLength2 = "9b28f36fbd67381120752d6172ecdcf10e06ab2d9a1367aac00cdcd6ac7855d3"
|
||||
)
|
||||
|
||||
// Sprint length change tests
|
||||
func TestValidatorsBlockProduction(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
log.Root().SetHandler(log.LvlFilterHandler(3, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
|
||||
_, err := fdlimit.Raise(2048)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
faucets := make([]*ecdsa.PrivateKey, 128)
|
||||
for i := 0; i < len(faucets); i++ {
|
||||
faucets[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
|
||||
// Create an Ethash network based off of the Ropsten config
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
genesis := InitGenesisSprintLength(t, faucets, "./testdata/genesis_sprint_length_change.json", 8)
|
||||
|
||||
nodes := make([]*eth.Ethereum, 2)
|
||||
enodes := make([]*enode.Node, 2)
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
// Start the node and wait until it's up
|
||||
stack, ethBackend, err := InitMinerSprintLength(genesis, keysSprintLength[i], true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stack.Close()
|
||||
|
||||
for stack.Server().NodeInfo().Ports.Listener == 0 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
// Connect the node to all the previous ones
|
||||
for j, n := range enodes {
|
||||
if j < i {
|
||||
stack.Server().AddPeer(n)
|
||||
}
|
||||
}
|
||||
// Start tracking the node and its enode
|
||||
nodes[i] = ethBackend
|
||||
enodes[i] = stack.Server().Self()
|
||||
}
|
||||
|
||||
// Iterate over all the nodes and start mining
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
for _, node := range nodes {
|
||||
if err := node.StartMining(1); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
// for block 0 to 7, the primary validator is node0
|
||||
// for block 8 to 15, the primary validator is node1
|
||||
// for block 16 to 19, the primary validator is node0
|
||||
// for block 20 to 23, the primary validator is node1
|
||||
blockHeaderVal0 := nodes[0].BlockChain().CurrentHeader()
|
||||
|
||||
if blockHeaderVal0.Number.Uint64() == 24 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// check block 7 miner ; expected author is node0 signer
|
||||
blockHeaderVal0 := nodes[0].BlockChain().GetHeaderByNumber(7)
|
||||
blockHeaderVal1 := nodes[1].BlockChain().GetHeaderByNumber(7)
|
||||
authorVal0, err := nodes[0].Engine().Author(blockHeaderVal0)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
authorVal1, err := nodes[1].Engine().Author(blockHeaderVal1)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 7
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check block mined by node0
|
||||
assert.Equal(t, authorVal0, nodes[0].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 15 miner ; expected author is node1 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(15)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(15)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 15
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 19 miner ; expected author is node0 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(19)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(19)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 19
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check block mined by node0
|
||||
assert.Equal(t, authorVal0, nodes[0].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 23 miner ; expected author is node1 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(23)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(23)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 23
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[1].AccountManager().Accounts()[0])
|
||||
}
|
||||
|
||||
func TestSprintLengths(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testBorConfig := params.TestChainConfig.Bor
|
||||
testBorConfig.Sprint = map[string]uint64{
|
||||
"0": 16,
|
||||
"8": 4,
|
||||
}
|
||||
assert.Equal(t, testBorConfig.CalculateSprint(0), uint64(16))
|
||||
assert.Equal(t, testBorConfig.CalculateSprint(8), uint64(4))
|
||||
assert.Equal(t, testBorConfig.CalculateSprint(9), uint64(4))
|
||||
}
|
||||
|
||||
func TestProducerDelay(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testBorConfig := params.TestChainConfig.Bor
|
||||
testBorConfig.ProducerDelay = map[string]uint64{
|
||||
"0": 16,
|
||||
"8": 4,
|
||||
}
|
||||
assert.Equal(t, testBorConfig.CalculateProducerDelay(0), uint64(16))
|
||||
assert.Equal(t, testBorConfig.CalculateProducerDelay(8), uint64(4))
|
||||
assert.Equal(t, testBorConfig.CalculateProducerDelay(9), uint64(4))
|
||||
}
|
||||
|
||||
var keys_21val = []map[string]string{
|
||||
{
|
||||
"address": "0x5C3E1B893B9315a968fcC6bce9EB9F7d8E22edB3",
|
||||
"priv_key": "c19fac8e538447124ad2408d9fbaeda2bb686fee763dca7a6bab58ea12442413",
|
||||
"pub_key": "0x0495421933eda03dcc37f9186c24e255b569513aefae71e96d55d0db3df17502e24e86297b01a167fab9ce1174f06ee3110510ac242e39218bd964de5b345edbd6",
|
||||
},
|
||||
{
|
||||
"address": "0x73E033779C9030D4528d86FbceF5B02e97488921",
|
||||
"priv_key": "61eb51cf8936309151ab7b931841ea033b6a09931f6a100b464fbbd74f3e0bd7",
|
||||
"pub_key": "0x04f9a5e9bf76b45ac58f1b018ccba4b83b3531010cdadf42174c18a9db9879ef1dcb5d1254ce834bc108b110cd8d0186ed69a0387528a142bdb5936faf58bf98c9",
|
||||
},
|
||||
{
|
||||
"address": "0x751eC4877450B8a4D652d0D70197337FC38a42e6",
|
||||
"priv_key": "6e7f48d012c9c0baadbdc88af32521e2e477fd6898a9b65e6abe19fd6652cb2e",
|
||||
"pub_key": "0x0479db4c0b757bf0e5d9b8954b078ab7c0e91d6c19697904d23d07ea4853c8584382de91174929ba5c598214b8a991471ae051458ea787cdc15a4e435a55ef8059",
|
||||
},
|
||||
{
|
||||
"address": "0xA464DC4810Bc79B956810759e314d85BcE35cD1c",
|
||||
"priv_key": "3efcf3f7014a6257f4a443119851414111820c681b27525dab3f35e72e28e51e",
|
||||
"pub_key": "0x040180920306bf598ea050e258f2c7e50804a77a64f5a11705e08d18ee71eb0a80fafc95d0a42b92371ded042edda16c1f0b5f2fef7c4113ad66c59a71c29d977e",
|
||||
},
|
||||
{
|
||||
"address": "0xb005bc07015170266Bd430f3EC1322938603be20",
|
||||
"priv_key": "17cd9b38c2b3a639c7d97ccbf2bb6c7140ab8f625aec4c249bc8e4cfd3bf9a96",
|
||||
"pub_key": "0x04435a70d343aa569e6f3386c73e39a1aa6f88c30e5943baedda9618b55cc944a2de1d114aff6d0e9fa002bebc780b04ef6c1b8a06bbf0d41c10d1efa55390f198",
|
||||
},
|
||||
{
|
||||
"address": "0xE8d02Da3dFeeB3e755472D95D666BD6821D92129",
|
||||
"priv_key": "45c9ef66361a2283cef14184f128c41949103b791aa622ead3c0bc844648b835",
|
||||
"pub_key": "0x04a14651ddc80467eb589d72d95153fa695e4cb2e4bb99edeb912e840d309d61313b6f4676081b099f29e6598ecf98cb7b44bb862d019920718b558f27ba94ca51",
|
||||
},
|
||||
{
|
||||
"address": "0xF93B54Cf36E917f625B48e1e3C9F93BC2344Fb06",
|
||||
"priv_key": "93788a1305605808df1f9a96b5e1157da191680cf08bc15e077138f517563cd5",
|
||||
"pub_key": "0x045eee11dceccd9cccc371ca3d96d74c848e785223f1e5df4d1a7f08efdfeb90bd8f0035342a9c26068cf6c7ab395ca3ceea555541325067fc187c375390efa57d",
|
||||
},
|
||||
}
|
||||
|
||||
func getTestSprintLengthReorgCases2Nodes() []map[string]interface{} {
|
||||
sprintSizes := []uint64{64}
|
||||
faultyNodes := [][]uint64{{0, 1}, {1, 2}, {0, 2}}
|
||||
reorgsLengthTests := make([]map[string]interface{}, 0)
|
||||
|
||||
for i := uint64(0); i < uint64(len(sprintSizes)); i++ {
|
||||
maxReorgLength := sprintSizes[i] * 4
|
||||
for j := uint64(20); j <= maxReorgLength; j = j + 8 {
|
||||
maxStartBlock := sprintSizes[i] - 1
|
||||
for k := sprintSizes[i] / 2; k <= maxStartBlock; k = k + 4 {
|
||||
for l := uint64(0); l < uint64(len(faultyNodes)); l++ {
|
||||
if j+k < sprintSizes[i] {
|
||||
continue
|
||||
}
|
||||
|
||||
reorgsLengthTest := map[string]interface{}{
|
||||
"reorgLength": j,
|
||||
"startBlock": k,
|
||||
"sprintSize": sprintSizes[i],
|
||||
"faultyNodes": faultyNodes[l], // node 1(index) is primary validator of the first sprint
|
||||
}
|
||||
reorgsLengthTests = append(reorgsLengthTests, reorgsLengthTest)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// reorgsLengthTests := []map[string]uint64{
|
||||
// {
|
||||
// "reorgLength": 3,
|
||||
// "startBlock": 7,
|
||||
// "sprintSize": 8,
|
||||
// "faultyNode": 1,
|
||||
// },
|
||||
// }
|
||||
return reorgsLengthTests
|
||||
}
|
||||
|
||||
func getTestSprintLengthReorgCases() []map[string]uint64 {
|
||||
sprintSizes := []uint64{64, 32, 16, 8}
|
||||
faultyNodes := []uint64{0, 1}
|
||||
reorgsLengthTests := make([]map[string]uint64, 0)
|
||||
|
||||
for i := uint64(0); i < uint64(len(sprintSizes)); i++ {
|
||||
maxReorgLength := sprintSizes[i] * 4
|
||||
for j := uint64(3); j <= maxReorgLength; j = j + 4 {
|
||||
maxStartBlock := sprintSizes[i] - 1
|
||||
for k := sprintSizes[i] / 2; k <= maxStartBlock; k = k + 4 {
|
||||
for l := uint64(0); l < uint64(len(faultyNodes)); l++ {
|
||||
if j+k < sprintSizes[i] {
|
||||
continue
|
||||
}
|
||||
|
||||
reorgsLengthTest := map[string]uint64{
|
||||
"reorgLength": j,
|
||||
"startBlock": k,
|
||||
"sprintSize": sprintSizes[i],
|
||||
"faultyNode": faultyNodes[l], // node 1(index) is primary validator of the first sprint
|
||||
}
|
||||
reorgsLengthTests = append(reorgsLengthTests, reorgsLengthTest)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// reorgsLengthTests := []map[string]uint64{
|
||||
// {
|
||||
// "reorgLength": 3,
|
||||
// "startBlock": 7,
|
||||
// "sprintSize": 8,
|
||||
// "faultyNode": 1,
|
||||
// },
|
||||
// }
|
||||
return reorgsLengthTests
|
||||
}
|
||||
|
||||
func SprintLengthReorgIndividual(t *testing.T, index int, tt map[string]uint64) (uint64, uint64, uint64, uint64, uint64, uint64) {
|
||||
t.Helper()
|
||||
|
||||
log.Warn("Case ----- ", "Index", index, "InducedReorgLength", tt["reorgLength"], "BlockStart", tt["startBlock"], "SprintSize", tt["sprintSize"], "DisconnectedNode", tt["faultyNode"])
|
||||
observerOldChainLength, faultyOldChainLength := SetupValidatorsAndTest(t, tt)
|
||||
|
||||
if observerOldChainLength > 0 {
|
||||
log.Warn("Observer", "Old Chain length", observerOldChainLength)
|
||||
}
|
||||
|
||||
if faultyOldChainLength > 0 {
|
||||
log.Warn("Faulty", "Old Chain length", faultyOldChainLength)
|
||||
}
|
||||
|
||||
return tt["reorgLength"], tt["startBlock"], tt["sprintSize"], tt["faultyNode"], faultyOldChainLength, observerOldChainLength
|
||||
}
|
||||
|
||||
func SprintLengthReorgIndividual2Nodes(t *testing.T, index int, tt map[string]interface{}) (uint64, uint64, uint64, []uint64, uint64, uint64) {
|
||||
t.Helper()
|
||||
|
||||
log.Warn("Case ----- ", "Index", index, "InducedReorgLength", tt["reorgLength"], "BlockStart", tt["startBlock"], "SprintSize", tt["sprintSize"], "DisconnectedNode", tt["faultyNodes"])
|
||||
observerOldChainLength, faultyOldChainLength := SetupValidatorsAndTest2Nodes(t, tt)
|
||||
|
||||
if observerOldChainLength > 0 {
|
||||
log.Warn("Observer", "Old Chain length", observerOldChainLength)
|
||||
}
|
||||
|
||||
if faultyOldChainLength > 0 {
|
||||
log.Warn("Faulty", "Old Chain length", faultyOldChainLength)
|
||||
}
|
||||
|
||||
fNodes, _ := tt["faultyNodes"].([]uint64)
|
||||
|
||||
return tt["reorgLength"].(uint64), tt["startBlock"].(uint64), tt["sprintSize"].(uint64), fNodes, faultyOldChainLength, observerOldChainLength
|
||||
}
|
||||
|
||||
func TestSprintLengthReorg2Nodes(t *testing.T) {
|
||||
t.Skip()
|
||||
t.Parallel()
|
||||
|
||||
log.Root().SetHandler(log.LvlFilterHandler(3, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
|
||||
_, err := fdlimit.Raise(2048)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
reorgsLengthTests := getTestSprintLengthReorgCases2Nodes()
|
||||
f, err := os.Create("sprintReorg2Nodes.csv")
|
||||
|
||||
defer func() {
|
||||
err = f.Close()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
_log.Fatalln("failed to open file", err)
|
||||
}
|
||||
|
||||
w := csv.NewWriter(f)
|
||||
err = w.Write([]string{"Induced Reorg Length", "Start Block", "Sprint Size", "Disconnected Node Ids", "Disconnected Node Id's Reorg Length", "Observer Node Id's Reorg Length"})
|
||||
w.Flush()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for index, tt := range reorgsLengthTests {
|
||||
if index%4 == 0 {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
go SprintLengthReorgIndividual2NodesHelper(t, index, tt, w, &wg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSprintLengthReorg(t *testing.T) {
|
||||
t.Skip()
|
||||
t.Parallel()
|
||||
|
||||
reorgsLengthTests := getTestSprintLengthReorgCases()
|
||||
f, err := os.Create("sprintReorg.csv")
|
||||
|
||||
defer func() {
|
||||
err = f.Close()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
_log.Fatalln("failed to open file", err)
|
||||
}
|
||||
|
||||
w := csv.NewWriter(f)
|
||||
err = w.Write([]string{"Induced Reorg Length", "Start Block", "Sprint Size", "Disconnected Node Id", "Disconnected Node Id's Reorg Length", "Observer Node Id's Reorg Length"})
|
||||
w.Flush()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for index, tt := range reorgsLengthTests {
|
||||
if index%4 == 0 {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
go SprintLengthReorgIndividualHelper(t, index, tt, w, &wg)
|
||||
}
|
||||
}
|
||||
|
||||
func SprintLengthReorgIndividualHelper(t *testing.T, index int, tt map[string]uint64, w *csv.Writer, wg *sync.WaitGroup) {
|
||||
t.Helper()
|
||||
|
||||
r1, r2, r3, r4, r5, r6 := SprintLengthReorgIndividual(t, index, tt)
|
||||
err := w.Write([]string{fmt.Sprint(r1), fmt.Sprint(r2), fmt.Sprint(r3), fmt.Sprint(r4), fmt.Sprint(r5), fmt.Sprint(r6)})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w.Flush()
|
||||
(*wg).Done()
|
||||
}
|
||||
|
||||
func SprintLengthReorgIndividual2NodesHelper(t *testing.T, index int, tt map[string]interface{}, w *csv.Writer, wg *sync.WaitGroup) {
|
||||
t.Helper()
|
||||
|
||||
r1, r2, r3, r4, r5, r6 := SprintLengthReorgIndividual2Nodes(t, index, tt)
|
||||
err := w.Write([]string{fmt.Sprint(r1), fmt.Sprint(r2), fmt.Sprint(r3), fmt.Sprint(r4), fmt.Sprint(r5), fmt.Sprint(r6)})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w.Flush()
|
||||
(*wg).Done()
|
||||
}
|
||||
|
||||
// nolint: gocognit
|
||||
func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64) {
|
||||
t.Helper()
|
||||
|
||||
log.Root().SetHandler(log.LvlFilterHandler(3, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
|
||||
_, err := fdlimit.Raise(2048)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
faucets := make([]*ecdsa.PrivateKey, 128)
|
||||
for i := 0; i < len(faucets); i++ {
|
||||
faucets[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
|
||||
// Create an Ethash network based off of the Ropsten config
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
genesis := InitGenesisSprintLength(t, faucets, "./testdata/genesis_7val.json", tt["sprintSize"])
|
||||
|
||||
nodes := make([]*eth.Ethereum, len(keys_21val))
|
||||
enodes := make([]*enode.Node, len(keys_21val))
|
||||
stacks := make([]*node.Node, len(keys_21val))
|
||||
|
||||
pkeys_21val := make([]*ecdsa.PrivateKey, len(keys_21val))
|
||||
|
||||
for index, signerdata := range keys_21val {
|
||||
pkeys_21val[index], _ = crypto.HexToECDSA(signerdata["priv_key"])
|
||||
}
|
||||
|
||||
for i := 0; i < len(keys_21val); i++ {
|
||||
// Start the node and wait until it's up
|
||||
stack, ethBackend, err := InitMinerSprintLength(genesis, pkeys_21val[i], true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stack.Close()
|
||||
|
||||
for stack.Server().NodeInfo().Ports.Listener == 0 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
// Connect the node to all the previous ones
|
||||
for j, n := range enodes {
|
||||
if j < i {
|
||||
stack.Server().AddPeer(n)
|
||||
}
|
||||
}
|
||||
// Start tracking the node and its enode
|
||||
stacks[i] = stack
|
||||
nodes[i] = ethBackend
|
||||
enodes[i] = stack.Server().Self()
|
||||
}
|
||||
|
||||
// Iterate over all the nodes and start mining
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
for _, node := range nodes {
|
||||
if err := node.StartMining(1); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
chain2HeadChObserver := make(chan core.Chain2HeadEvent, 64)
|
||||
chain2HeadChFaulty := make(chan core.Chain2HeadEvent, 64)
|
||||
|
||||
var observerOldChainLength, faultyOldChainLength uint64
|
||||
|
||||
faultyProducerIndex := tt["faultyNode"] // node causing reorg :: faulty ::
|
||||
subscribedNodeIndex := 6 // node on different partition, produces 7th sprint but our testcase does not run till 7th sprint. :: observer ::
|
||||
|
||||
nodes[subscribedNodeIndex].BlockChain().SubscribeChain2HeadEvent(chain2HeadChObserver)
|
||||
nodes[faultyProducerIndex].BlockChain().SubscribeChain2HeadEvent(chain2HeadChFaulty)
|
||||
|
||||
stacks[faultyProducerIndex].Server().NoDiscovery = true
|
||||
|
||||
for {
|
||||
blockHeaderObserver := nodes[subscribedNodeIndex].BlockChain().CurrentHeader()
|
||||
blockHeaderFaulty := nodes[faultyProducerIndex].BlockChain().CurrentHeader()
|
||||
|
||||
log.Warn("Current Observer block", "number", blockHeaderObserver.Number, "hash", blockHeaderObserver.Hash())
|
||||
log.Warn("Current Faulty block", "number", blockHeaderFaulty.Number, "hash", blockHeaderFaulty.Hash())
|
||||
|
||||
if blockHeaderFaulty.Number.Uint64() == tt["startBlock"] {
|
||||
stacks[faultyProducerIndex].Server().MaxPeers = 0
|
||||
|
||||
for _, enode := range enodes {
|
||||
stacks[faultyProducerIndex].Server().RemovePeer(enode)
|
||||
}
|
||||
}
|
||||
|
||||
if blockHeaderObserver.Number.Uint64() >= tt["startBlock"] && blockHeaderObserver.Number.Uint64() < tt["startBlock"]+tt["reorgLength"] {
|
||||
for _, enode := range enodes {
|
||||
stacks[faultyProducerIndex].Server().RemovePeer(enode)
|
||||
}
|
||||
}
|
||||
|
||||
if blockHeaderObserver.Number.Uint64() == tt["startBlock"]+tt["reorgLength"] {
|
||||
stacks[faultyProducerIndex].Server().NoDiscovery = false
|
||||
stacks[faultyProducerIndex].Server().MaxPeers = 100
|
||||
|
||||
for _, enode := range enodes {
|
||||
stacks[faultyProducerIndex].Server().AddPeer(enode)
|
||||
}
|
||||
}
|
||||
|
||||
if blockHeaderFaulty.Number.Uint64() >= 255 {
|
||||
break
|
||||
}
|
||||
|
||||
select {
|
||||
case ev := <-chain2HeadChObserver:
|
||||
if ev.Type == core.Chain2HeadReorgEvent {
|
||||
if len(ev.OldChain) > 1 {
|
||||
observerOldChainLength = uint64(len(ev.OldChain))
|
||||
return observerOldChainLength, 0
|
||||
}
|
||||
}
|
||||
|
||||
case ev := <-chain2HeadChFaulty:
|
||||
if ev.Type == core.Chain2HeadReorgEvent {
|
||||
if len(ev.OldChain) > 1 {
|
||||
faultyOldChainLength = uint64(len(ev.OldChain))
|
||||
return 0, faultyOldChainLength
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// nolint: gocognit
|
||||
func SetupValidatorsAndTest2Nodes(t *testing.T, tt map[string]interface{}) (uint64, uint64) {
|
||||
t.Helper()
|
||||
|
||||
log.Root().SetHandler(log.LvlFilterHandler(3, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
|
||||
_, err := fdlimit.Raise(2048)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
faucets := make([]*ecdsa.PrivateKey, 128)
|
||||
for i := 0; i < len(faucets); i++ {
|
||||
faucets[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
|
||||
// Create an Ethash network based off of the Ropsten config
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
genesis := InitGenesisSprintLength(t, faucets, "./testdata/genesis_7val.json", tt["sprintSize"].(uint64))
|
||||
|
||||
nodes := make([]*eth.Ethereum, len(keys_21val))
|
||||
enodes := make([]*enode.Node, len(keys_21val))
|
||||
stacks := make([]*node.Node, len(keys_21val))
|
||||
|
||||
pkeys_21val := make([]*ecdsa.PrivateKey, len(keys_21val))
|
||||
|
||||
for index, signerdata := range keys_21val {
|
||||
pkeys_21val[index], _ = crypto.HexToECDSA(signerdata["priv_key"])
|
||||
}
|
||||
|
||||
for i := 0; i < len(keys_21val); i++ {
|
||||
// Start the node and wait until it's up
|
||||
stack, ethBackend, err := InitMinerSprintLength(genesis, pkeys_21val[i], true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stack.Close()
|
||||
|
||||
for stack.Server().NodeInfo().Ports.Listener == 0 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
// Connect the node to all the previous ones
|
||||
for j, n := range enodes {
|
||||
if j < i {
|
||||
stack.Server().AddPeer(n)
|
||||
}
|
||||
}
|
||||
// Start tracking the node and its enode
|
||||
stacks[i] = stack
|
||||
nodes[i] = ethBackend
|
||||
enodes[i] = stack.Server().Self()
|
||||
}
|
||||
|
||||
// Iterate over all the nodes and start mining
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
for _, node := range nodes {
|
||||
if err := node.StartMining(1); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
chain2HeadChObserver := make(chan core.Chain2HeadEvent, 64)
|
||||
chain2HeadChFaulty := make(chan core.Chain2HeadEvent, 64)
|
||||
|
||||
var observerOldChainLength, faultyOldChainLength uint64
|
||||
|
||||
faultyProducerIndex := tt["faultyNodes"].([]uint64)[0] // node causing reorg :: faulty ::
|
||||
subscribedNodeIndex := 6 // node on different partition, produces 7th sprint but our testcase does not run till 7th sprint. :: observer ::
|
||||
|
||||
nodes[subscribedNodeIndex].BlockChain().SubscribeChain2HeadEvent(chain2HeadChObserver)
|
||||
nodes[faultyProducerIndex].BlockChain().SubscribeChain2HeadEvent(chain2HeadChFaulty)
|
||||
|
||||
stacks[faultyProducerIndex].Server().NoDiscovery = true
|
||||
|
||||
for {
|
||||
blockHeaderObserver := nodes[subscribedNodeIndex].BlockChain().CurrentHeader()
|
||||
blockHeaderFaulty := nodes[faultyProducerIndex].BlockChain().CurrentHeader()
|
||||
|
||||
log.Warn("Current Observer block", "number", blockHeaderObserver.Number, "hash", blockHeaderObserver.Hash())
|
||||
log.Warn("Current Faulty block", "number", blockHeaderFaulty.Number, "hash", blockHeaderFaulty.Hash())
|
||||
|
||||
if blockHeaderObserver.Number.Uint64() >= tt["startBlock"].(uint64) && blockHeaderObserver.Number.Uint64() < tt["startBlock"].(uint64)+tt["reorgLength"].(uint64) {
|
||||
for _, n := range tt["faultyNodes"].([]uint64) {
|
||||
stacks[n].Server().MaxPeers = 1
|
||||
|
||||
for _, enode := range enodes {
|
||||
stacks[n].Server().RemovePeer(enode)
|
||||
}
|
||||
|
||||
for _, m := range tt["faultyNodes"].([]uint64) {
|
||||
stacks[m].Server().AddPeer(enodes[n])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if blockHeaderObserver.Number.Uint64() == tt["startBlock"].(uint64)+tt["reorgLength"].(uint64) {
|
||||
stacks[faultyProducerIndex].Server().NoDiscovery = false
|
||||
stacks[faultyProducerIndex].Server().MaxPeers = 100
|
||||
|
||||
for _, enode := range enodes {
|
||||
stacks[faultyProducerIndex].Server().AddPeer(enode)
|
||||
}
|
||||
}
|
||||
|
||||
if blockHeaderFaulty.Number.Uint64() >= 255 {
|
||||
break
|
||||
}
|
||||
|
||||
select {
|
||||
case ev := <-chain2HeadChObserver:
|
||||
if ev.Type == core.Chain2HeadReorgEvent {
|
||||
if len(ev.OldChain) > 1 {
|
||||
observerOldChainLength = uint64(len(ev.OldChain))
|
||||
return observerOldChainLength, 0
|
||||
}
|
||||
}
|
||||
|
||||
case ev := <-chain2HeadChFaulty:
|
||||
if ev.Type == core.Chain2HeadReorgEvent {
|
||||
if len(ev.OldChain) > 1 {
|
||||
faultyOldChainLength = uint64(len(ev.OldChain))
|
||||
return 0, faultyOldChainLength
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
func InitGenesisSprintLength(t *testing.T, faucets []*ecdsa.PrivateKey, fileLocation string, sprintSize uint64) *core.Genesis {
|
||||
t.Helper()
|
||||
|
||||
// sprint size = 8 in genesis
|
||||
genesisData, err := ioutil.ReadFile(fileLocation)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
genesis := &core.Genesis{}
|
||||
|
||||
if err := json.Unmarshal(genesisData, genesis); err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
genesis.Config.ChainID = big.NewInt(15001)
|
||||
genesis.Config.EIP150Hash = common.Hash{}
|
||||
genesis.Config.Bor.Sprint["0"] = sprintSize
|
||||
|
||||
return genesis
|
||||
}
|
||||
|
||||
func InitMinerSprintLength(genesis *core.Genesis, privKey *ecdsa.PrivateKey, withoutHeimdall bool) (*node.Node, *eth.Ethereum, error) {
|
||||
// Define the basic configurations for the Ethereum node
|
||||
datadir, _ := ioutil.TempDir("", "")
|
||||
|
||||
config := &node.Config{
|
||||
Name: "geth",
|
||||
Version: params.Version,
|
||||
DataDir: datadir,
|
||||
P2P: p2p.Config{
|
||||
ListenAddr: "0.0.0.0:0",
|
||||
NoDiscovery: true,
|
||||
MaxPeers: 25,
|
||||
},
|
||||
UseLightweightKDF: true,
|
||||
}
|
||||
// Create the node and configure a full Ethereum node on it
|
||||
stack, err := node.New(config)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ethBackend, err := eth.New(stack, ðconfig.Config{
|
||||
Genesis: genesis,
|
||||
NetworkId: genesis.Config.ChainID.Uint64(),
|
||||
SyncMode: downloader.FullSync,
|
||||
DatabaseCache: 256,
|
||||
DatabaseHandles: 256,
|
||||
TxPool: core.DefaultTxPoolConfig,
|
||||
GPO: ethconfig.Defaults.GPO,
|
||||
Ethash: ethconfig.Defaults.Ethash,
|
||||
Miner: miner.Config{
|
||||
Etherbase: crypto.PubkeyToAddress(privKey.PublicKey),
|
||||
GasCeil: genesis.GasLimit * 11 / 10,
|
||||
GasPrice: big.NewInt(1),
|
||||
Recommit: time.Second,
|
||||
},
|
||||
WithoutHeimdall: withoutHeimdall,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// register backend to account manager with keystore for signing
|
||||
keydir := stack.KeyStoreDir()
|
||||
|
||||
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
||||
kStore := keystore.NewKeyStore(keydir, n, p)
|
||||
|
||||
_, err = kStore.ImportECDSA(privKey, "")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
acc := kStore.Accounts()[0]
|
||||
err = kStore.Unlock(acc, "")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// proceed to authorize the local account manager in any case
|
||||
ethBackend.AccountManager().AddBackend(kStore)
|
||||
|
||||
err = stack.Start()
|
||||
|
||||
return stack, ethBackend, err
|
||||
}
|
||||
|
|
@ -1,21 +1,27 @@
|
|||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package bor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||
"github.com/ethereum/go-ethereum/consensus/bor"
|
||||
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
||||
|
|
@ -26,11 +32,337 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/tests/bor/mocks"
|
||||
)
|
||||
|
||||
var (
|
||||
// addr1 = 0x71562b71999873DB5b286dF957af199Ec94617F7
|
||||
pkey1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
// addr2 = 0x9fB29AAc15b9A4B7F17c3385939b007540f4d791
|
||||
pkey2, _ = crypto.HexToECDSA("9b28f36fbd67381120752d6172ecdcf10e06ab2d9a1367aac00cdcd6ac7855d3")
|
||||
)
|
||||
|
||||
func TestValidatorWentOffline(t *testing.T) {
|
||||
|
||||
log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
fdlimit.Raise(2048)
|
||||
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
faucets := make([]*ecdsa.PrivateKey, 128)
|
||||
for i := 0; i < len(faucets); i++ {
|
||||
faucets[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
|
||||
// Create an Ethash network based off of the Ropsten config
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
genesis := InitGenesis(t, faucets, "./testdata/genesis_2val.json", 8)
|
||||
|
||||
var (
|
||||
stacks []*node.Node
|
||||
nodes []*eth.Ethereum
|
||||
enodes []*enode.Node
|
||||
)
|
||||
for i := 0; i < 2; i++ {
|
||||
// Start the node and wait until it's up
|
||||
stack, ethBackend, err := InitMiner(genesis, keys[i], true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer stack.Close()
|
||||
|
||||
for stack.Server().NodeInfo().Ports.Listener == 0 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
// Connect the node to all the previous ones
|
||||
for _, n := range enodes {
|
||||
stack.Server().AddPeer(n)
|
||||
}
|
||||
// Start tracking the node and its enode
|
||||
stacks = append(stacks, stack)
|
||||
nodes = append(nodes, ethBackend)
|
||||
enodes = append(enodes, stack.Server().Self())
|
||||
}
|
||||
|
||||
// Iterate over all the nodes and start mining
|
||||
time.Sleep(3 * time.Second)
|
||||
for _, node := range nodes {
|
||||
if err := node.StartMining(1); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
|
||||
// for block 1 to 8, the primary validator is node0
|
||||
// for block 9 to 16, the primary validator is node1
|
||||
// for block 17 to 24, the primary validator is node0
|
||||
// for block 25 to 32, the primary validator is node1
|
||||
blockHeaderVal0 := nodes[0].BlockChain().CurrentHeader()
|
||||
|
||||
// we remove peer connection between node0 and node1
|
||||
if blockHeaderVal0.Number.Uint64() == 9 {
|
||||
stacks[0].Server().RemovePeer(enodes[1])
|
||||
}
|
||||
|
||||
// here, node1 is the primary validator, node0 will sign out-of-turn
|
||||
|
||||
// we add peer connection between node1 and node0
|
||||
if blockHeaderVal0.Number.Uint64() == 14 {
|
||||
stacks[0].Server().AddPeer(enodes[1])
|
||||
}
|
||||
|
||||
// reorg happens here, node1 has higher difficulty, it will replace blocks by node0
|
||||
|
||||
if blockHeaderVal0.Number.Uint64() == 30 {
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check block 10 miner ; expected author is node1 signer
|
||||
blockHeaderVal0 := nodes[0].BlockChain().GetHeaderByNumber(10)
|
||||
blockHeaderVal1 := nodes[1].BlockChain().GetHeaderByNumber(10)
|
||||
authorVal0, err := nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
authorVal1, err := nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 10
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check node0 has block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check node1 has block mined by node1
|
||||
assert.Equal(t, authorVal1, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 11 miner ; expected author is node1 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(11)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(11)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 11
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check node0 has block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check node1 has block mined by node1
|
||||
assert.Equal(t, authorVal1, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 12 miner ; expected author is node1 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(12)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(12)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 12
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check node0 has block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check node1 has block mined by node1
|
||||
assert.Equal(t, authorVal1, nodes[1].AccountManager().Accounts()[0])
|
||||
|
||||
// check block 17 miner ; expected author is node0 signer
|
||||
blockHeaderVal0 = nodes[0].BlockChain().GetHeaderByNumber(17)
|
||||
blockHeaderVal1 = nodes[1].BlockChain().GetHeaderByNumber(17)
|
||||
authorVal0, err = nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
authorVal1, err = nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
log.Error("Error in getting author", "err", err)
|
||||
}
|
||||
|
||||
// check both nodes have the same block 17
|
||||
assert.Equal(t, authorVal0, authorVal1)
|
||||
|
||||
// check node0 has block mined by node1
|
||||
assert.Equal(t, authorVal0, nodes[0].AccountManager().Accounts()[0])
|
||||
|
||||
// check node1 has block mined by node1
|
||||
assert.Equal(t, authorVal1, nodes[0].AccountManager().Accounts()[0])
|
||||
}
|
||||
|
||||
func TestForkWithBlockTime(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
sprint map[string]uint64
|
||||
blockTime map[string]uint64
|
||||
change uint64
|
||||
producerDelay map[string]uint64
|
||||
forkExpected bool
|
||||
}{
|
||||
{
|
||||
name: "No fork after 2 sprints with producer delay = max block time",
|
||||
sprint: map[string]uint64{
|
||||
"0": 128,
|
||||
},
|
||||
blockTime: map[string]uint64{
|
||||
"0": 5,
|
||||
"128": 2,
|
||||
"256": 8,
|
||||
},
|
||||
change: 2,
|
||||
producerDelay: map[string]uint64{
|
||||
"0": 8,
|
||||
},
|
||||
forkExpected: false,
|
||||
},
|
||||
{
|
||||
name: "No Fork after 1 sprint producer delay = max block time",
|
||||
sprint: map[string]uint64{
|
||||
"0": 64,
|
||||
},
|
||||
blockTime: map[string]uint64{
|
||||
"0": 5,
|
||||
"64": 2,
|
||||
},
|
||||
change: 1,
|
||||
producerDelay: map[string]uint64{
|
||||
"0": 5,
|
||||
},
|
||||
forkExpected: false,
|
||||
},
|
||||
{
|
||||
name: "Fork after 4 sprints with producer delay < max block time",
|
||||
sprint: map[string]uint64{
|
||||
"0": 16,
|
||||
},
|
||||
blockTime: map[string]uint64{
|
||||
"0": 2,
|
||||
"64": 5,
|
||||
},
|
||||
change: 4,
|
||||
producerDelay: map[string]uint64{
|
||||
"0": 4,
|
||||
},
|
||||
forkExpected: true,
|
||||
},
|
||||
}
|
||||
|
||||
// Create an Ethash network based off of the Ropsten config
|
||||
// Generate a batch of accounts to seal and fund with
|
||||
faucets := make([]*ecdsa.PrivateKey, 128)
|
||||
for i := 0; i < len(faucets); i++ {
|
||||
faucets[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
genesis := InitGenesis(t, faucets, "./testdata/genesis_2val.json", 8)
|
||||
|
||||
for _, test := range cases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
|
||||
genesis.Config.Bor.Sprint = test.sprint
|
||||
genesis.Config.Bor.Period = test.blockTime
|
||||
genesis.Config.Bor.BackupMultiplier = test.blockTime
|
||||
genesis.Config.Bor.ProducerDelay = test.producerDelay
|
||||
|
||||
stacks, nodes, _ := setupMiner(t, 2, genesis)
|
||||
|
||||
defer func() {
|
||||
for _, stack := range stacks {
|
||||
stack.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// Iterate over all the nodes and start mining
|
||||
for _, node := range nodes {
|
||||
if err := node.StartMining(1); err != nil {
|
||||
t.Fatal("Error occured while starting miner", "node", node, "error", err)
|
||||
}
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
blockHeaders := make([]*types.Header, 2)
|
||||
ticker := time.NewTicker(time.Duration(test.blockTime["0"]) * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
wg.Add(1)
|
||||
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
|
||||
for range ticker.C {
|
||||
blockHeaders[i] = nodes[i].BlockChain().GetHeaderByNumber(test.sprint["0"]*test.change + 10)
|
||||
if blockHeaders[i] != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}(i)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
// Before the end of sprint
|
||||
blockHeaderVal0 := nodes[0].BlockChain().GetHeaderByNumber(test.sprint["0"] - 1)
|
||||
blockHeaderVal1 := nodes[1].BlockChain().GetHeaderByNumber(test.sprint["0"] - 1)
|
||||
assert.Equal(t, blockHeaderVal0.Hash(), blockHeaderVal1.Hash())
|
||||
assert.Equal(t, blockHeaderVal0.Time, blockHeaderVal1.Time)
|
||||
|
||||
author0, err := nodes[0].Engine().Author(blockHeaderVal0)
|
||||
if err != nil {
|
||||
t.Error("Error occured while fetching author", "err", err)
|
||||
}
|
||||
author1, err := nodes[1].Engine().Author(blockHeaderVal1)
|
||||
if err != nil {
|
||||
t.Error("Error occured while fetching author", "err", err)
|
||||
}
|
||||
assert.Equal(t, author0, author1)
|
||||
|
||||
// After the end of sprint
|
||||
author2, err := nodes[0].Engine().Author(blockHeaders[0])
|
||||
if err != nil {
|
||||
t.Error("Error occured while fetching author", "err", err)
|
||||
}
|
||||
author3, err := nodes[1].Engine().Author(blockHeaders[1])
|
||||
if err != nil {
|
||||
t.Error("Error occured while fetching author", "err", err)
|
||||
}
|
||||
|
||||
if test.forkExpected {
|
||||
assert.NotEqual(t, blockHeaders[0].Hash(), blockHeaders[1].Hash())
|
||||
assert.NotEqual(t, blockHeaders[0].Time, blockHeaders[1].Time)
|
||||
assert.NotEqual(t, author2, author3)
|
||||
} else {
|
||||
assert.Equal(t, blockHeaders[0].Hash(), blockHeaders[1].Hash())
|
||||
assert.Equal(t, blockHeaders[0].Time, blockHeaders[1].Time)
|
||||
assert.Equal(t, author2, author3)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestInsertingSpanSizeBlocks(t *testing.T) {
|
||||
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
|
||||
chain := init.ethereum.BlockChain()
|
||||
|
|
@ -341,13 +673,13 @@ func TestSignerNotFound(t *testing.T) {
|
|||
|
||||
// TestEIP1559Transition tests the following:
|
||||
//
|
||||
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
|
||||
// 2. Gas accounting for access lists on EIP-1559 transactions is correct.
|
||||
// 3. Only the transaction's tip will be received by the coinbase.
|
||||
// 4. The transaction sender pays for both the tip and baseFee.
|
||||
// 5. The coinbase receives only the partially realized tip when
|
||||
// gasFeeCap - gasTipCap < baseFee.
|
||||
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
|
||||
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
|
||||
// 2. Gas accounting for access lists on EIP-1559 transactions is correct.
|
||||
// 3. Only the transaction's tip will be received by the coinbase.
|
||||
// 4. The transaction sender pays for both the tip and baseFee.
|
||||
// 5. The coinbase receives only the partially realized tip when
|
||||
// gasFeeCap - gasTipCap < baseFee.
|
||||
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
|
||||
func TestEIP1559Transition(t *testing.T) {
|
||||
var (
|
||||
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
|
||||
|
|
@ -741,11 +1073,11 @@ func TestJaipurFork(t *testing.T) {
|
|||
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor, nil, res.Result.ValidatorSet.Validators)
|
||||
insertNewBlock(t, chain, block)
|
||||
|
||||
if block.Number().Uint64() == init.genesis.Config.Bor.JaipurBlock-1 {
|
||||
if block.Number().Uint64() == init.genesis.Config.Bor.JaipurBlock.Uint64()-1 {
|
||||
require.Equal(t, testSealHash(block.Header(), init.genesis.Config.Bor), bor.SealHash(block.Header(), init.genesis.Config.Bor))
|
||||
}
|
||||
|
||||
if block.Number().Uint64() == init.genesis.Config.Bor.JaipurBlock {
|
||||
if block.Number().Uint64() == init.genesis.Config.Bor.JaipurBlock.Uint64() {
|
||||
require.Equal(t, testSealHash(block.Header(), init.genesis.Config.Bor), bor.SealHash(block.Header(), init.genesis.Config.Bor))
|
||||
}
|
||||
}
|
||||
|
|
@ -777,7 +1109,7 @@ func testEncodeSigHeader(w io.Writer, header *types.Header, c *params.BorConfig)
|
|||
header.MixDigest,
|
||||
header.Nonce,
|
||||
}
|
||||
if c.IsJaipur(header.Number.Uint64()) {
|
||||
if c.IsJaipur(header.Number) {
|
||||
if header.BaseFee != nil {
|
||||
enc = append(enc, header.BaseFee)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package bor
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
|
@ -16,6 +17,7 @@ import (
|
|||
"github.com/golang/mock/gomock"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
|
|
@ -32,7 +34,13 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/tests/bor/mocks"
|
||||
)
|
||||
|
|
@ -46,6 +54,8 @@ var (
|
|||
// This account is one the validators for 1st span (0-indexed)
|
||||
key2, _ = crypto.HexToECDSA(privKey2)
|
||||
addr2 = crypto.PubkeyToAddress(key2.PublicKey) // 0x9fB29AAc15b9A4B7F17c3385939b007540f4d791
|
||||
|
||||
keys = []*ecdsa.PrivateKey{key, key2}
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -66,6 +76,39 @@ type initializeData struct {
|
|||
ethereum *eth.Ethereum
|
||||
}
|
||||
|
||||
func setupMiner(t *testing.T, n int, genesis *core.Genesis) ([]*node.Node, []*eth.Ethereum, []*enode.Node) {
|
||||
t.Helper()
|
||||
|
||||
// Create an Ethash network based off of the Ropsten config
|
||||
var (
|
||||
stacks []*node.Node
|
||||
nodes []*eth.Ethereum
|
||||
enodes []*enode.Node
|
||||
)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
// Start the node and wait until it's up
|
||||
stack, ethBackend, err := InitMiner(genesis, keys[i], true)
|
||||
if err != nil {
|
||||
t.Fatal("Error occured while initialising miner", "error", err)
|
||||
}
|
||||
|
||||
for stack.Server().NodeInfo().Ports.Listener == 0 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
// Connect the node to all the previous ones
|
||||
for _, n := range enodes {
|
||||
stack.Server().AddPeer(n)
|
||||
}
|
||||
// Start tracking the node and its enode
|
||||
stacks = append(stacks, stack)
|
||||
nodes = append(nodes, ethBackend)
|
||||
enodes = append(enodes, stack.Server().Self())
|
||||
}
|
||||
|
||||
return stacks, nodes, enodes
|
||||
}
|
||||
|
||||
func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData {
|
||||
genesisData, err := ioutil.ReadFile("./testdata/genesis.json")
|
||||
if err != nil {
|
||||
|
|
@ -362,3 +405,95 @@ func IsSprintStart(number uint64) bool {
|
|||
func IsSprintEnd(number uint64) bool {
|
||||
return (number+1)%sprintSize == 0
|
||||
}
|
||||
|
||||
func InitGenesis(t *testing.T, faucets []*ecdsa.PrivateKey, fileLocation string, sprintSize uint64) *core.Genesis {
|
||||
t.Helper()
|
||||
|
||||
// sprint size = 8 in genesis
|
||||
genesisData, err := ioutil.ReadFile(fileLocation)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
genesis := &core.Genesis{}
|
||||
|
||||
if err := json.Unmarshal(genesisData, genesis); err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
genesis.Config.ChainID = big.NewInt(15001)
|
||||
genesis.Config.EIP150Hash = common.Hash{}
|
||||
genesis.Config.Bor.Sprint["0"] = sprintSize
|
||||
|
||||
return genesis
|
||||
}
|
||||
|
||||
func InitMiner(genesis *core.Genesis, privKey *ecdsa.PrivateKey, withoutHeimdall bool) (*node.Node, *eth.Ethereum, error) {
|
||||
// Define the basic configurations for the Ethereum node
|
||||
datadir, _ := ioutil.TempDir("", "")
|
||||
|
||||
config := &node.Config{
|
||||
Name: "geth",
|
||||
Version: params.Version,
|
||||
DataDir: datadir,
|
||||
P2P: p2p.Config{
|
||||
ListenAddr: "0.0.0.0:0",
|
||||
NoDiscovery: true,
|
||||
MaxPeers: 25,
|
||||
},
|
||||
UseLightweightKDF: true,
|
||||
}
|
||||
// Create the node and configure a full Ethereum node on it
|
||||
stack, err := node.New(config)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ethBackend, err := eth.New(stack, ðconfig.Config{
|
||||
Genesis: genesis,
|
||||
NetworkId: genesis.Config.ChainID.Uint64(),
|
||||
SyncMode: downloader.FullSync,
|
||||
DatabaseCache: 256,
|
||||
DatabaseHandles: 256,
|
||||
TxPool: core.DefaultTxPoolConfig,
|
||||
GPO: ethconfig.Defaults.GPO,
|
||||
Ethash: ethconfig.Defaults.Ethash,
|
||||
Miner: miner.Config{
|
||||
Etherbase: crypto.PubkeyToAddress(privKey.PublicKey),
|
||||
GasCeil: genesis.GasLimit * 11 / 10,
|
||||
GasPrice: big.NewInt(1),
|
||||
Recommit: time.Second,
|
||||
},
|
||||
WithoutHeimdall: withoutHeimdall,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// register backend to account manager with keystore for signing
|
||||
keydir := stack.KeyStoreDir()
|
||||
|
||||
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
||||
kStore := keystore.NewKeyStore(keydir, n, p)
|
||||
|
||||
_, err = kStore.ImportECDSA(privKey, "")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
acc := kStore.Accounts()[0]
|
||||
err = kStore.Unlock(acc, "")
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// proceed to authorize the local account manager in any case
|
||||
ethBackend.AccountManager().AddBackend(kStore)
|
||||
|
||||
err = stack.Start()
|
||||
|
||||
return stack, ethBackend, err
|
||||
}
|
||||
|
|
|
|||
10
tests/bor/testdata/genesis.json
vendored
10
tests/bor/testdata/genesis.json
vendored
|
|
@ -15,11 +15,17 @@
|
|||
"londonBlock": 1,
|
||||
"bor": {
|
||||
"jaipurBlock": 2,
|
||||
"delhiBlock" :3,
|
||||
"period": {
|
||||
"0": 1
|
||||
},
|
||||
"producerDelay": 4,
|
||||
"sprint": 4,
|
||||
"producerDelay": {
|
||||
"0": 6
|
||||
},
|
||||
"sprint": {
|
||||
"0": 4,
|
||||
"32": 2
|
||||
},
|
||||
"backupMultiplier": {
|
||||
"0": 1
|
||||
},
|
||||
|
|
|
|||
126
tests/bor/testdata/genesis_21val.json
vendored
Normal file
126
tests/bor/testdata/genesis_21val.json
vendored
Normal file
File diff suppressed because one or more lines are too long
10
tests/bor/testdata/genesis_2val.json
vendored
10
tests/bor/testdata/genesis_2val.json
vendored
|
|
@ -15,11 +15,16 @@
|
|||
"londonBlock": 1,
|
||||
"bor": {
|
||||
"jaipurBlock": 2,
|
||||
"delhiBlock" :3,
|
||||
"period": {
|
||||
"0": 1
|
||||
},
|
||||
"producerDelay": 4,
|
||||
"sprint": 8,
|
||||
"producerDelay": {
|
||||
"0": 4
|
||||
},
|
||||
"sprint": {
|
||||
"0": 8
|
||||
},
|
||||
"backupMultiplier": {
|
||||
"0": 1
|
||||
},
|
||||
|
|
@ -61,4 +66,3 @@
|
|||
"gasUsed": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
|
||||
83
tests/bor/testdata/genesis_7val.json
vendored
Normal file
83
tests/bor/testdata/genesis_7val.json
vendored
Normal file
File diff suppressed because one or more lines are too long
69
tests/bor/testdata/genesis_sprint_length_change.json
vendored
Normal file
69
tests/bor/testdata/genesis_sprint_length_change.json
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -2,9 +2,9 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/tests/fuzzers/difficulty"
|
||||
)
|
||||
|
||||
|
|
@ -14,10 +14,11 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
crasher := os.Args[1]
|
||||
data, err := ioutil.ReadFile(crasher)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
|
||||
os.Exit(1)
|
||||
|
||||
data := common.VerifyCrasher(crasher)
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
|
||||
difficulty.Fuzz(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/tests/fuzzers/les"
|
||||
)
|
||||
|
||||
|
|
@ -32,10 +32,11 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
crasher := os.Args[1]
|
||||
data, err := ioutil.ReadFile(crasher)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
|
||||
os.Exit(1)
|
||||
|
||||
data := common.VerifyCrasher(crasher)
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
|
||||
les.Fuzz(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/tests/fuzzers/rangeproof"
|
||||
)
|
||||
|
||||
|
|
@ -32,10 +32,11 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
crasher := os.Args[1]
|
||||
data, err := ioutil.ReadFile(crasher)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
|
||||
os.Exit(1)
|
||||
|
||||
data := common.VerifyCrasher(crasher)
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
|
||||
rangeproof.Fuzz(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/tests/fuzzers/snap"
|
||||
)
|
||||
|
||||
|
|
@ -30,10 +30,11 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
crasher := os.Args[1]
|
||||
data, err := ioutil.ReadFile(crasher)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
|
||||
os.Exit(1)
|
||||
|
||||
data := common.VerifyCrasher(crasher)
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
|
||||
snap.FuzzTrieNodes(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/tests/fuzzers/stacktrie"
|
||||
)
|
||||
|
||||
|
|
@ -14,10 +14,11 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
crasher := os.Args[1]
|
||||
data, err := ioutil.ReadFile(crasher)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
|
||||
os.Exit(1)
|
||||
|
||||
data := common.VerifyCrasher(crasher)
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
|
||||
stacktrie.Debug(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/tests/fuzzers/vflux"
|
||||
)
|
||||
|
|
@ -35,10 +35,11 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
crasher := os.Args[1]
|
||||
data, err := ioutil.ReadFile(crasher)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
|
||||
os.Exit(1)
|
||||
|
||||
data := common.VerifyCrasher(crasher)
|
||||
if data == nil {
|
||||
return
|
||||
}
|
||||
|
||||
vflux.FuzzClientPool(data)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue