Compare commits
11 Commits
token-reco
...
faucet-rat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a40ee2828a | ||
|
|
f219c080c7 | ||
|
|
75c18c9817 | ||
|
|
45c683fc1d | ||
|
|
c5f157cfad | ||
|
|
e18194720b | ||
|
|
a85215cd70 | ||
|
|
cd3539ab18 | ||
|
|
a9893492ba | ||
|
|
8fe7ca0b3b | ||
|
|
d98b22ba75 |
16
.github/workflows/pre-release.yml
vendored
16
.github/workflows/pre-release.yml
vendored
@@ -82,28 +82,28 @@ jobs:
|
||||
# ==============================
|
||||
|
||||
- name: Upload Linux Build
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
uses: actions/upload-artifact@v3
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
name: linux
|
||||
path: ./build/bin/geth
|
||||
|
||||
- name: Upload MacOS Build
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
uses: actions/upload-artifact@v3
|
||||
if: matrix.os == 'macos-latest'
|
||||
with:
|
||||
name: macos
|
||||
path: ./build/bin/geth
|
||||
|
||||
- name: Upload Windows Build
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
uses: actions/upload-artifact@v3
|
||||
if: matrix.os == 'windows-latest'
|
||||
with:
|
||||
name: windows
|
||||
path: ./build/bin/geth.exe
|
||||
|
||||
- name: Upload ARM-64 Build
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
uses: actions/upload-artifact@v3
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
name: arm64
|
||||
@@ -125,25 +125,25 @@ jobs:
|
||||
# ==============================
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux
|
||||
path: ./linux
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: macos
|
||||
path: ./macos
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows
|
||||
path: ./windows
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: arm64
|
||||
path: ./arm64
|
||||
|
||||
16
.github/workflows/release.yml
vendored
16
.github/workflows/release.yml
vendored
@@ -81,28 +81,28 @@ jobs:
|
||||
# ==============================
|
||||
|
||||
- name: Upload Linux Build
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
uses: actions/upload-artifact@v3
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
name: linux
|
||||
path: ./build/bin/geth
|
||||
|
||||
- name: Upload MacOS Build
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
uses: actions/upload-artifact@v3
|
||||
if: matrix.os == 'macos-latest'
|
||||
with:
|
||||
name: macos
|
||||
path: ./build/bin/geth
|
||||
|
||||
- name: Upload Windows Build
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
uses: actions/upload-artifact@v3
|
||||
if: matrix.os == 'windows-latest'
|
||||
with:
|
||||
name: windows
|
||||
path: ./build/bin/geth.exe
|
||||
|
||||
- name: Upload ARM-64 Build
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
uses: actions/upload-artifact@v3
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
name: arm64
|
||||
@@ -124,25 +124,25 @@ jobs:
|
||||
# ==============================
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux
|
||||
path: ./linux
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: macos
|
||||
path: ./macos
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows
|
||||
path: ./windows
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: arm64
|
||||
path: ./arm64
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
CVE-2024-34478 # "CWE-754: Improper Check for Unusual or Exceptional Conditions." This vulnerability is BTC only, BSC does not have the issue.
|
||||
CVE-2024-6104 # "CWE-532: Information Exposure Through Log Files" This is caused by the vulnerabilities go-retryablehttp@v0.7.4, it is only used in cmd devp2p, impact is limited. will upgrade to v0.7.7 later
|
||||
CVE-2024-8421 # "CWE-400: Uncontrolled Resource Consumption (Resource Exhaustion)" This vulnerability is caused by issues in the golang.org/x/net package. Even the latest version(v0.29.0) has not yet addressed it, but we will continue to monitor updates closely.
|
||||
67
CHANGELOG.md
67
CHANGELOG.md
@@ -1,70 +1,4 @@
|
||||
# Changelog
|
||||
## v1.4.15
|
||||
### BUGFIX
|
||||
* [\#2680](https://github.com/bnb-chain/bsc/pull/2680) txpool: apply miner's gasceil to txpool
|
||||
* [\#2688](https://github.com/bnb-chain/bsc/pull/2688) txpool: set default GasCeil from 30M to 0
|
||||
* [\#2696](https://github.com/bnb-chain/bsc/pull/2696) miner: limit block size to eth protocol msg size
|
||||
* [\#2684](https://github.com/bnb-chain/bsc/pull/2684) eth: Add sidecars when available to broadcasted current block
|
||||
|
||||
### FEATURE
|
||||
* [\#2672](https://github.com/bnb-chain/bsc/pull/2672) faucet: with mainnet balance check, 0.002BNB at least
|
||||
* [\#2678](https://github.com/bnb-chain/bsc/pull/2678) beaconserver: simulated beacon api server for op-stack
|
||||
* [\#2687](https://github.com/bnb-chain/bsc/pull/2687) faucet: support customized token
|
||||
* [\#2698](https://github.com/bnb-chain/bsc/pull/2698) faucet: add example for custimized token
|
||||
* [\#2706](https://github.com/bnb-chain/bsc/pull/2706) faucet: update DIN token faucet support
|
||||
|
||||
### IMPROVEMENT
|
||||
* [\#2677](https://github.com/bnb-chain/bsc/pull/2677) log: add some p2p log
|
||||
* [\#2679](https://github.com/bnb-chain/bsc/pull/2679) build(deps): bump actions/download-artifact in /.github/workflows
|
||||
* [\#2662](https://github.com/bnb-chain/bsc/pull/2662) metrics: add some extra feature flags as node stats
|
||||
* [\#2675](https://github.com/bnb-chain/bsc/pull/2675) fetcher: Sleep after marking block as done when requeuing
|
||||
* [\#2695](https://github.com/bnb-chain/bsc/pull/2695) CI: nancy ignore CVE-2024-8421
|
||||
* [\#2689](https://github.com/bnb-chain/bsc/pull/2689) consensus/parlia: wait more time when processing huge blocks
|
||||
|
||||
## v1.4.14
|
||||
|
||||
### BUGFIX
|
||||
* [\#2643](https://github.com/bnb-chain/bsc/pull/2643)core: fix cache for receipts
|
||||
* [\#2656](https://github.com/bnb-chain/bsc/pull/2656)ethclient: fix BlobSidecars api
|
||||
* [\#2657](https://github.com/bnb-chain/bsc/pull/2657)fix: update prunefreezer’s offset when pruneancient and the dataset has pruned block
|
||||
|
||||
### FEATURE
|
||||
* [\#2661](https://github.com/bnb-chain/bsc/pull/2661)config: setup Mainnet 2 hardfork date: HaberFix & Bohr
|
||||
|
||||
### IMPROVEMENT
|
||||
* [\#2578](https://github.com/bnb-chain/bsc/pull/2578)core/systemcontracts: use vm.StateDB in UpgradeBuildInSystemContract
|
||||
* [\#2649](https://github.com/bnb-chain/bsc/pull/2649)internal/debug: remove memsize
|
||||
* [\#2655](https://github.com/bnb-chain/bsc/pull/2655)internal/ethapi: make GetFinalizedHeader monotonically increasing
|
||||
* [\#2658](https://github.com/bnb-chain/bsc/pull/2658)core: improve readability of the fork choice logic
|
||||
* [\#2665](https://github.com/bnb-chain/bsc/pull/2665)faucet: bump and resend faucet transaction if it has been pending for a while
|
||||
|
||||
## v1.4.13
|
||||
|
||||
### BUGFIX
|
||||
* [\#2602](https://github.com/bnb-chain/bsc/pull/2602) fix: prune-state when specify --triesInMemory 32
|
||||
* [\#2579](https://github.com/bnb-chain/bsc/pull/00025790) fix: only take non-mempool tx to calculate bid price
|
||||
|
||||
### FEATURE
|
||||
* [\#2634](https://github.com/bnb-chain/bsc/pull/2634) config: setup Testnet Bohr hardfork date
|
||||
* [\#2482](https://github.com/bnb-chain/bsc/pull/2482) BEP-341: Validators can produce consecutive blocks
|
||||
* [\#2502](https://github.com/bnb-chain/bsc/pull/2502) BEP-402: Complete Missing Fields in Block Header to Generate Signature
|
||||
* [\#2558](https://github.com/bnb-chain/bsc/pull/2558) BEP-404: Clear Miner History when Switching Validators Set
|
||||
* [\#2605](https://github.com/bnb-chain/bsc/pull/2605) feat: add bohr upgrade contracts bytecode
|
||||
* [\#2614](https://github.com/bnb-chain/bsc/pull/2614) fix: update stakehub bytecode after zero address agent issue fixed
|
||||
* [\#2608](https://github.com/bnb-chain/bsc/pull/2608) consensus/parlia: modify mining time for last block in one turn
|
||||
* [\#2618](https://github.com/bnb-chain/bsc/pull/2618) consensus/parlia: exclude inturn validator when calculate backoffTime
|
||||
* [\#2621](https://github.com/bnb-chain/bsc/pull/2621) core: not record zero hash beacon block root with Parlia engine
|
||||
|
||||
### IMPROVEMENT
|
||||
* [\#2589](https://github.com/bnb-chain/bsc/pull/2589) core/vote: vote before committing state and writing block
|
||||
* [\#2596](https://github.com/bnb-chain/bsc/pull/2596) core: improve the network stability when double sign happens
|
||||
* [\#2600](https://github.com/bnb-chain/bsc/pull/2600) core: cache block after wroten into db
|
||||
* [\#2629](https://github.com/bnb-chain/bsc/pull/2629) utils: add GetTopAddr to analyse large traffic
|
||||
* [\#2591](https://github.com/bnb-chain/bsc/pull/2591) consensus/parlia: add GetJustifiedNumber and GetFinalizedNumber
|
||||
* [\#2611](https://github.com/bnb-chain/bsc/pull/2611) cmd/utils: add new flag OverridePassedForkTime
|
||||
* [\#2603](https://github.com/bnb-chain/bsc/pull/2603) faucet: rate limit initial implementation
|
||||
* [\#2622](https://github.com/bnb-chain/bsc/pull/2622) tests: fix evm-test CI
|
||||
* [\#2628](https://github.com/bnb-chain/bsc/pull/2628) Makefile: use docker compose v2 instead of v1
|
||||
|
||||
## v1.4.12
|
||||
|
||||
@@ -101,6 +35,7 @@
|
||||
* [\#2534](https://github.com/bnb-chain/bsc/pull/2534) fix: nil pointer when clear simulating bid
|
||||
* [\#2535](https://github.com/bnb-chain/bsc/pull/2535) upgrade: add HaberFix hardfork
|
||||
|
||||
|
||||
## v1.4.10
|
||||
### FEATURE
|
||||
NA
|
||||
|
||||
13
Makefile
13
Makefile
@@ -17,11 +17,6 @@ geth:
|
||||
@echo "Done building."
|
||||
@echo "Run \"$(GOBIN)/geth\" to launch geth."
|
||||
|
||||
#? faucet: Build faucet
|
||||
faucet:
|
||||
$(GORUN) build/ci.go install ./cmd/faucet
|
||||
@echo "Done building faucet"
|
||||
|
||||
#? all: Build all packages and executables
|
||||
all:
|
||||
$(GORUN) build/ci.go install
|
||||
@@ -34,11 +29,11 @@ truffle-test:
|
||||
docker build . -f ./docker/Dockerfile --target bsc-genesis -t bsc-genesis
|
||||
docker build . -f ./docker/Dockerfile --target bsc -t bsc
|
||||
docker build . -f ./docker/Dockerfile.truffle -t truffle-test
|
||||
docker compose -f ./tests/truffle/docker-compose.yml up genesis
|
||||
docker compose -f ./tests/truffle/docker-compose.yml up -d bsc-rpc bsc-validator1
|
||||
docker-compose -f ./tests/truffle/docker-compose.yml up genesis
|
||||
docker-compose -f ./tests/truffle/docker-compose.yml up -d bsc-rpc bsc-validator1
|
||||
sleep 30
|
||||
docker compose -f ./tests/truffle/docker-compose.yml up --exit-code-from truffle-test truffle-test
|
||||
docker compose -f ./tests/truffle/docker-compose.yml down
|
||||
docker-compose -f ./tests/truffle/docker-compose.yml up --exit-code-from truffle-test truffle-test
|
||||
docker-compose -f ./tests/truffle/docker-compose.yml down
|
||||
|
||||
#? lint: Run certain pre-selected linters
|
||||
lint: ## Run linters.
|
||||
|
||||
26
README.md
26
README.md
@@ -9,15 +9,16 @@ https://pkg.go.dev/badge/github.com/ethereum/go-ethereum
|
||||
)](https://pkg.go.dev/github.com/ethereum/go-ethereum?tab=doc)
|
||||
[](https://discord.gg/z2VpC455eU)
|
||||
|
||||
But from that baseline of EVM compatible, BNB Smart Chain introduces a system of 21 validators with Proof of Staked Authority (PoSA) consensus that can support short block time and lower fees. The most bonded validator candidates of staking will become validators and produce blocks. The double-sign detection and other slashing logic guarantee security, stability, and chain finality.
|
||||
But from that baseline of EVM compatible, BNB Smart Chain introduces a system of 21 validators with Proof of Staked Authority (PoSA) consensus that can support short block time and lower fees. The most bonded validator candidates of staking will become validators and produce blocks. The double-sign detection and other slashing logic guarantee security, stability, and chain finality.
|
||||
|
||||
**The BNB Smart Chain** will be:
|
||||
Cross-chain transfer and other communication are possible due to native support of interoperability. Relayers and on-chain contracts are developed to support that. BNB Beacon Chain DEX remains a liquid venue of the exchange of assets on both chains. This dual-chain architecture will be ideal for users to take advantage of the fast trading on one side and build their decentralized apps on the other side. **The BNB Smart Chain** will be:
|
||||
|
||||
- **A self-sovereign blockchain**: Provides security and safety with elected validators.
|
||||
- **EVM-compatible**: Supports all the existing Ethereum tooling along with faster finality and cheaper transaction fees.
|
||||
- **Interoperable**: Comes with efficient native dual chain communication; Optimized for scaling high-performance dApps that require fast and smooth user experience.
|
||||
- **Distributed with on-chain governance**: Proof of Staked Authority brings in decentralization and community participants. As the native token, BNB will serve as both the gas of smart contract execution and tokens for staking.
|
||||
|
||||
More details in [White Paper](https://github.com/bnb-chain/whitepaper/blob/master/WHITEPAPER.md).
|
||||
More details in [White Paper](https://www.bnbchain.org/en#smartChain).
|
||||
|
||||
## Key features
|
||||
|
||||
@@ -33,8 +34,18 @@ To combine DPoS and PoA for consensus, BNB Smart Chain implement a novel consens
|
||||
|
||||
1. Blocks are produced by a limited set of validators.
|
||||
2. Validators take turns to produce blocks in a PoA manner, similar to Ethereum's Clique consensus engine.
|
||||
3. Validator set are elected in and out based on a staking based governance on BNB Smart Chain.
|
||||
4. Parlia consensus engine will interact with a set of [system contracts](https://docs.bnbchain.org/bnb-smart-chain/staking/overview/#system-contracts) to achieve liveness slash, revenue distributing and validator set renewing func.
|
||||
3. Validator set are elected in and out based on a staking based governance on BNB Beacon Chain.
|
||||
4. The validator set change is relayed via a cross-chain communication mechanism.
|
||||
5. Parlia consensus engine will interact with a set of [system contracts](https://docs.bnbchain.org/bnb-smart-chain/staking/overview/#system-contracts) to achieve liveness slash, revenue distributing and validator set renewing func.
|
||||
|
||||
|
||||
### Light Client of BNB Beacon Chain
|
||||
|
||||
To achieve the cross-chain communication from BNB Beacon Chain to BNB Smart Chain, need introduce a on-chain light client verification algorithm.
|
||||
It contains two parts:
|
||||
|
||||
1. [Stateless Precompiled contracts](https://github.com/bnb-chain/bsc/blob/master/core/vm/contracts_lightclient.go) to do tendermint header verification and Merkle Proof verification.
|
||||
2. [Stateful solidity contracts](https://github.com/bnb-chain/bsc-genesis-contract/blob/master/contracts/TendermintLightClient.sol) to store validator set and trusted appHash.
|
||||
|
||||
## Native Token
|
||||
|
||||
@@ -42,6 +53,7 @@ BNB will run on BNB Smart Chain in the same way as ETH runs on Ethereum so that
|
||||
BNB will be used to:
|
||||
|
||||
1. pay `gas` to deploy or invoke Smart Contract on BSC
|
||||
2. perform cross-chain operations, such as transfer token assets across BNB Smart Chain and BNB Beacon Chain.
|
||||
|
||||
## Building the source
|
||||
|
||||
@@ -235,7 +247,9 @@ running web servers, so malicious web pages could try to subvert locally availab
|
||||
APIs!**
|
||||
|
||||
### Operating a private network
|
||||
- [BSC-Deploy](https://github.com/bnb-chain/node-deploy/): deploy tool for setting up BNB Smart Chain.
|
||||
- [BSC-Deploy](https://github.com/bnb-chain/node-deploy/): deploy tool for setting up both BNB Beacon Chain, BNB Smart Chain and the cross chain infrastructure between them.
|
||||
- [BSC-Docker](https://github.com/bnb-chain/bsc-docker): deploy tool for setting up local BSC cluster in container.
|
||||
|
||||
|
||||
## Running a bootnode
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
package fakebeacon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
type BlobSidecar struct {
|
||||
Blob kzg4844.Blob `json:"blob"`
|
||||
Index int `json:"index"`
|
||||
KZGCommitment kzg4844.Commitment `json:"kzg_commitment"`
|
||||
KZGProof kzg4844.Proof `json:"kzg_proof"`
|
||||
}
|
||||
|
||||
type APIGetBlobSidecarsResponse struct {
|
||||
Data []*BlobSidecar `json:"data"`
|
||||
}
|
||||
|
||||
type ReducedGenesisData struct {
|
||||
GenesisTime string `json:"genesis_time"`
|
||||
}
|
||||
|
||||
type APIGenesisResponse struct {
|
||||
Data ReducedGenesisData `json:"data"`
|
||||
}
|
||||
|
||||
type ReducedConfigData struct {
|
||||
SecondsPerSlot string `json:"SECONDS_PER_SLOT"`
|
||||
}
|
||||
|
||||
type IndexedBlobHash struct {
|
||||
Index int // absolute index in the block, a.k.a. position in sidecar blobs array
|
||||
Hash common.Hash // hash of the blob, used for consistency checks
|
||||
}
|
||||
|
||||
func configSpec() ReducedConfigData {
|
||||
return ReducedConfigData{SecondsPerSlot: "1"}
|
||||
}
|
||||
|
||||
func beaconGenesis() APIGenesisResponse {
|
||||
return APIGenesisResponse{Data: ReducedGenesisData{GenesisTime: "0"}}
|
||||
}
|
||||
|
||||
func beaconBlobSidecars(ctx context.Context, backend ethapi.Backend, slot uint64, indices []int) (APIGetBlobSidecarsResponse, error) {
|
||||
var blockNrOrHash rpc.BlockNumberOrHash
|
||||
header, err := fetchBlockNumberByTime(ctx, int64(slot), backend)
|
||||
if err != nil {
|
||||
log.Error("Error fetching block number", "slot", slot, "indices", indices)
|
||||
return APIGetBlobSidecarsResponse{}, err
|
||||
}
|
||||
sideCars, err := backend.GetBlobSidecars(ctx, header.Hash())
|
||||
if err != nil {
|
||||
log.Error("Error fetching Sidecars", "blockNrOrHash", blockNrOrHash, "err", err)
|
||||
return APIGetBlobSidecarsResponse{}, err
|
||||
}
|
||||
sort.Ints(indices)
|
||||
fullBlob := len(indices) == 0
|
||||
res := APIGetBlobSidecarsResponse{}
|
||||
idx := 0
|
||||
curIdx := 0
|
||||
for _, sideCar := range sideCars {
|
||||
for i := 0; i < len(sideCar.Blobs); i++ {
|
||||
//hash := kZGToVersionedHash(sideCar.Commitments[i])
|
||||
if !fullBlob && curIdx >= len(indices) {
|
||||
break
|
||||
}
|
||||
if fullBlob || idx == indices[curIdx] {
|
||||
res.Data = append(res.Data, &BlobSidecar{
|
||||
Index: idx,
|
||||
Blob: sideCar.Blobs[i],
|
||||
KZGCommitment: sideCar.Commitments[i],
|
||||
KZGProof: sideCar.Proofs[i],
|
||||
})
|
||||
curIdx++
|
||||
}
|
||||
idx++
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package fakebeacon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
)
|
||||
|
||||
var (
|
||||
versionMethod = "/eth/v1/node/version"
|
||||
specMethod = "/eth/v1/config/spec"
|
||||
genesisMethod = "/eth/v1/beacon/genesis"
|
||||
sidecarsMethodPrefix = "/eth/v1/beacon/blob_sidecars/{slot}"
|
||||
)
|
||||
|
||||
func VersionMethod(w http.ResponseWriter, r *http.Request) {
|
||||
resp := &structs.GetVersionResponse{
|
||||
Data: &structs.Version{
|
||||
Version: "",
|
||||
},
|
||||
}
|
||||
httputil.WriteJson(w, resp)
|
||||
}
|
||||
|
||||
func SpecMethod(w http.ResponseWriter, r *http.Request) {
|
||||
httputil.WriteJson(w, &structs.GetSpecResponse{Data: configSpec()})
|
||||
}
|
||||
|
||||
func GenesisMethod(w http.ResponseWriter, r *http.Request) {
|
||||
httputil.WriteJson(w, beaconGenesis())
|
||||
}
|
||||
|
||||
func (s *Service) SidecarsMethod(w http.ResponseWriter, r *http.Request) {
|
||||
indices, err := parseIndices(r.URL)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
segments := strings.Split(r.URL.Path, "/")
|
||||
slot, err := strconv.ParseUint(segments[len(segments)-1], 10, 64)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, "not a valid slot(timestamp)", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := beaconBlobSidecars(r.Context(), s.backend, slot, indices)
|
||||
if err != nil {
|
||||
httputil.HandleError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
httputil.WriteJson(w, resp)
|
||||
}
|
||||
|
||||
// parseIndices filters out invalid and duplicate blob indices
|
||||
func parseIndices(url *url.URL) ([]int, error) {
|
||||
rawIndices := url.Query()["indices"]
|
||||
indices := make([]int, 0, field_params.MaxBlobsPerBlock)
|
||||
invalidIndices := make([]string, 0)
|
||||
loop:
|
||||
for _, raw := range rawIndices {
|
||||
ix, err := strconv.Atoi(raw)
|
||||
if err != nil {
|
||||
invalidIndices = append(invalidIndices, raw)
|
||||
continue
|
||||
}
|
||||
if ix >= field_params.MaxBlobsPerBlock {
|
||||
invalidIndices = append(invalidIndices, raw)
|
||||
continue
|
||||
}
|
||||
for i := range indices {
|
||||
if ix == indices[i] {
|
||||
continue loop
|
||||
}
|
||||
}
|
||||
indices = append(indices, ix)
|
||||
}
|
||||
|
||||
if len(invalidIndices) > 0 {
|
||||
return nil, fmt.Errorf("requested blob indices %v are invalid", invalidIndices)
|
||||
}
|
||||
return indices, nil
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package fakebeacon
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultAddr = "localhost"
|
||||
DefaultPort = 8686
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Enable bool
|
||||
Addr string
|
||||
Port int
|
||||
}
|
||||
|
||||
func defaultConfig() *Config {
|
||||
return &Config{
|
||||
Enable: false,
|
||||
Addr: DefaultAddr,
|
||||
Port: DefaultPort,
|
||||
}
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
cfg *Config
|
||||
router *mux.Router
|
||||
backend ethapi.Backend
|
||||
}
|
||||
|
||||
func NewService(cfg *Config, backend ethapi.Backend) *Service {
|
||||
cfgs := defaultConfig()
|
||||
if cfg.Addr != "" {
|
||||
cfgs.Addr = cfg.Addr
|
||||
}
|
||||
if cfg.Port > 0 {
|
||||
cfgs.Port = cfg.Port
|
||||
}
|
||||
|
||||
s := &Service{
|
||||
cfg: cfgs,
|
||||
backend: backend,
|
||||
}
|
||||
router := s.newRouter()
|
||||
s.router = router
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Service) Run() {
|
||||
_ = http.ListenAndServe(s.cfg.Addr+":"+strconv.Itoa(s.cfg.Port), s.router)
|
||||
}
|
||||
|
||||
func (s *Service) newRouter() *mux.Router {
|
||||
r := mux.NewRouter()
|
||||
r.Use(server.NormalizeQueryValuesHandler)
|
||||
for _, e := range s.endpoints() {
|
||||
r.HandleFunc(e.path, e.handler).Methods(e.methods...)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
type endpoint struct {
|
||||
path string
|
||||
handler http.HandlerFunc
|
||||
methods []string
|
||||
}
|
||||
|
||||
func (s *Service) endpoints() []endpoint {
|
||||
return []endpoint{
|
||||
{
|
||||
path: versionMethod,
|
||||
handler: VersionMethod,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
path: specMethod,
|
||||
handler: SpecMethod,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
path: genesisMethod,
|
||||
handler: GenesisMethod,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
{
|
||||
path: sidecarsMethodPrefix,
|
||||
handler: s.SidecarsMethod,
|
||||
methods: []string{http.MethodGet},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package fakebeacon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
//
|
||||
//func TestFetchBlockNumberByTime(t *testing.T) {
|
||||
// blockNum, err := fetchBlockNumberByTime(context.Background(), 1724052941, client)
|
||||
// assert.Nil(t, err)
|
||||
// assert.Equal(t, uint64(41493946), blockNum)
|
||||
//
|
||||
// blockNum, err = fetchBlockNumberByTime(context.Background(), 1734052941, client)
|
||||
// assert.Equal(t, err, errors.New("time too large"))
|
||||
//
|
||||
// blockNum, err = fetchBlockNumberByTime(context.Background(), 1600153618, client)
|
||||
// assert.Nil(t, err)
|
||||
// assert.Equal(t, uint64(493946), blockNum)
|
||||
//}
|
||||
//
|
||||
//func TestBeaconBlobSidecars(t *testing.T) {
|
||||
// indexBlobHash := []IndexedBlobHash{
|
||||
// {Hash: common.HexToHash("0x01231952ecbaede62f8d0398b656072c072db36982c9ef106fbbc39ce14f983c"), Index: 0},
|
||||
// {Hash: common.HexToHash("0x012c21a8284d2d707bb5318e874d2e1b97a53d028e96abb702b284a2cbb0f79c"), Index: 1},
|
||||
// {Hash: common.HexToHash("0x011196c8d02536ede0382aa6e9fdba6c460169c0711b5f97fcd701bd8997aee3"), Index: 2},
|
||||
// {Hash: common.HexToHash("0x019c86b46b27401fb978fd175d1eb7dadf4976d6919501b0c5280d13a5bab57b"), Index: 3},
|
||||
// {Hash: common.HexToHash("0x01e00db7ee99176b3fd50aab45b4fae953292334bbf013707aac58c455d98596"), Index: 4},
|
||||
// {Hash: common.HexToHash("0x0117d23b68123d578a98b3e1aa029661e0abda821a98444c21992eb1e5b7208f"), Index: 5},
|
||||
// //{Hash: common.HexToHash("0x01e00db7ee99176b3fd50aab45b4fae953292334bbf013707aac58c455d98596"), Index: 1},
|
||||
// }
|
||||
//
|
||||
// resp, err := beaconBlobSidecars(context.Background(), 1724055046, []int{0, 1, 2, 3, 4, 5}) // block: 41494647
|
||||
// assert.Nil(t, err)
|
||||
// assert.NotNil(t, resp)
|
||||
// assert.NotEmpty(t, resp.Data)
|
||||
// for i, sideCar := range resp.Data {
|
||||
// assert.Equal(t, indexBlobHash[i].Index, sideCar.Index)
|
||||
// assert.Equal(t, indexBlobHash[i].Hash, kZGToVersionedHash(sideCar.KZGCommitment))
|
||||
// }
|
||||
//
|
||||
// apiscs := make([]*BlobSidecar, 0, len(indexBlobHash))
|
||||
// // filter and order by hashes
|
||||
// for _, h := range indexBlobHash {
|
||||
// for _, apisc := range resp.Data {
|
||||
// if h.Index == int(apisc.Index) {
|
||||
// apiscs = append(apiscs, apisc)
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// assert.Equal(t, len(apiscs), len(resp.Data))
|
||||
// assert.Equal(t, len(apiscs), len(indexBlobHash))
|
||||
//}
|
||||
|
||||
type TimeToSlotFn func(timestamp uint64) (uint64, error)
|
||||
|
||||
// GetTimeToSlotFn returns a function that converts a timestamp to a slot number.
|
||||
func GetTimeToSlotFn(ctx context.Context) (TimeToSlotFn, error) {
|
||||
genesis := beaconGenesis()
|
||||
config := configSpec()
|
||||
|
||||
genesisTime, _ := strconv.ParseUint(genesis.Data.GenesisTime, 10, 64)
|
||||
secondsPerSlot, _ := strconv.ParseUint(config.SecondsPerSlot, 10, 64)
|
||||
if secondsPerSlot == 0 {
|
||||
return nil, fmt.Errorf("got bad value for seconds per slot: %v", config.SecondsPerSlot)
|
||||
}
|
||||
timeToSlotFn := func(timestamp uint64) (uint64, error) {
|
||||
if timestamp < genesisTime {
|
||||
return 0, fmt.Errorf("provided timestamp (%v) precedes genesis time (%v)", timestamp, genesisTime)
|
||||
}
|
||||
return (timestamp - genesisTime) / secondsPerSlot, nil
|
||||
}
|
||||
return timeToSlotFn, nil
|
||||
}
|
||||
|
||||
func TestAPI(t *testing.T) {
|
||||
slotFn, err := GetTimeToSlotFn(context.Background())
|
||||
assert.Nil(t, err)
|
||||
|
||||
expTx := uint64(123151345)
|
||||
gotTx, err := slotFn(expTx)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, expTx, gotTx)
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package fakebeacon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
func fetchBlockNumberByTime(ctx context.Context, ts int64, backend ethapi.Backend) (*types.Header, error) {
|
||||
// calc the block number of the ts.
|
||||
currentHeader := backend.CurrentHeader()
|
||||
blockTime := int64(currentHeader.Time)
|
||||
if ts > blockTime {
|
||||
return nil, errors.New("time too large")
|
||||
}
|
||||
blockNum := currentHeader.Number.Uint64()
|
||||
estimateEndNumber := int64(blockNum) - (blockTime-ts)/3
|
||||
// find the end number
|
||||
for {
|
||||
header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(estimateEndNumber))
|
||||
if err != nil {
|
||||
time.Sleep(time.Duration(rand.Int()%180) * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
if header == nil {
|
||||
estimateEndNumber -= 1
|
||||
time.Sleep(time.Duration(rand.Int()%180) * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
headerTime := int64(header.Time)
|
||||
if headerTime == ts {
|
||||
return header, nil
|
||||
}
|
||||
|
||||
// let the estimateEndNumber a little bigger than real value
|
||||
if headerTime > ts+8 {
|
||||
estimateEndNumber -= (headerTime - ts) / 3
|
||||
} else if headerTime < ts {
|
||||
estimateEndNumber += (ts-headerTime)/3 + 1
|
||||
} else {
|
||||
// search one by one
|
||||
for headerTime >= ts {
|
||||
header, err = backend.HeaderByNumber(ctx, rpc.BlockNumber(estimateEndNumber-1))
|
||||
if err != nil {
|
||||
time.Sleep(time.Duration(rand.Int()%180) * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
headerTime = int64(header.Time)
|
||||
if headerTime == ts {
|
||||
return header, nil
|
||||
}
|
||||
estimateEndNumber -= 1
|
||||
if headerTime < ts { //found the real endNumber
|
||||
return nil, fmt.Errorf("block not found by time %d", ts)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,42 +43,7 @@ func TestExtraParse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// case 3, |---Extra Vanity---|---Validators Number and Validators Bytes---|---Turn Length---|---Empty---|---Extra Seal---|
|
||||
{
|
||||
extraData := "0xd983010209846765746889676f312e31392e3131856c696e75780000a6bf97c1152465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c816295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e912d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab03f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a61dd481a114a2e761c554b641742c973867899d300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000069c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca70f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba772b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a517ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e8b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d78869485a6f79b60359f141df90a0c745125b131caaffd12000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b218c5d6af1f979ac42bc68d98a5a0d796c6ab01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4dd66d7c2c7e57f628210187192fb89d4b99dd4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cdcc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a419d1d6bf74282782b0b3eb1413c901d6ecf02e8e28000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d21e9ae3261a475a27bb1028f140bc2a7c843318afd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c192183ee226379db83cffc681495730c11fdde79ba4c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ef0274e31810c9df02f98fafde0f841f4e66a1cd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e99f701bb14cb7dfb68b90bd3e6d1ca656964630de71beffc7f33f7f08ec99d336ec51ad9fad0ac84ae77ca2e8ad9512acc56e0d7c93f3c2ce7de1b69149a5a400"
|
||||
extra, err := parseExtra(extraData)
|
||||
assert.NoError(t, err)
|
||||
{
|
||||
var have = extra.ValidatorSize
|
||||
var want = uint8(21)
|
||||
if have != want {
|
||||
t.Fatalf("extra.ValidatorSize mismatch, have %d, want %d", have, want)
|
||||
}
|
||||
}
|
||||
{
|
||||
var have = common.Bytes2Hex(extra.Validators[14].Address[:])
|
||||
var want = "cc8e6d00c17eb431350c6c50d8b8f05176b90b11"
|
||||
if have != want {
|
||||
t.Fatalf("extra.Validators[14].Address mismatch, have %s, want %s", have, want)
|
||||
}
|
||||
}
|
||||
{
|
||||
var have = common.Bytes2Hex(extra.Validators[18].BLSPublicKey[:])
|
||||
var want = "b2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c192183"
|
||||
if have != want {
|
||||
t.Fatalf("extra.Validators[18].BLSPublicKey mismatch, have %s, want %s", have, want)
|
||||
}
|
||||
}
|
||||
{
|
||||
var have = extra.TurnLength
|
||||
var want = uint8(4)
|
||||
if *have != want {
|
||||
t.Fatalf("extra.TurnLength mismatch, have %d, want %d", *have, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case 4, |---Extra Vanity---|---Empty---|---Vote Attestation---|---Extra Seal---|
|
||||
// case 3, |---Extra Vanity---|---Empty---|---Vote Attestation---|---Extra Seal---|
|
||||
{
|
||||
extraData := "0xd883010205846765746888676f312e32302e35856c696e75780000002995c52af8b5830563efb86089cf168dcf4c5d3cb057926628ad1bf0f03ea67eef1458485578a4f8489afa8a853ecc7af45e2d145c21b70641c4b29f0febd2dd2c61fa1ba174be3fd47f1f5fa2ab9b5c318563d8b70ca58d0d51e79ee32b2fb721649e2cb9d36538361fba11f84c8401d14bb7a0fa67ddb3ba654d6006bf788710032247aa4d1be0707273e696b422b3ff72e9798401d14bbaa01225f505f5a0e1aefadcd2913b7aac9009fe4fb3d1bf57399e0b9dce5947f94280fe6d3647276c4127f437af59eb7c7985b2ae1ebe432619860695cb6106b80cc66c735bc1709afd11f233a2c97409d38ebaf7178aa53e895aea2fe0a229f71ec601"
|
||||
extra, err := parseExtra(extraData)
|
||||
@@ -99,9 +64,9 @@ func TestExtraParse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// case 5, |---Extra Vanity---|---Validators Number and Validators Bytes---|---Vote Attestation---|---Extra Seal---|
|
||||
// case 4, |---Extra Vanity---|---Validators Number and Validators Bytes---|---Vote Attestation---|---Extra Seal---|
|
||||
{
|
||||
extraData := "0xd883010209846765746888676f312e31392e38856c696e7578000000dc55905c071284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c35552c16704d214347f29fa77f77da6d75d7c752b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f247788386d0ed6c748e03a53160b4b30ed3748cc5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d8a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0b973c2d38487e58fd6e145491b110080fb14ac915a0411fc78f19e09a399ddee0d20c63a75d8f930f1694544ad2dc01bb71b214cb885500844365e95cd9942c7276e7fd8a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5ff474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b878f8b27bb8608c11016739b3f8a19e54ab8c7abacd936cfeba200f3645a98b65adb0dd3692b69ce0b3ae10e7176b9a4b0d83f04065b1042b4bcb646a34b75c550f92fc34b8b2b1db0fa0d3172db23ba92727c80bcd306320d0ff411bf858525fde13bc8e0370f84c8401e9c2e6a0820dc11d63176a0eb1b828bc5376867b275579112b7013358da40317e7bab6e98401e9c2e7a00edc71ce80105a3220a87bea2792fa340d66c59002f02b0a09349ed1ed28407080048b972fac2b9077a4dcb6fc37093799a652858016c99142b227500c844fa97ec22e3f9d3b1e982f14bcd999a7453e89ce5ef5c55f1c7f8f74ba904186cd67828200"
|
||||
extraData := "0xd883010209846765746888676f312e31392e38856c696e7578000000dc55905c071284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c35552c16704d214347f29fa77f77da6d75d7c752b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f247788386d0ed6c748e03a53160b4b30ed3748cc5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d8a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0b973c2d38487e58fd6e145491b110080fb14ac915a0411fc78f19e09a399ddee0d20c63a75d8f930f1694544ad2dc01bb71b214cb885500844365e95cd9942c7276e7fd8a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5ff474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b878f8b27bb8608c11016739b3f8a19e54ab8c7abacd936cfeba200f3645a98b65adb0dd3692b69ce0b3ae10e7176b9a4b0d83f04065b1042b4bcb646a34b75c550f92fc34b8b2b1db0fa0d3172db23ba92727c80bcd306320d0ff411bf858525fde13bc8e0370f84c8401e9c2e6a0820dc11d63176a0eb1b828bc5376867b275579112b7013358da40317e7bab6e98401e9c2e7a00edc71ce80105a3220a87bea2792fa340d66c59002f02b0a09349ed1ed284070808b972fac2b9077a4dcb6fc37093799a652858016c99142b227500c844fa97ec22e3f9d3b1e982f14bcd999a7453e89ce5ef5c55f1c7f8f74ba904186cd67828200"
|
||||
extra, err := parseExtra(extraData)
|
||||
assert.NoError(t, err)
|
||||
{
|
||||
@@ -140,53 +105,4 @@ func TestExtraParse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case 6, |---Extra Vanity---|---Validators Number and Validators Bytes---|---Turn Length---|---Vote Attestation---|---Extra Seal---|
|
||||
{
|
||||
extraData := "0xd883010209846765746888676f312e31392e38856c696e7578000000dc55905c071284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c35552c16704d214347f29fa77f77da6d75d7c752b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f247788386d0ed6c748e03a53160b4b30ed3748cc5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d8a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0b973c2d38487e58fd6e145491b110080fb14ac915a0411fc78f19e09a399ddee0d20c63a75d8f930f1694544ad2dc01bb71b214cb885500844365e95cd9942c7276e7fd8a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5ff474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b87804f8b27bb8608c11016739b3f8a19e54ab8c7abacd936cfeba200f3645a98b65adb0dd3692b69ce0b3ae10e7176b9a4b0d83f04065b1042b4bcb646a34b75c550f92fc34b8b2b1db0fa0d3172db23ba92727c80bcd306320d0ff411bf858525fde13bc8e0370f84c8401e9c2e6a0820dc11d63176a0eb1b828bc5376867b275579112b7013358da40317e7bab6e98401e9c2e7a00edc71ce80105a3220a87bea2792fa340d66c59002f02b0a09349ed1ed28407080048b972fac2b9077a4dcb6fc37093799a652858016c99142b227500c844fa97ec22e3f9d3b1e982f14bcd999a7453e89ce5ef5c55f1c7f8f74ba904186cd67828200"
|
||||
extra, err := parseExtra(extraData)
|
||||
assert.NoError(t, err)
|
||||
{
|
||||
var have = common.Bytes2Hex(extra.Validators[0].Address[:])
|
||||
var want = "1284214b9b9c85549ab3d2b972df0deef66ac2c9"
|
||||
if have != want {
|
||||
t.Fatalf("extra.Validators[0].Address mismatch, have %s, want %s", have, want)
|
||||
}
|
||||
}
|
||||
{
|
||||
var have = common.Bytes2Hex(extra.Validators[0].BLSPublicKey[:])
|
||||
var want = "8e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c"
|
||||
if have != want {
|
||||
t.Fatalf("extra.Validators[0].BLSPublicKey mismatch, have %s, want %s", have, want)
|
||||
}
|
||||
}
|
||||
{
|
||||
var have = extra.Validators[0].VoteIncluded
|
||||
var want = true
|
||||
if have != want {
|
||||
t.Fatalf("extra.Validators[0].VoteIncluded mismatch, have %t, want %t", have, want)
|
||||
}
|
||||
}
|
||||
{
|
||||
var have = common.Bytes2Hex(extra.Data.TargetHash[:])
|
||||
var want = "0edc71ce80105a3220a87bea2792fa340d66c59002f02b0a09349ed1ed284070"
|
||||
if have != want {
|
||||
t.Fatalf("extra.Data.TargetHash mismatch, have %s, want %s", have, want)
|
||||
}
|
||||
}
|
||||
{
|
||||
var have = extra.Data.TargetNumber
|
||||
var want = uint64(32096999)
|
||||
if have != want {
|
||||
t.Fatalf("extra.Data.TargetNumber mismatch, have %d, want %d", have, want)
|
||||
}
|
||||
}
|
||||
{
|
||||
var have = extra.TurnLength
|
||||
var want = uint8(4)
|
||||
if *have != want {
|
||||
t.Fatalf("extra.TurnLength mismatch, have %d, want %d", *have, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ const (
|
||||
BLSPublicKeyLength = 48
|
||||
|
||||
// follow order in extra field
|
||||
// |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Turn Length (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---|
|
||||
// |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---|
|
||||
extraVanityLength = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
|
||||
validatorNumberSize = 1 // Fixed number of extra prefix bytes reserved for validator number after Luban
|
||||
validatorBytesLength = common.AddressLength + types.BLSPublicKeyLength
|
||||
@@ -35,7 +35,6 @@ type Extra struct {
|
||||
ExtraVanity string
|
||||
ValidatorSize uint8
|
||||
Validators validatorsAscending
|
||||
TurnLength *uint8
|
||||
*types.VoteAttestation
|
||||
ExtraSeal []byte
|
||||
}
|
||||
@@ -114,15 +113,6 @@ func parseExtra(hexData string) (*Extra, error) {
|
||||
sort.Sort(extra.Validators)
|
||||
data = data[validatorBytesTotalLength-validatorNumberSize:]
|
||||
dataLength = len(data)
|
||||
|
||||
// parse TurnLength
|
||||
if dataLength > 0 {
|
||||
if data[0] != '\xf8' {
|
||||
extra.TurnLength = &data[0]
|
||||
data = data[1:]
|
||||
dataLength = len(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse Vote Attestation
|
||||
@@ -158,10 +148,6 @@ func prettyExtra(extra Extra) {
|
||||
}
|
||||
}
|
||||
|
||||
if extra.TurnLength != nil {
|
||||
fmt.Printf("TurnLength : %d\n", *extra.TurnLength)
|
||||
}
|
||||
|
||||
if extra.VoteAttestation != nil {
|
||||
fmt.Printf("Attestation :\n")
|
||||
fmt.Printf("\tVoteAddressSet : %b, %d\n", extra.VoteAddressSet, bitset.From([]uint64{uint64(extra.VoteAddressSet)}).Count())
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
@@ -1,23 +0,0 @@
|
||||
# 1.Background
|
||||
This is to support some projects with customized tokens that they want to integrate into the BSC faucet tool.
|
||||
|
||||
## 1.1. How to Integrate Your Token
|
||||
- Step 1: Fund the faucet address by sending a specific amount of your BEP-20 token to the faucet address (0xaa25aa7a19f9c426e07dee59b12f944f4d9f1dd3) on the BSC testnet.
|
||||
- Step 2: Update this README.md file and create a Pull Request on [bsc github](https://github.com/bnb-chain/bsc) with relevant information.
|
||||
|
||||
We will review the request, and once it is approved, the faucet tool will start to support the customized token and list it on https://www.bnbchain.org/en/testnet-faucet.
|
||||
|
||||
# 2.Token List
|
||||
## 2.1.DemoToken
|
||||
- symbol: DEMO
|
||||
- amount: 10000000000000000000
|
||||
- icon: ./demotoken.png
|
||||
- addr: https://testnet.bscscan.com/address/0xe15c158d768c306dae87b96430a94f884333e55d
|
||||
- fundTx: [0xa499dc9aaf918aff0507538a8aa80a88d0af6ca15054e6acc57b69c651945280](https://testnet.bscscan.com/tx/0x2a3f334b6ca756b64331bdec9e6cf3207ac50a4839fda6379e909de4d9a194ca)
|
||||
-
|
||||
## 2.2.DIN token
|
||||
- symbol: DIN
|
||||
- amount: 10000000000000000000
|
||||
- icon: ./DIN.png
|
||||
- addr: https://testnet.bscscan.com/address/0xb8b40FcC5B4519Dba0E07Ac8821884CE90BdE677
|
||||
- fundTx: [0x17fc4c1db133830c7c146a0d41ca1df31cb446989ec11b382d58bb6176d6fde3](https://testnet.bscscan.com/tx/0x17fc4c1db133830c7c146a0d41ca1df31cb446989ec11b382d58bb6176d6fde3)
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB |
@@ -53,10 +53,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
genesisFlag = flag.String("genesis", "", "Genesis json file to seed the chain with")
|
||||
apiPortFlag = flag.Int("apiport", 8080, "Listener port for the HTTP API connection")
|
||||
wsEndpoint = flag.String("ws", "http://127.0.0.1:7777/", "Url to ws endpoint")
|
||||
wsEndpointMainnet = flag.String("ws.mainnet", "", "Url to ws endpoint of BSC mainnet")
|
||||
genesisFlag = flag.String("genesis", "", "Genesis json file to seed the chain with")
|
||||
apiPortFlag = flag.Int("apiport", 8080, "Listener port for the HTTP API connection")
|
||||
wsEndpoint = flag.String("ws", "http://127.0.0.1:7777/", "Url to ws endpoint")
|
||||
|
||||
netnameFlag = flag.String("faucet.name", "", "Network name to assign to the faucet")
|
||||
payoutFlag = flag.Int("faucet.amount", 1, "Number of Ethers to pay out per user request")
|
||||
@@ -78,12 +77,6 @@ var (
|
||||
fixGasPrice = flag.Int64("faucet.fixedprice", 0, "Will use fixed gas price if specified")
|
||||
twitterTokenFlag = flag.String("twitter.token", "", "Bearer token to authenticate with the v2 Twitter API")
|
||||
twitterTokenV1Flag = flag.String("twitter.token.v1", "", "Bearer token to authenticate with the v1.1 Twitter API")
|
||||
|
||||
resendInterval = 15 * time.Second
|
||||
resendBatchSize = 3
|
||||
resendMaxGasPrice = big.NewInt(50 * params.GWei)
|
||||
wsReadTimeout = 5 * time.Minute
|
||||
minMainnetBalance = big.NewInt(2 * 1e6 * params.GWei) // 0.002 bnb
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -94,17 +87,11 @@ var (
|
||||
//go:embed faucet.html
|
||||
var websiteTmpl string
|
||||
|
||||
func weiToEtherStringFx(wei *big.Int, prec int) string {
|
||||
etherValue := new(big.Float).Quo(new(big.Float).SetInt(wei), big.NewFloat(params.Ether))
|
||||
// Format the big.Float directly to a string with the specified precision
|
||||
return etherValue.Text('f', prec)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Parse the flags and set up the logger to print everything requested
|
||||
flag.Parse()
|
||||
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.FromLegacyLevel(*logFlag), false)))
|
||||
log.Info("faucet started")
|
||||
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.FromLegacyLevel(*logFlag), true)))
|
||||
|
||||
// Construct the payout tiers
|
||||
amounts := make([]string, *tiersFlag)
|
||||
for i := 0; i < *tiersFlag; i++ {
|
||||
@@ -183,7 +170,7 @@ func main() {
|
||||
log.Crit("Failed to unlock faucet signer account", "err", err)
|
||||
}
|
||||
// Assemble and start the faucet light service
|
||||
faucet, err := newFaucet(genesis, *wsEndpoint, *wsEndpointMainnet, ks, website.Bytes(), bep2eInfos)
|
||||
faucet, err := newFaucet(genesis, *wsEndpoint, ks, website.Bytes(), bep2eInfos)
|
||||
if err != nil {
|
||||
log.Crit("Failed to start faucet", "err", err)
|
||||
}
|
||||
@@ -210,10 +197,9 @@ type bep2eInfo struct {
|
||||
|
||||
// faucet represents a crypto faucet backed by an Ethereum light client.
|
||||
type faucet struct {
|
||||
config *params.ChainConfig // Chain configurations for signing
|
||||
client *ethclient.Client // Client connection to the Ethereum chain
|
||||
clientMainnet *ethclient.Client // Client connection to BSC mainnet for balance check
|
||||
index []byte // Index page to serve up on the web
|
||||
config *params.ChainConfig // Chain configurations for signing
|
||||
client *ethclient.Client // Client connection to the Ethereum chain
|
||||
index []byte // Index page to serve up on the web
|
||||
|
||||
keystore *keystore.KeyStore // Keystore containing the single signer
|
||||
account accounts.Account // Account funding user faucet requests
|
||||
@@ -242,7 +228,7 @@ type wsConn struct {
|
||||
wlock sync.Mutex
|
||||
}
|
||||
|
||||
func newFaucet(genesis *core.Genesis, url string, mainnetUrl string, ks *keystore.KeyStore, index []byte, bep2eInfos map[string]bep2eInfo) (*faucet, error) {
|
||||
func newFaucet(genesis *core.Genesis, url string, ks *keystore.KeyStore, index []byte, bep2eInfos map[string]bep2eInfo) (*faucet, error) {
|
||||
bep2eAbi, err := abi.JSON(strings.NewReader(bep2eAbiJson))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -251,11 +237,6 @@ func newFaucet(genesis *core.Genesis, url string, mainnetUrl string, ks *keystor
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientMainnet, err := ethclient.Dial(mainnetUrl)
|
||||
if err != nil {
|
||||
// skip mainnet balance check if it there is no available mainnet endpoint
|
||||
log.Warn("dail mainnet endpoint failed", "mainnetUrl", mainnetUrl, "err", err)
|
||||
}
|
||||
|
||||
// Allow 1 request per minute with burst of 5, and cache up to 1000 IPs
|
||||
limiter, err := NewIPRateLimiter(rate.Limit(1.0), 5, 1000)
|
||||
@@ -264,17 +245,16 @@ func newFaucet(genesis *core.Genesis, url string, mainnetUrl string, ks *keystor
|
||||
}
|
||||
|
||||
return &faucet{
|
||||
config: genesis.Config,
|
||||
client: client,
|
||||
clientMainnet: clientMainnet,
|
||||
index: index,
|
||||
keystore: ks,
|
||||
account: ks.Accounts()[0],
|
||||
timeouts: make(map[string]time.Time),
|
||||
update: make(chan struct{}, 1),
|
||||
bep2eInfos: bep2eInfos,
|
||||
bep2eAbi: bep2eAbi,
|
||||
limiter: limiter,
|
||||
config: genesis.Config,
|
||||
client: client,
|
||||
index: index,
|
||||
keystore: ks,
|
||||
account: ks.Accounts()[0],
|
||||
timeouts: make(map[string]time.Time),
|
||||
update: make(chan struct{}, 1),
|
||||
bep2eInfos: bep2eInfos,
|
||||
bep2eAbi: bep2eAbi,
|
||||
limiter: limiter,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -398,11 +378,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
Captcha string `json:"captcha"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
// not sure if it helps or not, but set a read deadline could help prevent resource leakage
|
||||
// if user did not give response for too long, then the routine will be stuck.
|
||||
conn.SetReadDeadline(time.Now().Add(wsReadTimeout))
|
||||
if err = conn.ReadJSON(&msg); err != nil {
|
||||
log.Debug("read json message failed", "err", err, "ip", ip)
|
||||
return
|
||||
}
|
||||
if !*noauthFlag && !strings.HasPrefix(msg.URL, "https://twitter.com/") && !strings.HasPrefix(msg.URL, "https://www.facebook.com/") {
|
||||
@@ -420,9 +396,9 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
continue
|
||||
}
|
||||
log.Info("Faucet funds requested", "url", msg.URL, "tier", msg.Tier, "ip", ip)
|
||||
log.Info("Faucet funds requested", "url", msg.URL, "tier", msg.Tier)
|
||||
|
||||
// check #1: captcha verifications to exclude robot
|
||||
// If captcha verifications are enabled, make sure we're not dealing with a robot
|
||||
if *captchaToken != "" {
|
||||
form := url.Values{}
|
||||
form.Add("secret", *captchaSecret)
|
||||
@@ -499,108 +475,88 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
continue
|
||||
}
|
||||
log.Info("Faucet request valid", "url", msg.URL, "tier", msg.Tier, "user", username, "address", address)
|
||||
|
||||
// check #2: check IP and ID(address) to ensure the user didn't request funds too frequently
|
||||
// Ensure the user didn't request funds too recently
|
||||
f.lock.Lock()
|
||||
var (
|
||||
fund bool
|
||||
timeout time.Time
|
||||
)
|
||||
|
||||
if ipTimeout := f.timeouts[ips[len(ips)-2]]; time.Now().Before(ipTimeout) {
|
||||
f.lock.Unlock()
|
||||
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(time.Until(ipTimeout)))); err != nil { // nolint: gosimple
|
||||
log.Warn("Failed to send funding error to client", "err", err)
|
||||
return
|
||||
}
|
||||
log.Info("too frequent funding(ip)", "TimeLeft", common.PrettyDuration(time.Until(ipTimeout)), "ip", ips[len(ips)-2], "ipsStr", ipsStr)
|
||||
f.lock.Unlock()
|
||||
continue
|
||||
}
|
||||
if idTimeout := f.timeouts[id]; time.Now().Before(idTimeout) {
|
||||
f.lock.Unlock()
|
||||
// Send an error if too frequent funding, otherwise a success
|
||||
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(time.Until(idTimeout)))); err != nil { // nolint: gosimple
|
||||
|
||||
if timeout = f.timeouts[id]; time.Now().After(timeout) {
|
||||
var tx *types.Transaction
|
||||
if msg.Symbol == "BNB" {
|
||||
// User wasn't funded recently, create the funding transaction
|
||||
amount := new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(*payoutFlag)), ether), big.NewInt(10))
|
||||
amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil))
|
||||
amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil))
|
||||
|
||||
tx = types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil)
|
||||
} else {
|
||||
tokenInfo, ok := f.bep2eInfos[msg.Symbol]
|
||||
if !ok {
|
||||
f.lock.Unlock()
|
||||
log.Warn("Failed to find symbol", "symbol", msg.Symbol)
|
||||
continue
|
||||
}
|
||||
input, err := f.bep2eAbi.Pack("transfer", address, &tokenInfo.Amount)
|
||||
if err != nil {
|
||||
f.lock.Unlock()
|
||||
log.Warn("Failed to pack transfer transaction", "err", err)
|
||||
continue
|
||||
}
|
||||
tx = types.NewTransaction(f.nonce+uint64(len(f.reqs)), tokenInfo.Contract, nil, 420000, f.price, input)
|
||||
}
|
||||
signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainID)
|
||||
if err != nil {
|
||||
f.lock.Unlock()
|
||||
if err = sendError(wsconn, err); err != nil {
|
||||
log.Warn("Failed to send transaction creation error to client", "err", err)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Submit the transaction and mark as funded if successful
|
||||
if err := f.client.SendTransaction(context.Background(), signed); err != nil {
|
||||
f.lock.Unlock()
|
||||
if err = sendError(wsconn, err); err != nil {
|
||||
log.Warn("Failed to send transaction transmission error to client", "err", err)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
f.reqs = append(f.reqs, &request{
|
||||
Avatar: avatar,
|
||||
Account: address,
|
||||
Time: time.Now(),
|
||||
Tx: signed,
|
||||
})
|
||||
timeout := time.Duration(*minutesFlag*int(math.Pow(3, float64(msg.Tier)))) * time.Minute
|
||||
grace := timeout / 288 // 24h timeout => 5m grace
|
||||
|
||||
f.timeouts[id] = time.Now().Add(timeout - grace)
|
||||
f.timeouts[ips[len(ips)-2]] = time.Now().Add(timeout - grace)
|
||||
fund = true
|
||||
}
|
||||
f.lock.Unlock()
|
||||
|
||||
// Send an error if too frequent funding, otherwise a success
|
||||
if !fund {
|
||||
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(time.Until(timeout)))); err != nil { // nolint: gosimple
|
||||
log.Warn("Failed to send funding error to client", "err", err)
|
||||
return
|
||||
}
|
||||
log.Info("too frequent funding(id)", "TimeLeft", common.PrettyDuration(time.Until(idTimeout)), "id", id)
|
||||
continue
|
||||
}
|
||||
// check #3: minimum mainnet balance check, internal error will bypass the check to avoid blocking the faucet service
|
||||
if f.clientMainnet != nil {
|
||||
mainnetAddr := address
|
||||
balanceMainnet, err := f.clientMainnet.BalanceAt(context.Background(), mainnetAddr, nil)
|
||||
if err != nil {
|
||||
log.Warn("check balance failed, call BalanceAt", "err", err)
|
||||
} else if balanceMainnet == nil {
|
||||
log.Warn("check balance failed, balanceMainnet is nil")
|
||||
} else {
|
||||
if balanceMainnet.Cmp(minMainnetBalance) < 0 {
|
||||
f.lock.Unlock()
|
||||
log.Warn("insufficient BNB on BSC mainnet", "address", mainnetAddr,
|
||||
"balanceMainnet", balanceMainnet, "minMainnetBalance", minMainnetBalance)
|
||||
// Send an error if failed to meet the minimum balance requirement
|
||||
if err = sendError(wsconn, fmt.Errorf("insufficient BNB on BSC mainnet (require >=%sBNB)",
|
||||
weiToEtherStringFx(minMainnetBalance, 3))); err != nil {
|
||||
log.Warn("Failed to send mainnet minimum balance error to client", "err", err)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Info("Faucet request valid", "url", msg.URL, "tier", msg.Tier, "user", username, "address", address, "ip", ip)
|
||||
|
||||
// now, it is ok to send tBNB or other tokens
|
||||
var tx *types.Transaction
|
||||
if msg.Symbol == "BNB" {
|
||||
// User wasn't funded recently, create the funding transaction
|
||||
amount := new(big.Int).Div(new(big.Int).Mul(big.NewInt(int64(*payoutFlag)), ether), big.NewInt(10))
|
||||
amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil))
|
||||
amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil))
|
||||
|
||||
tx = types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil)
|
||||
} else {
|
||||
tokenInfo, ok := f.bep2eInfos[msg.Symbol]
|
||||
if !ok {
|
||||
f.lock.Unlock()
|
||||
log.Warn("Failed to find symbol", "symbol", msg.Symbol)
|
||||
continue
|
||||
}
|
||||
input, err := f.bep2eAbi.Pack("transfer", address, &tokenInfo.Amount)
|
||||
if err != nil {
|
||||
f.lock.Unlock()
|
||||
log.Warn("Failed to pack transfer transaction", "err", err)
|
||||
continue
|
||||
}
|
||||
tx = types.NewTransaction(f.nonce+uint64(len(f.reqs)), tokenInfo.Contract, nil, 420000, f.price, input)
|
||||
}
|
||||
signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainID)
|
||||
if err != nil {
|
||||
f.lock.Unlock()
|
||||
if err = sendError(wsconn, err); err != nil {
|
||||
log.Warn("Failed to send transaction creation error to client", "err", err)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Submit the transaction and mark as funded if successful
|
||||
if err := f.client.SendTransaction(context.Background(), signed); err != nil {
|
||||
f.lock.Unlock()
|
||||
if err = sendError(wsconn, err); err != nil {
|
||||
log.Warn("Failed to send transaction transmission error to client", "err", err)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
f.reqs = append(f.reqs, &request{
|
||||
Avatar: avatar,
|
||||
Account: address,
|
||||
Time: time.Now(),
|
||||
Tx: signed,
|
||||
})
|
||||
timeoutInt64 := time.Duration(*minutesFlag*int(math.Pow(3, float64(msg.Tier)))) * time.Minute
|
||||
grace := timeoutInt64 / 288 // 24h timeout => 5m grace
|
||||
|
||||
f.timeouts[id] = time.Now().Add(timeoutInt64 - grace)
|
||||
f.timeouts[ips[len(ips)-2]] = time.Now().Add(timeoutInt64 - grace)
|
||||
f.lock.Unlock()
|
||||
if err = sendSuccess(wsconn, fmt.Sprintf("Funding request accepted for %s into %s", username, address.Hex())); err != nil {
|
||||
log.Warn("Failed to send funding success to client", "err", err)
|
||||
return
|
||||
@@ -649,52 +605,9 @@ func (f *faucet) refresh(head *types.Header) error {
|
||||
f.lock.Lock()
|
||||
f.head, f.balance = head, balance
|
||||
f.price, f.nonce = price, nonce
|
||||
if len(f.reqs) == 0 {
|
||||
log.Debug("refresh len(f.reqs) == 0", "f.nonce", f.nonce)
|
||||
f.lock.Unlock()
|
||||
return nil
|
||||
}
|
||||
if f.reqs[0].Tx.Nonce() == f.nonce {
|
||||
// if the next Tx failed to be included for a certain time(resendInterval), try to
|
||||
// resend it with higher gasPrice, as it could be discarded in the network.
|
||||
// Also resend extra following txs, as they could be discarded as well.
|
||||
if time.Now().After(f.reqs[0].Time.Add(resendInterval)) {
|
||||
for i, req := range f.reqs {
|
||||
if i >= resendBatchSize {
|
||||
break
|
||||
}
|
||||
prePrice := req.Tx.GasPrice()
|
||||
// bump gas price 20% to replace the previous tx
|
||||
newPrice := new(big.Int).Add(prePrice, new(big.Int).Div(prePrice, big.NewInt(5)))
|
||||
if newPrice.Cmp(resendMaxGasPrice) >= 0 {
|
||||
log.Info("resendMaxGasPrice reached", "newPrice", newPrice, "resendMaxGasPrice", resendMaxGasPrice, "nonce", req.Tx.Nonce())
|
||||
break
|
||||
}
|
||||
newTx := types.NewTransaction(req.Tx.Nonce(), *req.Tx.To(), req.Tx.Value(), req.Tx.Gas(), newPrice, req.Tx.Data())
|
||||
newSigned, err := f.keystore.SignTx(f.account, newTx, f.config.ChainID)
|
||||
if err != nil {
|
||||
log.Error("resend sign tx failed", "err", err)
|
||||
}
|
||||
log.Info("reqs[0] Tx has been stuck for a while, trigger resend",
|
||||
"resendInterval", resendInterval, "resendTxSize", resendBatchSize,
|
||||
"preHash", req.Tx.Hash().Hex(), "newHash", newSigned.Hash().Hex(),
|
||||
"newPrice", newPrice, "nonce", req.Tx.Nonce(), "req.Tx.Gas()", req.Tx.Gas())
|
||||
if err := f.client.SendTransaction(context.Background(), newSigned); err != nil {
|
||||
log.Warn("resend tx failed", "err", err)
|
||||
continue
|
||||
}
|
||||
req.Tx = newSigned
|
||||
}
|
||||
}
|
||||
}
|
||||
// it is abnormal that reqs[0] has larger nonce than next expected nonce.
|
||||
// could be caused by reorg? reset it
|
||||
if f.reqs[0].Tx.Nonce() > f.nonce {
|
||||
log.Warn("reset due to nonce gap", "f.nonce", f.nonce, "f.reqs[0].Tx.Nonce()", f.reqs[0].Tx.Nonce())
|
||||
if len(f.reqs) > 0 && f.reqs[0].Tx.Nonce() > f.nonce {
|
||||
f.reqs = f.reqs[:0]
|
||||
}
|
||||
// remove the reqs if they have smaller nonce, which means it is no longer valid,
|
||||
// either has been accepted or replaced.
|
||||
for len(f.reqs) > 0 && f.reqs[0].Tx.Nonce() < f.nonce {
|
||||
f.reqs = f.reqs[1:]
|
||||
}
|
||||
|
||||
@@ -62,9 +62,7 @@ var (
|
||||
ArgsUsage: "<genesisPath>",
|
||||
Flags: flags.Merge([]cli.Flag{
|
||||
utils.CachePreimagesFlag,
|
||||
utils.OverridePassedForkTime,
|
||||
utils.OverridePascal,
|
||||
utils.OverridePrague,
|
||||
utils.OverrideBohr,
|
||||
utils.OverrideVerkle,
|
||||
utils.MultiDataBaseFlag,
|
||||
}, utils.DatabaseFlags),
|
||||
@@ -255,17 +253,9 @@ func initGenesis(ctx *cli.Context) error {
|
||||
defer stack.Close()
|
||||
|
||||
var overrides core.ChainOverrides
|
||||
if ctx.IsSet(utils.OverridePassedForkTime.Name) {
|
||||
v := ctx.Uint64(utils.OverridePassedForkTime.Name)
|
||||
overrides.OverridePassedForkTime = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverridePascal.Name) {
|
||||
v := ctx.Uint64(utils.OverridePascal.Name)
|
||||
overrides.OverridePascal = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverridePrague.Name) {
|
||||
v := ctx.Uint64(utils.OverridePrague.Name)
|
||||
overrides.OverridePrague = &v
|
||||
if ctx.IsSet(utils.OverrideBohr.Name) {
|
||||
v := ctx.Uint64(utils.OverrideBohr.Name)
|
||||
overrides.OverrideBohr = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
||||
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||
|
||||
@@ -33,7 +33,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
||||
"github.com/ethereum/go-ethereum/accounts/usbwallet"
|
||||
"github.com/ethereum/go-ethereum/beacon/fakebeacon"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
@@ -93,11 +92,10 @@ type ethstatsConfig struct {
|
||||
}
|
||||
|
||||
type gethConfig struct {
|
||||
Eth ethconfig.Config
|
||||
Node node.Config
|
||||
Ethstats ethstatsConfig
|
||||
Metrics metrics.Config
|
||||
FakeBeacon fakebeacon.Config
|
||||
Eth ethconfig.Config
|
||||
Node node.Config
|
||||
Ethstats ethstatsConfig
|
||||
Metrics metrics.Config
|
||||
}
|
||||
|
||||
func loadConfig(file string, cfg *gethConfig) error {
|
||||
@@ -187,17 +185,9 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||
params.RialtoGenesisHash = common.HexToHash(v)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.OverridePassedForkTime.Name) {
|
||||
v := ctx.Uint64(utils.OverridePassedForkTime.Name)
|
||||
cfg.Eth.OverridePassedForkTime = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverridePascal.Name) {
|
||||
v := ctx.Uint64(utils.OverridePascal.Name)
|
||||
cfg.Eth.OverridePascal = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverridePrague.Name) {
|
||||
v := ctx.Uint64(utils.OverridePrague.Name)
|
||||
cfg.Eth.OverridePrague = &v
|
||||
if ctx.IsSet(utils.OverrideBohr.Name) {
|
||||
v := ctx.Uint64(utils.OverrideBohr.Name)
|
||||
cfg.Eth.OverrideBohr = &v
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideVerkle.Name) {
|
||||
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||
@@ -216,9 +206,6 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||
if ctx.IsSet(utils.OverrideBreatheBlockInterval.Name) {
|
||||
params.BreatheBlockInterval = ctx.Uint64(utils.OverrideBreatheBlockInterval.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.OverrideFixedTurnLength.Name) {
|
||||
params.FixedTurnLength = ctx.Uint64(utils.OverrideFixedTurnLength.Name)
|
||||
}
|
||||
|
||||
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
|
||||
|
||||
@@ -248,22 +235,11 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
||||
utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.FakeBeaconAddrFlag.Name) {
|
||||
cfg.FakeBeacon.Addr = ctx.String(utils.FakeBeaconAddrFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.FakeBeaconPortFlag.Name) {
|
||||
cfg.FakeBeacon.Port = ctx.Int(utils.FakeBeaconPortFlag.Name)
|
||||
}
|
||||
if cfg.FakeBeacon.Enable || ctx.IsSet(utils.FakeBeaconEnabledFlag.Name) {
|
||||
go fakebeacon.NewService(&cfg.FakeBeacon, backend).Run()
|
||||
}
|
||||
|
||||
git, _ := version.VCS()
|
||||
utils.SetupMetrics(ctx,
|
||||
utils.EnableBuildInfo(git.Commit, git.Date),
|
||||
utils.EnableMinerInfo(ctx, &cfg.Eth.Miner),
|
||||
utils.EnableNodeInfo(&cfg.Eth.TxPool, stack.Server().NodeInfo()),
|
||||
utils.EnableNodeTrack(ctx, &cfg.Eth, stack),
|
||||
)
|
||||
return stack, backend
|
||||
}
|
||||
|
||||
@@ -72,15 +72,12 @@ var (
|
||||
utils.USBFlag,
|
||||
utils.SmartCardDaemonPathFlag,
|
||||
utils.RialtoHash,
|
||||
utils.OverridePassedForkTime,
|
||||
utils.OverridePascal,
|
||||
utils.OverridePrague,
|
||||
utils.OverrideBohr,
|
||||
utils.OverrideVerkle,
|
||||
utils.OverrideFullImmutabilityThreshold,
|
||||
utils.OverrideMinBlocksForBlobRequests,
|
||||
utils.OverrideDefaultExtraReserveForBlobRequests,
|
||||
utils.OverrideBreatheBlockInterval,
|
||||
utils.OverrideFixedTurnLength,
|
||||
utils.EnablePersonal,
|
||||
utils.TxPoolLocalsFlag,
|
||||
utils.TxPoolNoLocalsFlag,
|
||||
@@ -233,12 +230,6 @@ var (
|
||||
utils.MetricsInfluxDBBucketFlag,
|
||||
utils.MetricsInfluxDBOrganizationFlag,
|
||||
}
|
||||
|
||||
fakeBeaconFlags = []cli.Flag{
|
||||
utils.FakeBeaconEnabledFlag,
|
||||
utils.FakeBeaconAddrFlag,
|
||||
utils.FakeBeaconPortFlag,
|
||||
}
|
||||
)
|
||||
|
||||
var app = flags.NewApp("the go-ethereum command line interface")
|
||||
@@ -293,7 +284,6 @@ func init() {
|
||||
consoleFlags,
|
||||
debug.Flags,
|
||||
metricsFlags,
|
||||
fakeBeaconFlags,
|
||||
)
|
||||
flags.AutoEnvVars(app.Flags, "GETH")
|
||||
|
||||
@@ -379,6 +369,8 @@ func geth(ctx *cli.Context) error {
|
||||
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
|
||||
// miner.
|
||||
func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isConsole bool) {
|
||||
debug.Memsize.Add("node", stack)
|
||||
|
||||
// Start up the node itself
|
||||
utils.StartNode(ctx, stack, isConsole)
|
||||
|
||||
@@ -451,23 +443,22 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
|
||||
}
|
||||
|
||||
// Start auxiliary services if enabled
|
||||
ethBackend, ok := backend.(*eth.EthAPIBackend)
|
||||
gasCeil := ethBackend.Miner().GasCeil()
|
||||
if gasCeil > params.SystemTxsGas {
|
||||
ethBackend.TxPool().SetMaxGas(gasCeil - params.SystemTxsGas)
|
||||
}
|
||||
if ctx.Bool(utils.MiningEnabledFlag.Name) {
|
||||
// Mining only makes sense if a full Ethereum node is running
|
||||
if ctx.String(utils.SyncModeFlag.Name) == "light" {
|
||||
utils.Fatalf("Light clients do not support mining")
|
||||
}
|
||||
|
||||
ethBackend, ok := backend.(*eth.EthAPIBackend)
|
||||
if !ok {
|
||||
utils.Fatalf("Ethereum service not running")
|
||||
}
|
||||
// Set the gas price to the limits from the CLI and start mining
|
||||
gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
|
||||
ethBackend.TxPool().SetGasTip(gasprice)
|
||||
gasCeil := ethBackend.Miner().GasCeil()
|
||||
if gasCeil > params.SystemTxsGas {
|
||||
ethBackend.TxPool().SetMaxGas(gasCeil - params.SystemTxsGas)
|
||||
}
|
||||
if err := ethBackend.StartMining(); err != nil {
|
||||
utils.Fatalf("Failed to start mining: %v", err)
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ const main = async () => {
|
||||
let gasUsedTotal = 0;
|
||||
let inturnBlocks = 0;
|
||||
let justifiedBlocks = 0;
|
||||
let turnLength = await provider.send("parlia_getTurnLength", [
|
||||
ethers.toQuantity(program.startNum)]);
|
||||
for (let i = program.startNum; i < program.endNum; i++) {
|
||||
let txCount = await provider.send("eth_getBlockTransactionCountByNumber", [
|
||||
ethers.toQuantity(i)]);
|
||||
@@ -37,7 +35,7 @@ const main = async () => {
|
||||
} else {
|
||||
console.log("justified unexpected", "BlockNumber =", i,"justifiedNumber",justifiedNumber)
|
||||
}
|
||||
console.log("BlockNumber =", i, "mod =", i%turnLength, "miner =", header.miner , "difficulty =", difficulty, "txCount =", ethers.toNumber(txCount), "gasUsed", gasUsed, "timestamp", timestamp)
|
||||
console.log("BlockNumber =", i, "mod =", i%4, "miner =", header.miner , "difficulty =", difficulty, "txCount =", ethers.toNumber(txCount), "gasUsed", gasUsed, "timestamp", timestamp)
|
||||
}
|
||||
|
||||
let blockCount = program.endNum - program.startNum
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
import { ethers } from "ethers";
|
||||
import program from "commander";
|
||||
|
||||
// Global Options:
|
||||
program.option("--rpc <rpc>", "Rpc");
|
||||
// GetTxCount Options:
|
||||
program.option("--startNum <startNum>", "start num")
|
||||
program.option("--endNum <endNum>", "end num")
|
||||
program.option("--miner <miner>", "miner", "")
|
||||
// GetVersion Options:
|
||||
program.option("--num <Num>", "validator num", 21)
|
||||
// GetTopAddr Options:
|
||||
program.option("--topNum <Num>", "top num of address to be displayed", 20)
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.rpc)
|
||||
|
||||
function printUsage() {
|
||||
console.log("Usage:");
|
||||
console.log(" node getchainstatus.js --help");
|
||||
console.log(" node getchainstatus.js [subcommand] [options]");
|
||||
console.log("\nSubcommands:");
|
||||
console.log(" GetTxCount: find the block with max tx size of a range");
|
||||
console.log(" GetVersion: dump validators' binary version, based on Header.Extra");
|
||||
console.log(" GetTopAddr: get hottest $topNum target address within a block range");
|
||||
console.log("\nOptions:");
|
||||
console.log(" --rpc specify the url of RPC endpoint");
|
||||
console.log(" --startNum the start block number, for command GetTxCount");
|
||||
console.log(" --endNum the end block number, for command GetTxCount");
|
||||
console.log(" --miner the miner address, for command GetTxCount");
|
||||
console.log(" --num the number of blocks to be checked, for command GetVersion");
|
||||
console.log(" --topNum the topNum of blocks to be checked, for command GetVersion");
|
||||
console.log("\nExample:");
|
||||
// mainnet https://bsc-mainnet.nodereal.io/v1/454e504917db4f82b756bd0cf6317dce
|
||||
console.log(" node getchainstatus.js GetTxCount --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000005")
|
||||
console.log(" node getchainstatus.js GetVersion --rpc https://bsc-testnet-dataseed.bnbchain.org --num 21")
|
||||
console.log(" node getchainstatus.js GetTopAddr --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000010 --topNum 10")
|
||||
}
|
||||
|
||||
// 1.cmd: "GetTxCount", usage:
|
||||
// node getchainstatus.js GetTxCount --rpc https://bsc-testnet-dataseed.bnbchain.org \
|
||||
// --startNum 40000001 --endNum 40000005 \
|
||||
// --miner(optional): specified: find the max txCounter from the specified validator,
|
||||
// not specified: find the max txCounter from all validators
|
||||
async function getTxCount() {
|
||||
let txCount = 0;
|
||||
let num = 0;
|
||||
console.log("Find the max txs count between", program.startNum, "and", program.endNum);
|
||||
for (let i = program.startNum; i < program.endNum; i++) {
|
||||
if (program.miner !== "") {
|
||||
let blockData = await provider.getBlock(Number(i))
|
||||
if (program.miner !== blockData.miner) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
let x = await provider.send("eth_getBlockTransactionCountByNumber", [
|
||||
ethers.toQuantity(i)]);
|
||||
let a = ethers.toNumber(x)
|
||||
if (a > txCount) {
|
||||
num = i;
|
||||
txCount = a;
|
||||
}
|
||||
}
|
||||
console.log("BlockNum = ", num, "TxCount =", txCount);
|
||||
}
|
||||
|
||||
// 2.cmd: "GetVersion", usage:
|
||||
// node getchainstatus.js GetVersion \
|
||||
// --rpc https://bsc-testnet-dataseed.bnbchain.org \
|
||||
// --num(optional): defualt 21, the number of blocks that will be checked
|
||||
async function getBinaryVersion() {
|
||||
const blockNum = await provider.getBlockNumber();
|
||||
console.log(blockNum);
|
||||
for (let i = 0; i < program.num; i++) {
|
||||
let blockData = await provider.getBlock(blockNum - i);
|
||||
// 1.get Geth client version
|
||||
let major = ethers.toNumber(ethers.dataSlice(blockData.extraData, 2, 3))
|
||||
let minor = ethers.toNumber(ethers.dataSlice(blockData.extraData, 3, 4))
|
||||
let patch = ethers.toNumber(ethers.dataSlice(blockData.extraData, 4, 5))
|
||||
|
||||
// 2.get minimum txGasPrice based on the last non-zero-gasprice transaction
|
||||
let lastGasPrice = 0
|
||||
for (let txIndex = blockData.transactions.length - 1; txIndex >= 0; txIndex--) {
|
||||
let txHash = blockData.transactions[txIndex]
|
||||
let txData = await provider.getTransaction(txHash);
|
||||
if (txData.gasPrice == 0) {
|
||||
continue
|
||||
}
|
||||
lastGasPrice = txData.gasPrice
|
||||
break
|
||||
}
|
||||
console.log(blockData.miner, "version =", major + "." + minor + "." + patch, " MinGasPrice = " + lastGasPrice)
|
||||
}
|
||||
};
|
||||
|
||||
// 3.cmd: "GetTopAddr", usage:
|
||||
// node getchainstatus.js GetTopAddr \
|
||||
// --rpc https://bsc-testnet-dataseed.bnbchain.org \
|
||||
// --startNum 40000001 --endNum 40000005 \
|
||||
// --topNum(optional): the top num of address to be displayed, default 20
|
||||
function getTopKElements(map, k) {
|
||||
let entries = Array.from(map.entries());
|
||||
entries.sort((a, b) => b[1] - a[1]);
|
||||
return entries.slice(0, k);
|
||||
}
|
||||
|
||||
async function getTopAddr() {
|
||||
let countMap = new Map();
|
||||
let totalTxs = 0
|
||||
console.log("Find the top target address, between", program.startNum, "and", program.endNum);
|
||||
for (let i = program.startNum; i <= program.endNum; i++) {
|
||||
let blockData = await provider.getBlock(Number(i), true)
|
||||
totalTxs += blockData.transactions.length
|
||||
for (let txIndex = blockData.transactions.length - 1; txIndex >= 0; txIndex--) {
|
||||
let txData = await blockData.getTransaction(txIndex)
|
||||
if (txData.to == null) {
|
||||
console.log("Contract creation,txHash:", txData.hash)
|
||||
continue
|
||||
}
|
||||
let toAddr = txData.to;
|
||||
if (countMap.has(toAddr)) {
|
||||
countMap.set(toAddr, countMap.get(toAddr) + 1);
|
||||
} else {
|
||||
countMap.set(toAddr, 1);
|
||||
}
|
||||
}
|
||||
console.log("progress:", (program.endNum-i), "blocks left", "totalTxs", totalTxs)
|
||||
}
|
||||
let tops = getTopKElements(countMap, program.topNum)
|
||||
tops.forEach((value, key) => {
|
||||
// value: [ '0x40661F989826CC641Ce1601526Bb16a4221412c8', 71 ]
|
||||
console.log(key+":", value[0], " ", value[1], " ", ((value[1]*100)/totalTxs).toFixed(2)+"%");
|
||||
});
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
if (process.argv.length <= 2) {
|
||||
console.error('invalid process.argv.length', process.argv.length);
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
const cmd = process.argv[2]
|
||||
if (cmd === "--help") {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
if (cmd === "GetTxCount") {
|
||||
await getTxCount()
|
||||
} else if (cmd === "GetVersion") {
|
||||
await getBinaryVersion()
|
||||
} else if (cmd === "GetTopAddr") {
|
||||
await getTopAddr()
|
||||
} else {
|
||||
console.log("unsupported cmd", cmd);
|
||||
printUsage()
|
||||
}
|
||||
}
|
||||
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
41
cmd/jsutils/gettxcount.js
Normal file
41
cmd/jsutils/gettxcount.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { ethers } from "ethers";
|
||||
import program from "commander";
|
||||
|
||||
program.option("--rpc <rpc>", "Rpc");
|
||||
program.option("--startNum <startNum>", "start num")
|
||||
program.option("--endNum <endNum>", "end num")
|
||||
// --miner:
|
||||
// specified: find the max txCounter from the specified validator
|
||||
// not specified: find the max txCounter from all validators
|
||||
program.option("--miner <miner>", "miner", "")
|
||||
program.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.rpc)
|
||||
|
||||
const main = async () => {
|
||||
let txCount = 0;
|
||||
let num = 0;
|
||||
console.log("Find the max txs count between", program.startNum, "and", program.endNum);
|
||||
for (let i = program.startNum; i < program.endNum; i++) {
|
||||
if (program.miner !== "") {
|
||||
let blockData = await provider.getBlock(Number(i))
|
||||
if (program.miner !== blockData.miner) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
let x = await provider.send("eth_getBlockTransactionCountByNumber", [
|
||||
ethers.toQuantity(i)]);
|
||||
let a = ethers.toNumber(x)
|
||||
if (a > txCount) {
|
||||
num = i;
|
||||
txCount = a;
|
||||
}
|
||||
}
|
||||
console.log("BlockNum = ", num, "TxCount =", txCount);
|
||||
};
|
||||
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
38
cmd/jsutils/getvalidatorversion.js
Normal file
38
cmd/jsutils/getvalidatorversion.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { ethers } from "ethers";
|
||||
import program from "commander";
|
||||
|
||||
program.option("--Rpc <Rpc>", "Rpc");
|
||||
program.option("--Num <Num>", "validator num", 21)
|
||||
program.parse(process.argv);
|
||||
|
||||
const provider = new ethers.JsonRpcProvider(program.Rpc);
|
||||
|
||||
const main = async () => {
|
||||
const blockNum = await provider.getBlockNumber();
|
||||
console.log(blockNum);
|
||||
for (let i = 0; i < program.Num; i++) {
|
||||
let blockData = await provider.getBlock(blockNum - i);
|
||||
// 1.get Geth client version
|
||||
let major = ethers.toNumber(ethers.dataSlice(blockData.extraData, 2, 3))
|
||||
let minor = ethers.toNumber(ethers.dataSlice(blockData.extraData, 3, 4))
|
||||
let patch = ethers.toNumber(ethers.dataSlice(blockData.extraData, 4, 5))
|
||||
|
||||
// 2.get minimum txGasPrice based on the last non-zero-gasprice transaction
|
||||
let lastGasPrice = 0
|
||||
for (let txIndex = blockData.transactions.length - 1; txIndex >= 0; txIndex--) {
|
||||
let txHash = blockData.transactions[txIndex]
|
||||
let txData = await provider.getTransaction(txHash);
|
||||
if (txData.gasPrice == 0) {
|
||||
continue
|
||||
}
|
||||
lastGasPrice = txData.gasPrice
|
||||
break
|
||||
}
|
||||
console.log(blockData.miner, "version =", major + "." + minor + "." + patch, " MinGasPrice = " + lastGasPrice)
|
||||
}
|
||||
};
|
||||
main().then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -35,11 +35,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/internal/version"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/beacon/fakebeacon"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
@@ -308,19 +305,9 @@ var (
|
||||
Usage: "Manually specify the Rialto Genesis Hash, to trigger builtin network logic",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverridePassedForkTime = &cli.Uint64Flag{
|
||||
Name: "override.passedforktime",
|
||||
Usage: "Manually specify the hard fork timestamps which have passed on the mainnet, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverridePascal = &cli.Uint64Flag{
|
||||
Name: "override.pascal",
|
||||
Usage: "Manually specify the Pascal fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverridePrague = &cli.Uint64Flag{
|
||||
Name: "override.prague",
|
||||
Usage: "Manually specify the Prague fork timestamp, overriding the bundled setting",
|
||||
OverrideBohr = &cli.Uint64Flag{
|
||||
Name: "override.bohr",
|
||||
Usage: "Manually specify the Bohr fork timestamp, overriding the bundled setting",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideVerkle = &cli.Uint64Flag{
|
||||
@@ -352,12 +339,6 @@ var (
|
||||
Value: params.BreatheBlockInterval,
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
OverrideFixedTurnLength = &cli.Uint64Flag{
|
||||
Name: "override.fixedturnlength",
|
||||
Usage: "It use fixed or random values for turn length instead of reading from the contract, only for testing purpose",
|
||||
Value: params.FixedTurnLength,
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
SyncModeFlag = &flags.TextMarshalerFlag{
|
||||
Name: "syncmode",
|
||||
Usage: `Blockchain sync mode ("snap" or "full")`,
|
||||
@@ -1154,25 +1135,6 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
||||
Value: params.DefaultExtraReserveForBlobRequests,
|
||||
Category: flags.MiscCategory,
|
||||
}
|
||||
|
||||
// Fake beacon
|
||||
FakeBeaconEnabledFlag = &cli.BoolFlag{
|
||||
Name: "fake-beacon",
|
||||
Usage: "Enable the HTTP-RPC server of fake-beacon",
|
||||
Category: flags.APICategory,
|
||||
}
|
||||
FakeBeaconAddrFlag = &cli.StringFlag{
|
||||
Name: "fake-beacon.addr",
|
||||
Usage: "HTTP-RPC server listening addr of fake-beacon",
|
||||
Value: fakebeacon.DefaultAddr,
|
||||
Category: flags.APICategory,
|
||||
}
|
||||
FakeBeaconPortFlag = &cli.IntFlag{
|
||||
Name: "fake-beacon.port",
|
||||
Usage: "HTTP-RPC server listening port of fake-beacon",
|
||||
Value: fakebeacon.DefaultPort,
|
||||
Category: flags.APICategory,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -2324,67 +2286,6 @@ func EnableNodeInfo(poolConfig *legacypool.Config, nodeInfo *p2p.NodeInfo) Setup
|
||||
}
|
||||
}
|
||||
|
||||
func EnableNodeTrack(ctx *cli.Context, cfg *ethconfig.Config, stack *node.Node) SetupMetricsOption {
|
||||
nodeInfo := stack.Server().NodeInfo()
|
||||
return func() {
|
||||
// register node info into metrics
|
||||
metrics.NewRegisteredLabel("node-stats", nil).Mark(map[string]interface{}{
|
||||
"NodeType": parseNodeType(),
|
||||
"ENR": nodeInfo.ENR,
|
||||
"Mining": ctx.Bool(MiningEnabledFlag.Name),
|
||||
"Etherbase": parseEtherbase(cfg),
|
||||
"MiningFeatures": parseMiningFeatures(ctx, cfg),
|
||||
"DBFeatures": parseDBFeatures(cfg, stack),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func parseEtherbase(cfg *ethconfig.Config) string {
|
||||
if cfg.Miner.Etherbase == (common.Address{}) {
|
||||
return ""
|
||||
}
|
||||
return cfg.Miner.Etherbase.String()
|
||||
}
|
||||
|
||||
func parseNodeType() string {
|
||||
git, _ := version.VCS()
|
||||
version := []string{params.VersionWithMeta}
|
||||
if len(git.Commit) >= 7 {
|
||||
version = append(version, git.Commit[:7])
|
||||
}
|
||||
if git.Date != "" {
|
||||
version = append(version, git.Date)
|
||||
}
|
||||
arch := []string{runtime.GOOS, runtime.GOARCH}
|
||||
infos := []string{"BSC", strings.Join(version, "-"), strings.Join(arch, "-"), runtime.Version()}
|
||||
return strings.Join(infos, "/")
|
||||
}
|
||||
|
||||
func parseDBFeatures(cfg *ethconfig.Config, stack *node.Node) string {
|
||||
var features []string
|
||||
if cfg.StateScheme == rawdb.PathScheme {
|
||||
features = append(features, "PBSS")
|
||||
}
|
||||
if stack.CheckIfMultiDataBase() {
|
||||
features = append(features, "MultiDB")
|
||||
}
|
||||
return strings.Join(features, "|")
|
||||
}
|
||||
|
||||
func parseMiningFeatures(ctx *cli.Context, cfg *ethconfig.Config) string {
|
||||
if !ctx.Bool(MiningEnabledFlag.Name) {
|
||||
return ""
|
||||
}
|
||||
var features []string
|
||||
if cfg.Miner.Mev.Enabled {
|
||||
features = append(features, "MEV")
|
||||
}
|
||||
if cfg.Miner.VoteEnable {
|
||||
features = append(features, "FFVoting")
|
||||
}
|
||||
return strings.Join(features, "|")
|
||||
}
|
||||
|
||||
func SetupMetrics(ctx *cli.Context, options ...SetupMetricsOption) {
|
||||
if metrics.Enabled {
|
||||
log.Info("Enabling metrics collection")
|
||||
|
||||
@@ -2306,19 +2306,6 @@ const validatorSetABI = `
|
||||
],
|
||||
"stateMutability": "view"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getTurnLength",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "getValidators",
|
||||
|
||||
@@ -88,19 +88,6 @@ func (api *API) GetJustifiedNumber(number *rpc.BlockNumber) (uint64, error) {
|
||||
return snap.Attestation.TargetNumber, nil
|
||||
}
|
||||
|
||||
func (api *API) GetTurnLength(number *rpc.BlockNumber) (uint8, error) {
|
||||
header := api.getHeader(number)
|
||||
// Ensure we have an actually valid block and return the validators from its snapshot
|
||||
if header == nil {
|
||||
return 0, errUnknownBlock
|
||||
}
|
||||
snap, err := api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||
if err != nil || snap.TurnLength == 0 {
|
||||
return 0, err
|
||||
}
|
||||
return snap.TurnLength, nil
|
||||
}
|
||||
|
||||
func (api *API) GetFinalizedNumber(number *rpc.BlockNumber) (uint64, error) {
|
||||
header := api.getHeader(number)
|
||||
// Ensure we have an actually valid block and return the validators from its snapshot
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
package parlia
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/big"
|
||||
mrand "math/rand"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
func (p *Parlia) getTurnLength(chain consensus.ChainHeaderReader, header *types.Header) (*uint8, error) {
|
||||
parent := chain.GetHeaderByHash(header.ParentHash)
|
||||
if parent == nil {
|
||||
return nil, errors.New("parent not found")
|
||||
}
|
||||
|
||||
var turnLength uint8
|
||||
if p.chainConfig.IsBohr(parent.Number, parent.Time) {
|
||||
turnLengthFromContract, err := p.getTurnLengthFromContract(parent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if turnLengthFromContract == nil {
|
||||
return nil, errors.New("unexpected error when getTurnLengthFromContract")
|
||||
}
|
||||
turnLength = uint8(turnLengthFromContract.Int64())
|
||||
} else {
|
||||
turnLength = defaultTurnLength
|
||||
}
|
||||
log.Debug("getTurnLength", "turnLength", turnLength)
|
||||
|
||||
return &turnLength, nil
|
||||
}
|
||||
|
||||
func (p *Parlia) getTurnLengthFromContract(header *types.Header) (turnLength *big.Int, err error) {
|
||||
// mock to get turnLength from the contract
|
||||
if params.FixedTurnLength >= 1 && params.FixedTurnLength <= 9 {
|
||||
if params.FixedTurnLength == 2 {
|
||||
return p.getRandTurnLength(header)
|
||||
}
|
||||
return big.NewInt(int64(params.FixedTurnLength)), nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
method := "getTurnLength"
|
||||
toAddress := common.HexToAddress(systemcontracts.ValidatorContract)
|
||||
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
||||
|
||||
data, err := p.validatorSetABI.Pack(method)
|
||||
if err != nil {
|
||||
log.Error("Unable to pack tx for getTurnLength", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
msgData := (hexutil.Bytes)(data)
|
||||
|
||||
blockNr := rpc.BlockNumberOrHashWithHash(header.Hash(), false)
|
||||
result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||
Gas: &gas,
|
||||
To: &toAddress,
|
||||
Data: &msgData,
|
||||
}, &blockNr, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.validatorSetABI.UnpackIntoInterface(&turnLength, method, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return turnLength, nil
|
||||
}
|
||||
|
||||
// getRandTurnLength returns a random valid value, used to test switching turn length
|
||||
func (p *Parlia) getRandTurnLength(header *types.Header) (turnLength *big.Int, err error) {
|
||||
turnLengths := [8]uint8{1, 3, 4, 5, 6, 7, 8, 9}
|
||||
r := mrand.New(mrand.NewSource(int64(header.Time)))
|
||||
lengthIndex := int(r.Int31n(int32(len(turnLengths))))
|
||||
return big.NewInt(int64(turnLengths[lengthIndex])), nil
|
||||
}
|
||||
@@ -54,13 +54,11 @@ const (
|
||||
inMemoryHeaders = 86400 // Number of recent headers to keep in memory for double sign detection,
|
||||
|
||||
checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database
|
||||
defaultEpochLength = uint64(200) // Default number of blocks of checkpoint to update validatorSet from contract
|
||||
defaultTurnLength = uint8(1) // Default consecutive number of blocks a validator receives priority for block production
|
||||
defaultEpochLength = uint64(100) // Default number of blocks of checkpoint to update validatorSet from contract
|
||||
|
||||
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
|
||||
nextForkHashSize = 4 // Fixed number of extra-data suffix bytes reserved for nextForkHash.
|
||||
turnLengthSize = 1 // Fixed number of extra-data suffix bytes reserved for turnLength
|
||||
|
||||
validatorBytesLengthBeforeLuban = common.AddressLength
|
||||
validatorBytesLength = common.AddressLength + types.BLSPublicKeyLength
|
||||
@@ -68,6 +66,7 @@ const (
|
||||
|
||||
wiggleTime = uint64(1) // second, Random delay (per signer) to allow concurrent signers
|
||||
initialBackOffTime = uint64(1) // second
|
||||
processBackOffTime = uint64(1) // second
|
||||
|
||||
systemRewardPercent = 4 // it means 1/2^4 = 1/16 percentage of gas fee incoming will be distributed to system
|
||||
|
||||
@@ -128,10 +127,6 @@ var (
|
||||
// invalid list of validators (i.e. non divisible by 20 bytes).
|
||||
errInvalidSpanValidators = errors.New("invalid validator list on sprint end block")
|
||||
|
||||
// errInvalidTurnLength is returned if a block contains an
|
||||
// invalid length of turn (i.e. no data left after parsing validators).
|
||||
errInvalidTurnLength = errors.New("invalid turnLength")
|
||||
|
||||
// errInvalidMixDigest is returned if a block's mix digest is non-zero.
|
||||
errInvalidMixDigest = errors.New("non-zero mix digest")
|
||||
|
||||
@@ -142,10 +137,6 @@ var (
|
||||
// list of validators different than the one the local node calculated.
|
||||
errMismatchingEpochValidators = errors.New("mismatching validator list on epoch block")
|
||||
|
||||
// errMismatchingEpochTurnLength is returned if a sprint block contains a
|
||||
// turn length different than the one the local node calculated.
|
||||
errMismatchingEpochTurnLength = errors.New("mismatching turn length on epoch block")
|
||||
|
||||
// errInvalidDifficulty is returned if the difficulty of a block is missing.
|
||||
errInvalidDifficulty = errors.New("invalid difficulty")
|
||||
|
||||
@@ -379,7 +370,6 @@ func (p *Parlia) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*typ
|
||||
// On luban fork, we introduce vote attestation into the header's extra field, so extra format is different from before.
|
||||
// Before luban fork: |---Extra Vanity---|---Validators Bytes (or Empty)---|---Extra Seal---|
|
||||
// After luban fork: |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---|
|
||||
// After bohr fork: |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Turn Length (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---|
|
||||
func getValidatorBytesFromHeader(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) []byte {
|
||||
if len(header.Extra) <= extraVanity+extraSeal {
|
||||
return nil
|
||||
@@ -396,15 +386,11 @@ func getValidatorBytesFromHeader(header *types.Header, chainConfig *params.Chain
|
||||
return nil
|
||||
}
|
||||
num := int(header.Extra[extraVanity])
|
||||
start := extraVanity + validatorNumberSize
|
||||
end := start + num*validatorBytesLength
|
||||
extraMinLen := end + extraSeal
|
||||
if chainConfig.IsBohr(header.Number, header.Time) {
|
||||
extraMinLen += turnLengthSize
|
||||
}
|
||||
if num == 0 || len(header.Extra) < extraMinLen {
|
||||
if num == 0 || len(header.Extra) <= extraVanity+extraSeal+num*validatorBytesLength {
|
||||
return nil
|
||||
}
|
||||
start := extraVanity + validatorNumberSize
|
||||
end := start + num*validatorBytesLength
|
||||
return header.Extra[start:end]
|
||||
}
|
||||
|
||||
@@ -423,14 +409,11 @@ func getVoteAttestationFromHeader(header *types.Header, chainConfig *params.Chai
|
||||
attestationBytes = header.Extra[extraVanity : len(header.Extra)-extraSeal]
|
||||
} else {
|
||||
num := int(header.Extra[extraVanity])
|
||||
start := extraVanity + validatorNumberSize + num*validatorBytesLength
|
||||
if chainConfig.IsBohr(header.Number, header.Time) {
|
||||
start += turnLengthSize
|
||||
}
|
||||
end := len(header.Extra) - extraSeal
|
||||
if end <= start {
|
||||
if len(header.Extra) <= extraVanity+extraSeal+validatorNumberSize+num*validatorBytesLength {
|
||||
return nil, nil
|
||||
}
|
||||
start := extraVanity + validatorNumberSize + num*validatorBytesLength
|
||||
end := len(header.Extra) - extraSeal
|
||||
attestationBytes = header.Extra[start:end]
|
||||
}
|
||||
|
||||
@@ -738,28 +721,13 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
|
||||
}
|
||||
}
|
||||
|
||||
// If we're at the genesis, snapshot the initial state. Alternatively if we have
|
||||
// piled up more headers than allowed to be reorged (chain reinit from a freezer),
|
||||
// consider the checkpoint trusted and snapshot it.
|
||||
// An offset `p.config.Epoch - 1` can ensure getting the right validators.
|
||||
if number == 0 || ((number+1)%p.config.Epoch == 0 && (len(headers) > int(params.FullImmutabilityThreshold))) {
|
||||
var (
|
||||
checkpoint *types.Header
|
||||
blockHash common.Hash
|
||||
)
|
||||
if number == 0 {
|
||||
checkpoint = chain.GetHeaderByNumber(0)
|
||||
if checkpoint != nil {
|
||||
blockHash = checkpoint.Hash()
|
||||
}
|
||||
} else {
|
||||
checkpoint = chain.GetHeaderByNumber(number + 1 - p.config.Epoch)
|
||||
blockHeader := chain.GetHeaderByNumber(number)
|
||||
if blockHeader != nil {
|
||||
blockHash = blockHeader.Hash()
|
||||
}
|
||||
}
|
||||
if checkpoint != nil && blockHash != (common.Hash{}) {
|
||||
// If we're at the genesis, snapshot the initial state.
|
||||
if number == 0 {
|
||||
checkpoint := chain.GetHeaderByNumber(number)
|
||||
if checkpoint != nil {
|
||||
// get checkpoint data
|
||||
hash := checkpoint.Hash()
|
||||
|
||||
// get validators from headers
|
||||
validators, voteAddrs, err := parseValidators(checkpoint, p.chainConfig, p.config)
|
||||
if err != nil {
|
||||
@@ -767,27 +735,11 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
|
||||
}
|
||||
|
||||
// new snapshot
|
||||
snap = newSnapshot(p.config, p.signatures, number, blockHash, validators, voteAddrs, p.ethAPI)
|
||||
|
||||
// get turnLength from headers and use that for new turnLength
|
||||
turnLength, err := parseTurnLength(checkpoint, p.chainConfig, p.config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if turnLength != nil {
|
||||
snap.TurnLength = *turnLength
|
||||
}
|
||||
|
||||
// snap.Recents is currently empty, which affects the following:
|
||||
// a. The function SignRecently - This is acceptable since an empty snap.Recents results in a more lenient check.
|
||||
// b. The function blockTimeVerifyForRamanujanFork - This is also acceptable as it won't be invoked during `snap.apply`.
|
||||
// c. This may cause a mismatch in the slash systemtx, but the transaction list is not verified during `snap.apply`.
|
||||
|
||||
// snap.Attestation is nil, but Snapshot.updateAttestation will handle it correctly.
|
||||
snap = newSnapshot(p.config, p.signatures, number, hash, validators, voteAddrs, p.ethAPI)
|
||||
if err := snap.store(p.db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", blockHash)
|
||||
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -944,24 +896,6 @@ func (p *Parlia) prepareValidators(header *types.Header) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parlia) prepareTurnLength(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||
if header.Number.Uint64()%p.config.Epoch != 0 ||
|
||||
!p.chainConfig.IsBohr(header.Number, header.Time) {
|
||||
return nil
|
||||
}
|
||||
|
||||
turnLength, err := p.getTurnLength(chain, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if turnLength != nil {
|
||||
header.Extra = append(header.Extra, *turnLength)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||
if !p.chainConfig.IsLuban(header.Number) || header.Number.Uint64() < 2 {
|
||||
return nil
|
||||
@@ -1093,9 +1027,6 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header
|
||||
return err
|
||||
}
|
||||
|
||||
if err := p.prepareTurnLength(chain, header); err != nil {
|
||||
return err
|
||||
}
|
||||
// add extra seal space
|
||||
header.Extra = append(header.Extra, make([]byte, extraSeal)...)
|
||||
|
||||
@@ -1146,30 +1077,6 @@ func (p *Parlia) verifyValidators(header *types.Header) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parlia) verifyTurnLength(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||
if header.Number.Uint64()%p.config.Epoch != 0 ||
|
||||
!p.chainConfig.IsBohr(header.Number, header.Time) {
|
||||
return nil
|
||||
}
|
||||
|
||||
turnLengthFromHeader, err := parseTurnLength(header, p.chainConfig, p.config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if turnLengthFromHeader != nil {
|
||||
turnLength, err := p.getTurnLength(chain, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if turnLength != nil && *turnLength == *turnLengthFromHeader {
|
||||
log.Debug("verifyTurnLength", "turnLength", *turnLength)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errMismatchingEpochTurnLength
|
||||
}
|
||||
|
||||
func (p *Parlia) distributeFinalityReward(chain consensus.ChainHeaderReader, state *state.StateDB, header *types.Header,
|
||||
cx core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction,
|
||||
usedGas *uint64, mining bool) error {
|
||||
@@ -1264,10 +1171,6 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
|
||||
return err
|
||||
}
|
||||
|
||||
if err := p.verifyTurnLength(chain, header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cx := chainContext{Chain: chain, parlia: p}
|
||||
|
||||
parent := chain.GetHeaderByHash(header.ParentHash)
|
||||
@@ -1294,7 +1197,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
|
||||
}
|
||||
}
|
||||
if header.Difficulty.Cmp(diffInTurn) != 0 {
|
||||
spoiledVal := snap.inturnValidator()
|
||||
spoiledVal := snap.supposeValidator()
|
||||
signedRecently := false
|
||||
if p.chainConfig.IsPlato(header.Number) {
|
||||
signedRecently = snap.SignRecently(spoiledVal)
|
||||
@@ -1385,7 +1288,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
spoiledVal := snap.inturnValidator()
|
||||
spoiledVal := snap.supposeValidator()
|
||||
signedRecently := false
|
||||
if p.chainConfig.IsPlato(header.Number) {
|
||||
signedRecently = snap.SignRecently(spoiledVal)
|
||||
@@ -1538,13 +1441,10 @@ func (p *Parlia) Delay(chain consensus.ChainReader, header *types.Header, leftOv
|
||||
delay = delay - *leftOver
|
||||
}
|
||||
|
||||
// The blocking time should be no more than half of period when snap.TurnLength == 1
|
||||
timeForMining := time.Duration(p.config.Period) * time.Second / 2
|
||||
if !snap.lastBlockInOneTurn(header.Number.Uint64()) {
|
||||
timeForMining = time.Duration(p.config.Period) * time.Second * 2 / 3
|
||||
}
|
||||
if delay > timeForMining {
|
||||
delay = timeForMining
|
||||
// The blocking time should be no more than half of period
|
||||
half := time.Duration(p.config.Period) * time.Second / 2
|
||||
if delay > half {
|
||||
delay = half
|
||||
}
|
||||
return &delay
|
||||
}
|
||||
@@ -1615,15 +1515,12 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res
|
||||
copy(header.Extra[len(header.Extra)-extraSeal:], sig)
|
||||
|
||||
if p.shouldWaitForCurrentBlockProcess(chain, header, snap) {
|
||||
highestVerifiedHeader := chain.GetHighestVerifiedHeader()
|
||||
// including time for writing and committing blocks
|
||||
waitProcessEstimate := math.Ceil(float64(highestVerifiedHeader.GasUsed) / float64(100_000_000))
|
||||
log.Info("Waiting for received in turn block to process", "waitProcessEstimate(Seconds)", waitProcessEstimate)
|
||||
log.Info("Waiting for received in turn block to process")
|
||||
select {
|
||||
case <-stop:
|
||||
log.Info("Received block process finished, abort block seal")
|
||||
return
|
||||
case <-time.After(time.Duration(waitProcessEstimate) * time.Second):
|
||||
case <-time.After(time.Duration(processBackOffTime) * time.Second):
|
||||
if chain.CurrentHeader().Number.Uint64() >= header.Number.Uint64() {
|
||||
log.Info("Process backoff time exhausted, and current header has updated to abort this seal")
|
||||
return
|
||||
@@ -2039,40 +1936,42 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t
|
||||
// =========================== utility function ==========================
|
||||
func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 {
|
||||
if snap.inturn(val) {
|
||||
log.Debug("backOffTime", "blockNumber", header.Number, "in turn validator", val)
|
||||
return 0
|
||||
} else {
|
||||
delay := initialBackOffTime
|
||||
validators := snap.validators()
|
||||
if p.chainConfig.IsPlanck(header.Number) {
|
||||
counts := snap.countRecents()
|
||||
for addr, seenTimes := range counts {
|
||||
log.Debug("backOffTime", "blockNumber", header.Number, "validator", addr, "seenTimes", seenTimes)
|
||||
// reverse the key/value of snap.Recents to get recentsMap
|
||||
recentsMap := make(map[common.Address]uint64, len(snap.Recents))
|
||||
bound := uint64(0)
|
||||
if n, limit := header.Number.Uint64(), uint64(len(validators)/2+1); n > limit {
|
||||
bound = n - limit
|
||||
}
|
||||
for seen, recent := range snap.Recents {
|
||||
if seen <= bound {
|
||||
continue
|
||||
}
|
||||
recentsMap[recent] = seen
|
||||
}
|
||||
|
||||
// The backOffTime does not matter when a validator has signed recently.
|
||||
if snap.signRecentlyByCounts(val, counts) {
|
||||
if _, ok := recentsMap[val]; ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
inTurnAddr := snap.inturnValidator()
|
||||
if snap.signRecentlyByCounts(inTurnAddr, counts) {
|
||||
inTurnAddr := validators[(snap.Number+1)%uint64(len(validators))]
|
||||
if _, ok := recentsMap[inTurnAddr]; ok {
|
||||
log.Debug("in turn validator has recently signed, skip initialBackOffTime",
|
||||
"inTurnAddr", inTurnAddr)
|
||||
delay = 0
|
||||
}
|
||||
|
||||
// Exclude the recently signed validators and the in turn validator
|
||||
// Exclude the recently signed validators
|
||||
temp := make([]common.Address, 0, len(validators))
|
||||
for _, addr := range validators {
|
||||
if snap.signRecentlyByCounts(addr, counts) {
|
||||
if _, ok := recentsMap[addr]; ok {
|
||||
continue
|
||||
}
|
||||
if p.chainConfig.IsBohr(header.Number, header.Time) {
|
||||
if addr == inTurnAddr {
|
||||
continue
|
||||
}
|
||||
}
|
||||
temp = append(temp, addr)
|
||||
}
|
||||
validators = temp
|
||||
@@ -2090,11 +1989,7 @@ func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Ad
|
||||
return 0
|
||||
}
|
||||
|
||||
randSeed := snap.Number
|
||||
if p.chainConfig.IsBohr(header.Number, header.Time) {
|
||||
randSeed = header.Number.Uint64() / uint64(snap.TurnLength)
|
||||
}
|
||||
s := rand.NewSource(int64(randSeed))
|
||||
s := rand.NewSource(int64(snap.Number))
|
||||
r := rand.New(s)
|
||||
n := len(validators)
|
||||
backOffSteps := make([]uint64, 0, n)
|
||||
|
||||
@@ -22,44 +22,22 @@ func TestImpactOfValidatorOutOfService(t *testing.T) {
|
||||
testCases := []struct {
|
||||
totalValidators int
|
||||
downValidators int
|
||||
turnLength int
|
||||
}{
|
||||
{3, 1, 1},
|
||||
{5, 2, 1},
|
||||
{10, 1, 2},
|
||||
{10, 4, 2},
|
||||
{21, 1, 3},
|
||||
{21, 3, 3},
|
||||
{21, 5, 4},
|
||||
{21, 10, 5},
|
||||
{3, 1},
|
||||
{5, 2},
|
||||
{10, 1},
|
||||
{10, 4},
|
||||
{21, 1},
|
||||
{21, 3},
|
||||
{21, 5},
|
||||
{21, 10},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
simulateValidatorOutOfService(tc.totalValidators, tc.downValidators, tc.turnLength)
|
||||
simulateValidatorOutOfService(tc.totalValidators, tc.downValidators)
|
||||
}
|
||||
}
|
||||
|
||||
// refer Snapshot.SignRecently
|
||||
func signRecently(idx int, recents map[uint64]int, turnLength int) bool {
|
||||
recentSignTimes := 0
|
||||
for _, signIdx := range recents {
|
||||
if signIdx == idx {
|
||||
recentSignTimes += 1
|
||||
}
|
||||
}
|
||||
return recentSignTimes >= turnLength
|
||||
}
|
||||
|
||||
// refer Snapshot.minerHistoryCheckLen
|
||||
func minerHistoryCheckLen(totalValidators int, turnLength int) uint64 {
|
||||
return uint64(totalValidators/2+1)*uint64(turnLength) - 1
|
||||
}
|
||||
|
||||
// refer Snapshot.inturnValidator
|
||||
func inturnValidator(totalValidators int, turnLength int, height int) int {
|
||||
return height / turnLength % totalValidators
|
||||
}
|
||||
|
||||
func simulateValidatorOutOfService(totalValidators int, downValidators int, turnLength int) {
|
||||
func simulateValidatorOutOfService(totalValidators int, downValidators int) {
|
||||
downBlocks := 10000
|
||||
recoverBlocks := 10000
|
||||
recents := make(map[uint64]int)
|
||||
@@ -77,7 +55,12 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int, turn
|
||||
delete(validators, down[i])
|
||||
}
|
||||
isRecentSign := func(idx int) bool {
|
||||
return signRecently(idx, recents, turnLength)
|
||||
for _, signIdx := range recents {
|
||||
if signIdx == idx {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
isInService := func(idx int) bool {
|
||||
return validators[idx]
|
||||
@@ -85,10 +68,10 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int, turn
|
||||
|
||||
downDelay := uint64(0)
|
||||
for h := 1; h <= downBlocks; h++ {
|
||||
if limit := minerHistoryCheckLen(totalValidators, turnLength) + 1; uint64(h) >= limit {
|
||||
if limit := uint64(totalValidators/2 + 1); uint64(h) >= limit {
|
||||
delete(recents, uint64(h)-limit)
|
||||
}
|
||||
proposer := inturnValidator(totalValidators, turnLength, h)
|
||||
proposer := h % totalValidators
|
||||
if !isInService(proposer) || isRecentSign(proposer) {
|
||||
candidates := make(map[int]bool, totalValidators/2)
|
||||
for v := range validators {
|
||||
@@ -116,10 +99,10 @@ func simulateValidatorOutOfService(totalValidators int, downValidators int, turn
|
||||
recoverDelay := uint64(0)
|
||||
lastseen := downBlocks
|
||||
for h := downBlocks + 1; h <= downBlocks+recoverBlocks; h++ {
|
||||
if limit := minerHistoryCheckLen(totalValidators, turnLength) + 1; uint64(h) >= limit {
|
||||
if limit := uint64(totalValidators/2 + 1); uint64(h) >= limit {
|
||||
delete(recents, uint64(h)-limit)
|
||||
}
|
||||
proposer := inturnValidator(totalValidators, turnLength, h)
|
||||
proposer := h % totalValidators
|
||||
if !isInService(proposer) || isRecentSign(proposer) {
|
||||
lastseen = h
|
||||
candidates := make(map[int]bool, totalValidators/2)
|
||||
|
||||
@@ -44,7 +44,6 @@ type Snapshot struct {
|
||||
|
||||
Number uint64 `json:"number"` // Block number where the snapshot was created
|
||||
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
|
||||
TurnLength uint8 `json:"turn_length"` // Length of `turn`, meaning the consecutive number of blocks a validator receives priority for block production
|
||||
Validators map[common.Address]*ValidatorInfo `json:"validators"` // Set of authorized validators at this moment
|
||||
Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections
|
||||
RecentForkHashes map[uint64]string `json:"recent_fork_hashes"` // Set of recent forkHash
|
||||
@@ -74,7 +73,6 @@ func newSnapshot(
|
||||
sigCache: sigCache,
|
||||
Number: number,
|
||||
Hash: hash,
|
||||
TurnLength: defaultTurnLength,
|
||||
Recents: make(map[uint64]common.Address),
|
||||
RecentForkHashes: make(map[uint64]string),
|
||||
Validators: make(map[common.Address]*ValidatorInfo),
|
||||
@@ -117,10 +115,6 @@ func loadSnapshot(config *params.ParliaConfig, sigCache *lru.ARCCache, db ethdb.
|
||||
if err := json.Unmarshal(blob, snap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if snap.TurnLength == 0 { // no TurnLength field in old snapshots
|
||||
snap.TurnLength = defaultTurnLength
|
||||
}
|
||||
|
||||
snap.config = config
|
||||
snap.sigCache = sigCache
|
||||
snap.ethAPI = ethAPI
|
||||
@@ -145,7 +139,6 @@ func (s *Snapshot) copy() *Snapshot {
|
||||
sigCache: s.sigCache,
|
||||
Number: s.Number,
|
||||
Hash: s.Hash,
|
||||
TurnLength: s.TurnLength,
|
||||
Validators: make(map[common.Address]*ValidatorInfo),
|
||||
Recents: make(map[uint64]common.Address),
|
||||
RecentForkHashes: make(map[uint64]string),
|
||||
@@ -218,43 +211,15 @@ func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.C
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Snapshot) versionHistoryCheckLen() uint64 {
|
||||
return uint64(len(s.Validators)) * uint64(s.TurnLength)
|
||||
}
|
||||
|
||||
func (s *Snapshot) minerHistoryCheckLen() uint64 {
|
||||
return (uint64(len(s.Validators))/2+1)*uint64(s.TurnLength) - 1
|
||||
}
|
||||
|
||||
func (s *Snapshot) countRecents() map[common.Address]uint8 {
|
||||
leftHistoryBound := uint64(0) // the bound is excluded
|
||||
checkHistoryLength := s.minerHistoryCheckLen()
|
||||
if s.Number > checkHistoryLength {
|
||||
leftHistoryBound = s.Number - checkHistoryLength
|
||||
}
|
||||
counts := make(map[common.Address]uint8, len(s.Validators))
|
||||
for seen, recent := range s.Recents {
|
||||
if seen <= leftHistoryBound || recent == (common.Address{}) /*when seen == `epochKey`*/ {
|
||||
continue
|
||||
}
|
||||
counts[recent] += 1
|
||||
}
|
||||
return counts
|
||||
}
|
||||
|
||||
func (s *Snapshot) signRecentlyByCounts(validator common.Address, counts map[common.Address]uint8) bool {
|
||||
if seenTimes, ok := counts[validator]; ok && seenTimes >= s.TurnLength {
|
||||
if seenTimes > s.TurnLength {
|
||||
log.Warn("produce more blocks than expected!", "validator", validator, "seenTimes", seenTimes)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Snapshot) SignRecently(validator common.Address) bool {
|
||||
return s.signRecentlyByCounts(validator, s.countRecents())
|
||||
for seen, recent := range s.Recents {
|
||||
if recent == validator {
|
||||
if limit := uint64(len(s.Validators)/2 + 1); s.Number+1 < limit || seen > s.Number+1-limit {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainConfig *params.ChainConfig) (*Snapshot, error) {
|
||||
@@ -283,10 +248,10 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
||||
for _, header := range headers {
|
||||
number := header.Number.Uint64()
|
||||
// Delete the oldest validator from the recent list to allow it signing again
|
||||
if limit := snap.minerHistoryCheckLen() + 1; number >= limit {
|
||||
if limit := uint64(len(snap.Validators)/2 + 1); number >= limit {
|
||||
delete(snap.Recents, number-limit)
|
||||
}
|
||||
if limit := snap.versionHistoryCheckLen(); number >= limit {
|
||||
if limit := uint64(len(snap.Validators)); number >= limit {
|
||||
delete(snap.RecentForkHashes, number-limit)
|
||||
}
|
||||
// Resolve the authorization key and check against signers
|
||||
@@ -297,22 +262,16 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
||||
if _, ok := snap.Validators[validator]; !ok {
|
||||
return nil, errUnauthorizedValidator(validator.String())
|
||||
}
|
||||
if chainConfig.IsBohr(header.Number, header.Time) {
|
||||
if snap.SignRecently(validator) {
|
||||
for _, recent := range snap.Recents {
|
||||
if recent == validator {
|
||||
return nil, errRecentlySigned
|
||||
}
|
||||
} else {
|
||||
for _, recent := range snap.Recents {
|
||||
if recent == validator {
|
||||
return nil, errRecentlySigned
|
||||
}
|
||||
}
|
||||
}
|
||||
snap.Recents[number] = validator
|
||||
snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity])
|
||||
snap.updateAttestation(header, chainConfig, s.config)
|
||||
// change validator set
|
||||
if number > 0 && number%s.config.Epoch == snap.minerHistoryCheckLen() {
|
||||
if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) {
|
||||
epochKey := math.MaxUint64 - header.Number.Uint64()/s.config.Epoch // impossible used as a block number
|
||||
if chainConfig.IsBohr(header.Number, header.Time) {
|
||||
// after switching the validator set, snap.Validators may become larger,
|
||||
@@ -322,22 +281,11 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
||||
}
|
||||
}
|
||||
|
||||
checkpointHeader := FindAncientHeader(header, snap.minerHistoryCheckLen(), chain, parents)
|
||||
checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents)
|
||||
if checkpointHeader == nil {
|
||||
return nil, consensus.ErrUnknownAncestor
|
||||
}
|
||||
|
||||
oldVersionsLen := snap.versionHistoryCheckLen()
|
||||
// get turnLength from headers and use that for new turnLength
|
||||
turnLength, err := parseTurnLength(checkpointHeader, chainConfig, s.config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if turnLength != nil {
|
||||
snap.TurnLength = *turnLength
|
||||
log.Debug("validator set switch", "turnLength", *turnLength)
|
||||
}
|
||||
|
||||
// get validators from headers and use that for new validator set
|
||||
newValArr, voteAddrs, err := parseValidators(checkpointHeader, chainConfig, s.config)
|
||||
if err != nil {
|
||||
@@ -367,6 +315,13 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
||||
}
|
||||
}
|
||||
}
|
||||
oldLimit := len(snap.Validators)
|
||||
newLimit := len(newVals)
|
||||
if newLimit < oldLimit {
|
||||
for i := 0; i < oldLimit-newLimit; i++ {
|
||||
delete(snap.RecentForkHashes, number-uint64(newLimit)-uint64(i))
|
||||
}
|
||||
}
|
||||
snap.Validators = newVals
|
||||
if chainConfig.IsLuban(header.Number) {
|
||||
validators := snap.validators()
|
||||
@@ -374,9 +329,6 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
||||
snap.Validators[val].Index = idx + 1 // offset by 1
|
||||
}
|
||||
}
|
||||
for i := snap.versionHistoryCheckLen(); i < oldVersionsLen; i++ {
|
||||
delete(snap.RecentForkHashes, number-i)
|
||||
}
|
||||
}
|
||||
}
|
||||
snap.Number += uint64(len(headers))
|
||||
@@ -394,20 +346,17 @@ func (s *Snapshot) validators() []common.Address {
|
||||
return validators
|
||||
}
|
||||
|
||||
// lastBlockInOneTurn returns if the block at height `blockNumber` is the last block in current turn.
|
||||
func (s *Snapshot) lastBlockInOneTurn(blockNumber uint64) bool {
|
||||
return (blockNumber+1)%uint64(s.TurnLength) == 0
|
||||
}
|
||||
|
||||
// inturn returns if a validator at a given block height is in-turn or not.
|
||||
func (s *Snapshot) inturn(validator common.Address) bool {
|
||||
return s.inturnValidator() == validator
|
||||
validators := s.validators()
|
||||
offset := (s.Number + 1) % uint64(len(validators))
|
||||
return validators[offset] == validator
|
||||
}
|
||||
|
||||
// inturnValidator returns the validator for the following block height.
|
||||
// inturnValidator returns the validator at a given block height.
|
||||
func (s *Snapshot) inturnValidator() common.Address {
|
||||
validators := s.validators()
|
||||
offset := (s.Number + 1) / uint64(s.TurnLength) % uint64(len(validators))
|
||||
offset := (s.Number + 1) % uint64(len(validators))
|
||||
return validators[offset]
|
||||
}
|
||||
|
||||
@@ -445,6 +394,12 @@ func (s *Snapshot) indexOfVal(validator common.Address) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
func (s *Snapshot) supposeValidator() common.Address {
|
||||
validators := s.validators()
|
||||
index := (s.Number + 1) % uint64(len(validators))
|
||||
return validators[index]
|
||||
}
|
||||
|
||||
func parseValidators(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) ([]common.Address, []types.BLSPublicKey, error) {
|
||||
validatorsBytes := getValidatorBytesFromHeader(header, chainConfig, parliaConfig)
|
||||
if len(validatorsBytes) == 0 {
|
||||
@@ -470,24 +425,6 @@ func parseValidators(header *types.Header, chainConfig *params.ChainConfig, parl
|
||||
return cnsAddrs, voteAddrs, nil
|
||||
}
|
||||
|
||||
func parseTurnLength(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) (*uint8, error) {
|
||||
if header.Number.Uint64()%parliaConfig.Epoch != 0 ||
|
||||
!chainConfig.IsBohr(header.Number, header.Time) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if len(header.Extra) <= extraVanity+extraSeal {
|
||||
return nil, errInvalidSpanValidators
|
||||
}
|
||||
num := int(header.Extra[extraVanity])
|
||||
pos := extraVanity + validatorNumberSize + num*validatorBytesLength
|
||||
if len(header.Extra) <= pos {
|
||||
return nil, errInvalidTurnLength
|
||||
}
|
||||
turnLength := header.Extra[pos]
|
||||
return &turnLength, nil
|
||||
}
|
||||
|
||||
func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHeaderReader, candidateParents []*types.Header) *types.Header {
|
||||
ancient := header
|
||||
for i := uint64(1); i <= ite; i++ {
|
||||
|
||||
@@ -66,6 +66,31 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin
|
||||
return validator
|
||||
}
|
||||
|
||||
// ValidateListsInBody validates that UncleHash, WithdrawalsHash, and WithdrawalsHash correspond to the lists in the block body, respectively.
|
||||
func ValidateListsInBody(block *types.Block) error {
|
||||
header := block.Header()
|
||||
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
|
||||
return fmt.Errorf("uncle root hash mismatch (header value %x, calculated %x)", header.UncleHash, hash)
|
||||
}
|
||||
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
|
||||
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
|
||||
}
|
||||
// Withdrawals are present after the Shanghai fork.
|
||||
if header.WithdrawalsHash != nil {
|
||||
// Withdrawals list must be present in body after Shanghai.
|
||||
if block.Withdrawals() == nil {
|
||||
return errors.New("missing withdrawals in block body")
|
||||
}
|
||||
if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash {
|
||||
return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash)
|
||||
}
|
||||
} else if block.Withdrawals() != nil { // Withdrawals turn into empty from nil when BlockBody has Sidecars
|
||||
// Withdrawals are not allowed prior to shanghai fork
|
||||
return errors.New("withdrawals present in block body")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateBody validates the given block's uncles and verifies the block
|
||||
// header's transaction and uncle roots. The headers are assumed to be already
|
||||
// validated at this point.
|
||||
@@ -83,31 +108,12 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||
if err := v.engine.VerifyUncles(v.bc, block); err != nil {
|
||||
return err
|
||||
}
|
||||
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
|
||||
return fmt.Errorf("uncle root hash mismatch (header value %x, calculated %x)", header.UncleHash, hash)
|
||||
}
|
||||
|
||||
validateFuns := []func() error{
|
||||
func() error {
|
||||
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
|
||||
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
|
||||
}
|
||||
return nil
|
||||
return ValidateListsInBody(block)
|
||||
},
|
||||
func() error {
|
||||
// Withdrawals are present after the Shanghai fork.
|
||||
if header.WithdrawalsHash != nil {
|
||||
// Withdrawals list must be present in body after Shanghai.
|
||||
if block.Withdrawals() == nil {
|
||||
return errors.New("missing withdrawals in block body")
|
||||
}
|
||||
if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash {
|
||||
return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash)
|
||||
}
|
||||
} else if block.Withdrawals() != nil { // Withdrawals turn into empty from nil when BlockBody has Sidecars
|
||||
// Withdrawals are not allowed prior to shanghai fork
|
||||
return errors.New("withdrawals present in block body")
|
||||
}
|
||||
// Blob transactions may be present after the Cancun fork.
|
||||
var blobs int
|
||||
for i, tx := range block.Transactions() {
|
||||
|
||||
@@ -100,8 +100,6 @@ var (
|
||||
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
||||
blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil)
|
||||
|
||||
blockRecvTimeDiffGauge = metrics.NewRegisteredGauge("chain/block/recvtimediff", nil)
|
||||
|
||||
errStateRootVerificationFailed = errors.New("state root verification failed")
|
||||
errInsertionInterrupted = errors.New("insertion is interrupted")
|
||||
errChainStopped = errors.New("blockchain is stopped")
|
||||
@@ -1395,7 +1393,7 @@ func (bc *BlockChain) Stop() {
|
||||
if !bc.cacheConfig.TrieDirtyDisabled {
|
||||
triedb := bc.triedb
|
||||
var once sync.Once
|
||||
for _, offset := range []uint64{0, 1, bc.TriesInMemory() - 1} {
|
||||
for _, offset := range []uint64{0, 1, TriesInMemory - 1} {
|
||||
if number := bc.CurrentBlock().Number.Uint64(); number > offset {
|
||||
recent := bc.GetBlockByNumber(number - offset)
|
||||
log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
|
||||
@@ -1803,12 +1801,6 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||
if err := blockBatch.Write(); err != nil {
|
||||
log.Crit("Failed to write block into disk", "err", err)
|
||||
}
|
||||
bc.hc.tdCache.Add(block.Hash(), externTd)
|
||||
bc.blockCache.Add(block.Hash(), block)
|
||||
bc.cacheReceipts(block.Hash(), receipts, block)
|
||||
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||
bc.sidecarsCache.Add(block.Hash(), block.Sidecars())
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
@@ -1833,7 +1825,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||
|
||||
// Flush limits are not considered for the first TriesInMemory blocks.
|
||||
current := block.NumberU64()
|
||||
if current <= bc.TriesInMemory() {
|
||||
if current <= TriesInMemory {
|
||||
return nil
|
||||
}
|
||||
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
||||
@@ -1919,18 +1911,18 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||
|
||||
// WriteBlockAndSetHead writes the given block and all associated state to the database,
|
||||
// and applies the block as the new chain head.
|
||||
func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
||||
func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool, mux *event.TypeMux) (status WriteStatus, err error) {
|
||||
if !bc.chainmu.TryLock() {
|
||||
return NonStatTy, errChainStopped
|
||||
}
|
||||
defer bc.chainmu.Unlock()
|
||||
|
||||
return bc.writeBlockAndSetHead(block, receipts, logs, state, emitHeadEvent)
|
||||
return bc.writeBlockAndSetHead(block, receipts, logs, state, emitHeadEvent, mux)
|
||||
}
|
||||
|
||||
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
||||
// This function expects the chain mutex to be held.
|
||||
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
||||
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool, mux *event.TypeMux) (status WriteStatus, err error) {
|
||||
currentBlock := bc.CurrentBlock()
|
||||
reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock, block.Header())
|
||||
if err != nil {
|
||||
@@ -1939,6 +1931,9 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||
if reorg {
|
||||
bc.highestVerifiedBlock.Store(types.CopyHeader(block.Header()))
|
||||
bc.highestVerifiedBlockFeed.Send(HighestVerifiedBlockEvent{Header: block.Header()})
|
||||
if mux != nil {
|
||||
mux.Post(NewSealedBlockEvent{Block: block})
|
||||
}
|
||||
}
|
||||
|
||||
if err := bc.writeBlockWithState(block, receipts, state); err != nil {
|
||||
@@ -2057,9 +2052,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if len(chain) > 0 {
|
||||
blockRecvTimeDiffGauge.Update(time.Now().Unix() - int64(chain[0].Time()))
|
||||
}
|
||||
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
||||
signer := types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time())
|
||||
go SenderCacher.RecoverFromBlocks(signer, chain)
|
||||
@@ -2319,12 +2311,14 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||
// Don't set the head, only insert the block
|
||||
err = bc.writeBlockWithState(block, receipts, statedb)
|
||||
} else {
|
||||
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false)
|
||||
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false, nil)
|
||||
}
|
||||
if err != nil {
|
||||
return it.index, err
|
||||
}
|
||||
|
||||
bc.cacheReceipts(block.Hash(), receipts, block)
|
||||
|
||||
// Update the metrics touched during block commit
|
||||
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
|
||||
storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them
|
||||
|
||||
@@ -27,7 +27,10 @@ type NewTxsEvent struct{ Txs []*types.Transaction }
|
||||
// ReannoTxsEvent is posted when a batch of local pending transactions exceed a specified duration.
|
||||
type ReannoTxsEvent struct{ Txs []*types.Transaction }
|
||||
|
||||
// NewMinedBlockEvent is posted when a block has been imported.
|
||||
// NewSealedBlockEvent is posted when a block has been sealed.
|
||||
type NewSealedBlockEvent struct{ Block *types.Block }
|
||||
|
||||
// NewMinedBlockEvent is posted when a block has been mined.
|
||||
type NewMinedBlockEvent struct{ Block *types.Block }
|
||||
|
||||
// RemovedLogsEvent is posted when a reorg happens
|
||||
|
||||
@@ -121,19 +121,12 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (b
|
||||
if f.preserve != nil {
|
||||
currentPreserve, externPreserve = f.preserve(current), f.preserve(extern)
|
||||
}
|
||||
choiceRules := func() bool {
|
||||
if extern.Time == current.Time {
|
||||
doubleSign := (extern.Coinbase == current.Coinbase)
|
||||
if doubleSign {
|
||||
return extern.Hash().Cmp(current.Hash()) < 0
|
||||
} else {
|
||||
return f.rand.Float64() < 0.5
|
||||
}
|
||||
} else {
|
||||
return extern.Time < current.Time
|
||||
}
|
||||
}
|
||||
reorg = !currentPreserve && (externPreserve || choiceRules())
|
||||
doubleSign := (extern.Coinbase == current.Coinbase)
|
||||
reorg = !currentPreserve && (externPreserve ||
|
||||
extern.Time < current.Time ||
|
||||
extern.Time == current.Time &&
|
||||
((doubleSign && extern.Hash().Cmp(current.Hash()) < 0) ||
|
||||
(!doubleSign && f.rand.Float64() < 0.5)))
|
||||
}
|
||||
return reorg, nil
|
||||
}
|
||||
|
||||
@@ -216,10 +216,8 @@ func (e *GenesisMismatchError) Error() string {
|
||||
// ChainOverrides contains the changes to chain config
|
||||
// Typically, these modifications involve hardforks that are not enabled on the BSC mainnet, intended for testing purposes.
|
||||
type ChainOverrides struct {
|
||||
OverridePassedForkTime *uint64
|
||||
OverridePascal *uint64
|
||||
OverridePrague *uint64
|
||||
OverrideVerkle *uint64
|
||||
OverrideBohr *uint64
|
||||
OverrideVerkle *uint64
|
||||
}
|
||||
|
||||
// SetupGenesisBlock writes or updates the genesis block in db.
|
||||
@@ -245,21 +243,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
|
||||
}
|
||||
applyOverrides := func(config *params.ChainConfig) {
|
||||
if config != nil {
|
||||
if overrides != nil && overrides.OverridePassedForkTime != nil {
|
||||
config.ShanghaiTime = overrides.OverridePassedForkTime
|
||||
config.KeplerTime = overrides.OverridePassedForkTime
|
||||
config.FeynmanTime = overrides.OverridePassedForkTime
|
||||
config.FeynmanFixTime = overrides.OverridePassedForkTime
|
||||
config.CancunTime = overrides.OverridePassedForkTime
|
||||
config.HaberTime = overrides.OverridePassedForkTime
|
||||
config.HaberFixTime = overrides.OverridePassedForkTime
|
||||
config.BohrTime = overrides.OverridePassedForkTime
|
||||
}
|
||||
if overrides != nil && overrides.OverridePascal != nil {
|
||||
config.PascalTime = overrides.OverridePascal
|
||||
}
|
||||
if overrides != nil && overrides.OverridePrague != nil {
|
||||
config.PragueTime = overrides.OverridePrague
|
||||
if overrides != nil && overrides.OverrideBohr != nil {
|
||||
config.BohrTime = overrides.OverrideBohr
|
||||
}
|
||||
if overrides != nil && overrides.OverrideVerkle != nil {
|
||||
config.VerkleTime = overrides.OverrideVerkle
|
||||
|
||||
@@ -68,7 +68,6 @@ func newPrunedFreezer(datadir string, db ethdb.KeyValueStore, offset uint64) (*p
|
||||
|
||||
// repair init frozen , compatible disk-ancientdb and pruner-block-tool.
|
||||
func (f *prunedfreezer) repair(datadir string) error {
|
||||
offset := atomic.LoadUint64(&f.frozen)
|
||||
// compatible freezer
|
||||
minItems := uint64(math.MaxUint64)
|
||||
for name, disableSnappy := range chainFreezerNoSnappy {
|
||||
@@ -97,14 +96,19 @@ func (f *prunedfreezer) repair(datadir string) error {
|
||||
table.Close()
|
||||
}
|
||||
|
||||
// If the dataset has undergone a prune block, the offset is a non-zero value, otherwise the offset is a zero value.
|
||||
// The minItems is the value relative to offset
|
||||
offset += minItems
|
||||
// If minItems is non-zero, it indicates that the chain freezer was previously enabled, and we should use minItems as the current frozen value.
|
||||
// If minItems is zero, it indicates that the pruneAncient was previously enabled, and we should continue using frozen
|
||||
// (retrieved from CurrentAncientFreezer) as the current frozen value.
|
||||
offset := minItems
|
||||
if offset == 0 {
|
||||
// no item in ancientDB, init `offset` to the `f.frozen`
|
||||
offset = atomic.LoadUint64(&f.frozen)
|
||||
}
|
||||
log.Info("Read ancientdb item counts", "items", minItems, "offset", offset)
|
||||
|
||||
// FrozenOfAncientFreezer is the progress of the last prune-freezer freeze.
|
||||
frozenInDB := ReadFrozenOfAncientFreezer(f.db)
|
||||
maxOffset := max(offset, frozenInDB)
|
||||
log.Info("Read ancient db item counts", "items", minItems, "frozen", maxOffset)
|
||||
|
||||
atomic.StoreUint64(&f.frozen, maxOffset)
|
||||
if err := f.Sync(); err != nil {
|
||||
@@ -157,12 +161,12 @@ func (f *prunedfreezer) AncientOffSet() uint64 {
|
||||
|
||||
// MigrateTable processes the entries in a given table in sequence
|
||||
// converting them to a new format if they're of an old format.
|
||||
func (f *prunedfreezer) MigrateTable(kind string, convert convertLegacyFn) error {
|
||||
func (db *prunedfreezer) MigrateTable(kind string, convert convertLegacyFn) error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
// AncientDatadir returns an error as we don't have a backing chain freezer.
|
||||
func (f *prunedfreezer) AncientDatadir() (string, error) {
|
||||
func (db *prunedfreezer) AncientDatadir() (string, error) {
|
||||
return "", errNotSupported
|
||||
}
|
||||
|
||||
|
||||
@@ -231,13 +231,6 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
|
||||
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
||||
// contract. This method is exported to be used in tests.
|
||||
func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) {
|
||||
// Return immediately if beaconRoot equals the zero hash when using the Parlia engine.
|
||||
if beaconRoot == (common.Hash{}) {
|
||||
if chainConfig := vmenv.ChainConfig(); chainConfig != nil && chainConfig.Parlia != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with
|
||||
// the new root
|
||||
msg := &Message{
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,19 +0,0 @@
|
||||
package bohr
|
||||
|
||||
import _ "embed"
|
||||
|
||||
// contract codes for Mainnet upgrade
|
||||
var (
|
||||
//go:embed mainnet/ValidatorContract
|
||||
MainnetValidatorContract string
|
||||
//go:embed mainnet/StakeHubContract
|
||||
MainnetStakeHubContract string
|
||||
)
|
||||
|
||||
// contract codes for Chapel upgrade
|
||||
var (
|
||||
//go:embed chapel/ValidatorContract
|
||||
ChapelValidatorContract string
|
||||
//go:embed chapel/StakeHubContract
|
||||
ChapelStakeHubContract string
|
||||
)
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,168 +0,0 @@
|
||||
package pascal
|
||||
|
||||
import _ "embed"
|
||||
|
||||
// contract codes for Mainnet upgrade
|
||||
var (
|
||||
|
||||
//go:embed mainnet/ValidatorContract
|
||||
MainnetValidatorContract string
|
||||
|
||||
//go:embed mainnet/SlashContract
|
||||
MainnetSlashContract string
|
||||
|
||||
//go:embed mainnet/SystemRewardContract
|
||||
MainnetSystemRewardContract string
|
||||
|
||||
//go:embed mainnet/LightClientContract
|
||||
MainnetLightClientContract string
|
||||
|
||||
//go:embed mainnet/TokenHubContract
|
||||
MainnetTokenHubContract string
|
||||
|
||||
//go:embed mainnet/RelayerIncentivizeContract
|
||||
MainnetRelayerIncentivizeContract string
|
||||
|
||||
//go:embed mainnet/RelayerHubContract
|
||||
MainnetRelayerHubContract string
|
||||
|
||||
//go:embed mainnet/GovHubContract
|
||||
MainnetGovHubContract string
|
||||
|
||||
//go:embed mainnet/TokenManagerContract
|
||||
MainnetTokenManagerContract string
|
||||
|
||||
//go:embed mainnet/CrossChainContract
|
||||
MainnetCrossChainContract string
|
||||
|
||||
//go:embed mainnet/StakingContract
|
||||
MainnetStakingContract string
|
||||
|
||||
//go:embed mainnet/StakeHubContract
|
||||
MainnetStakeHubContract string
|
||||
|
||||
//go:embed mainnet/StakeCreditContract
|
||||
MainnetStakeCreditContract string
|
||||
|
||||
//go:embed mainnet/GovernorContract
|
||||
MainnetGovernorContract string
|
||||
|
||||
//go:embed mainnet/GovTokenContract
|
||||
MainnetGovTokenContract string
|
||||
|
||||
//go:embed mainnet/TimelockContract
|
||||
MainnetTimelockContract string
|
||||
|
||||
//go:embed mainnet/TokenRecoverPortalContract
|
||||
MainnetTokenRecoverPortalContract string
|
||||
)
|
||||
|
||||
// contract codes for Chapel upgrade
|
||||
var (
|
||||
|
||||
//go:embed chapel/ValidatorContract
|
||||
ChapelValidatorContract string
|
||||
|
||||
//go:embed chapel/SlashContract
|
||||
ChapelSlashContract string
|
||||
|
||||
//go:embed chapel/SystemRewardContract
|
||||
ChapelSystemRewardContract string
|
||||
|
||||
//go:embed chapel/LightClientContract
|
||||
ChapelLightClientContract string
|
||||
|
||||
//go:embed chapel/TokenHubContract
|
||||
ChapelTokenHubContract string
|
||||
|
||||
//go:embed chapel/RelayerIncentivizeContract
|
||||
ChapelRelayerIncentivizeContract string
|
||||
|
||||
//go:embed chapel/RelayerHubContract
|
||||
ChapelRelayerHubContract string
|
||||
|
||||
//go:embed chapel/GovHubContract
|
||||
ChapelGovHubContract string
|
||||
|
||||
//go:embed chapel/TokenManagerContract
|
||||
ChapelTokenManagerContract string
|
||||
|
||||
//go:embed chapel/CrossChainContract
|
||||
ChapelCrossChainContract string
|
||||
|
||||
//go:embed chapel/StakingContract
|
||||
ChapelStakingContract string
|
||||
|
||||
//go:embed chapel/StakeHubContract
|
||||
ChapelStakeHubContract string
|
||||
|
||||
//go:embed chapel/StakeCreditContract
|
||||
ChapelStakeCreditContract string
|
||||
|
||||
//go:embed chapel/GovernorContract
|
||||
ChapelGovernorContract string
|
||||
|
||||
//go:embed chapel/GovTokenContract
|
||||
ChapelGovTokenContract string
|
||||
|
||||
//go:embed chapel/TimelockContract
|
||||
ChapelTimelockContract string
|
||||
|
||||
//go:embed chapel/TokenRecoverPortalContract
|
||||
ChapelTokenRecoverPortalContract string
|
||||
)
|
||||
|
||||
// contract codes for Rialto upgrade
|
||||
var (
|
||||
|
||||
//go:embed rialto/ValidatorContract
|
||||
RialtoValidatorContract string
|
||||
|
||||
//go:embed rialto/SlashContract
|
||||
RialtoSlashContract string
|
||||
|
||||
//go:embed rialto/SystemRewardContract
|
||||
RialtoSystemRewardContract string
|
||||
|
||||
//go:embed rialto/LightClientContract
|
||||
RialtoLightClientContract string
|
||||
|
||||
//go:embed rialto/TokenHubContract
|
||||
RialtoTokenHubContract string
|
||||
|
||||
//go:embed rialto/RelayerIncentivizeContract
|
||||
RialtoRelayerIncentivizeContract string
|
||||
|
||||
//go:embed rialto/RelayerHubContract
|
||||
RialtoRelayerHubContract string
|
||||
|
||||
//go:embed rialto/GovHubContract
|
||||
RialtoGovHubContract string
|
||||
|
||||
//go:embed rialto/TokenManagerContract
|
||||
RialtoTokenManagerContract string
|
||||
|
||||
//go:embed rialto/CrossChainContract
|
||||
RialtoCrossChainContract string
|
||||
|
||||
//go:embed rialto/StakingContract
|
||||
RialtoStakingContract string
|
||||
|
||||
//go:embed rialto/StakeHubContract
|
||||
RialtoStakeHubContract string
|
||||
|
||||
//go:embed rialto/StakeCreditContract
|
||||
RialtoStakeCreditContract string
|
||||
|
||||
//go:embed rialto/GovernorContract
|
||||
RialtoGovernorContract string
|
||||
|
||||
//go:embed rialto/GovTokenContract
|
||||
RialtoGovTokenContract string
|
||||
|
||||
//go:embed rialto/TimelockContract
|
||||
RialtoTimelockContract string
|
||||
|
||||
//go:embed rialto/TokenRecoverPortalContract
|
||||
RialtoTokenRecoverPortalContract string
|
||||
)
|
||||
@@ -4,11 +4,10 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/bohr"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/bruno"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/euler"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/feynman"
|
||||
@@ -20,11 +19,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/mirror"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/moran"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/niels"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/pascal"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/planck"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/plato"
|
||||
"github.com/ethereum/go-ethereum/core/systemcontracts/ramanujan"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
@@ -42,7 +39,7 @@ type Upgrade struct {
|
||||
Configs []*UpgradeConfig
|
||||
}
|
||||
|
||||
type upgradeHook func(blockNumber *big.Int, contractAddr common.Address, statedb vm.StateDB) error
|
||||
type upgradeHook func(blockNumber *big.Int, contractAddr common.Address, statedb *state.StateDB) error
|
||||
|
||||
const (
|
||||
mainNet = "Mainnet"
|
||||
@@ -81,10 +78,6 @@ var (
|
||||
feynmanFixUpgrade = make(map[string]*Upgrade)
|
||||
|
||||
haberFixUpgrade = make(map[string]*Upgrade)
|
||||
|
||||
bohrUpgrade = make(map[string]*Upgrade)
|
||||
|
||||
pascalUpgrade = make(map[string]*Upgrade)
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -743,318 +736,12 @@ func init() {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
bohrUpgrade[mainNet] = &Upgrade{
|
||||
UpgradeName: "bohr",
|
||||
Configs: []*UpgradeConfig{
|
||||
{
|
||||
ContractAddr: common.HexToAddress(ValidatorContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/398c9364aad5261c1ecd90ac3ab2df89b65c45e3",
|
||||
Code: bohr.MainnetValidatorContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakeHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/398c9364aad5261c1ecd90ac3ab2df89b65c45e3",
|
||||
Code: bohr.MainnetStakeHubContract,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
bohrUpgrade[chapelNet] = &Upgrade{
|
||||
UpgradeName: "bohr",
|
||||
Configs: []*UpgradeConfig{
|
||||
{
|
||||
ContractAddr: common.HexToAddress(ValidatorContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/398c9364aad5261c1ecd90ac3ab2df89b65c45e3",
|
||||
Code: bohr.ChapelValidatorContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakeHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/398c9364aad5261c1ecd90ac3ab2df89b65c45e3",
|
||||
Code: bohr.ChapelStakeHubContract,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pascalUpgrade[mainNet] = &Upgrade{
|
||||
UpgradeName: "pascal",
|
||||
Configs: []*UpgradeConfig{
|
||||
{
|
||||
ContractAddr: common.HexToAddress(ValidatorContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetValidatorContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(SlashContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetSlashContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(SystemRewardContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetSystemRewardContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(LightClientContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetLightClientContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetTokenHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(RelayerIncentivizeContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetRelayerIncentivizeContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(RelayerHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetRelayerHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetGovHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenManagerContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetTokenManagerContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(CrossChainContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetCrossChainContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakingContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetStakingContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakeHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetStakeHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakeCreditContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetStakeCreditContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovernorContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetGovernorContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovTokenContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetGovTokenContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TimelockContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetTimelockContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenRecoverPortalContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.MainnetTokenRecoverPortalContract,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pascalUpgrade[chapelNet] = &Upgrade{
|
||||
UpgradeName: "pascal",
|
||||
Configs: []*UpgradeConfig{
|
||||
{
|
||||
ContractAddr: common.HexToAddress(ValidatorContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelValidatorContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(SlashContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelSlashContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(SystemRewardContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelSystemRewardContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(LightClientContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelLightClientContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelTokenHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(RelayerIncentivizeContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelRelayerIncentivizeContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(RelayerHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelRelayerHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelGovHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenManagerContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelTokenManagerContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(CrossChainContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelCrossChainContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakingContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelStakingContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakeHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelStakeHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakeCreditContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelStakeCreditContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovernorContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelGovernorContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovTokenContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelGovTokenContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TimelockContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelTimelockContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenRecoverPortalContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.ChapelTokenRecoverPortalContract,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pascalUpgrade[rialtoNet] = &Upgrade{
|
||||
UpgradeName: "pascal",
|
||||
Configs: []*UpgradeConfig{
|
||||
{
|
||||
ContractAddr: common.HexToAddress(ValidatorContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoValidatorContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(SlashContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoSlashContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(SystemRewardContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoSystemRewardContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(LightClientContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoLightClientContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoTokenHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(RelayerIncentivizeContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoRelayerIncentivizeContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(RelayerHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoRelayerHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoGovHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenManagerContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoTokenManagerContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(CrossChainContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoCrossChainContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakingContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoStakingContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakeHubContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoStakeHubContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(StakeCreditContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoStakeCreditContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovernorContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoGovernorContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(GovTokenContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoGovTokenContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TimelockContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoTimelockContract,
|
||||
},
|
||||
{
|
||||
ContractAddr: common.HexToAddress(TokenRecoverPortalContract),
|
||||
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
|
||||
Code: pascal.RialtoTokenRecoverPortalContract,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb vm.StateDB) {
|
||||
if config == nil || blockNumber == nil || statedb == nil || reflect.ValueOf(statedb).IsNil() {
|
||||
func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb *state.StateDB) {
|
||||
if config == nil || blockNumber == nil || statedb == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var network string
|
||||
switch GenesisHash {
|
||||
/* Add mainnet genesis hash */
|
||||
@@ -1129,20 +816,12 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I
|
||||
applySystemContractUpgrade(haberFixUpgrade[network], blockNumber, statedb, logger)
|
||||
}
|
||||
|
||||
if config.IsOnBohr(blockNumber, lastBlockTime, blockTime) {
|
||||
applySystemContractUpgrade(bohrUpgrade[network], blockNumber, statedb, logger)
|
||||
}
|
||||
|
||||
if config.IsOnPascal(blockNumber, lastBlockTime, blockTime) {
|
||||
applySystemContractUpgrade(pascalUpgrade[network], blockNumber, statedb, logger)
|
||||
}
|
||||
|
||||
/*
|
||||
apply other upgrades
|
||||
*/
|
||||
}
|
||||
|
||||
func applySystemContractUpgrade(upgrade *Upgrade, blockNumber *big.Int, statedb vm.StateDB, logger log.Logger) {
|
||||
func applySystemContractUpgrade(upgrade *Upgrade, blockNumber *big.Int, statedb *state.StateDB, logger log.Logger) {
|
||||
if upgrade == nil {
|
||||
logger.Info("Empty upgrade config", "height", blockNumber.String())
|
||||
return
|
||||
|
||||
@@ -2,13 +2,9 @@ package systemcontracts
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -43,31 +39,3 @@ func TestAllCodesHash(t *testing.T) {
|
||||
allCodeHash := sha256.Sum256(allCodes)
|
||||
require.Equal(t, allCodeHash[:], common.Hex2Bytes("833cc0fc87c46ad8a223e44ccfdc16a51a7e7383525136441bd0c730f06023df"))
|
||||
}
|
||||
|
||||
func TestUpgradeBuildInSystemContractNilInterface(t *testing.T) {
|
||||
var (
|
||||
config = params.BSCChainConfig
|
||||
blockNumber = big.NewInt(37959559)
|
||||
lastBlockTime uint64 = 1713419337
|
||||
blockTime uint64 = 1713419340
|
||||
statedb vm.StateDB
|
||||
)
|
||||
|
||||
GenesisHash = params.BSCGenesisHash
|
||||
|
||||
UpgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, statedb)
|
||||
}
|
||||
|
||||
func TestUpgradeBuildInSystemContractNilValue(t *testing.T) {
|
||||
var (
|
||||
config = params.BSCChainConfig
|
||||
blockNumber = big.NewInt(37959559)
|
||||
lastBlockTime uint64 = 1713419337
|
||||
blockTime uint64 = 1713419340
|
||||
statedb vm.StateDB = (*state.StateDB)(nil)
|
||||
)
|
||||
|
||||
GenesisHash = params.BSCGenesisHash
|
||||
|
||||
UpgradeBuildInSystemContract(config, blockNumber, lastBlockTime, blockTime, statedb)
|
||||
}
|
||||
|
||||
@@ -2,12 +2,10 @@ package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
@@ -55,40 +53,3 @@ func (s *BlobSidecar) SanityCheck(blockNumber *big.Int, blockHash common.Hash) e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *BlobSidecar) MarshalJSON() ([]byte, error) {
|
||||
fields := map[string]interface{}{
|
||||
"blockHash": s.BlockHash,
|
||||
"blockNumber": hexutil.EncodeUint64(s.BlockNumber.Uint64()),
|
||||
"txHash": s.TxHash,
|
||||
"txIndex": hexutil.EncodeUint64(s.TxIndex),
|
||||
}
|
||||
fields["blobSidecar"] = s.BlobTxSidecar
|
||||
return json.Marshal(fields)
|
||||
}
|
||||
|
||||
func (s *BlobSidecar) UnmarshalJSON(input []byte) error {
|
||||
type blobSidecar struct {
|
||||
BlobSidecar BlobTxSidecar `json:"blobSidecar"`
|
||||
BlockNumber *hexutil.Big `json:"blockNumber"`
|
||||
BlockHash common.Hash `json:"blockHash"`
|
||||
TxIndex *hexutil.Big `json:"txIndex"`
|
||||
TxHash common.Hash `json:"txHash"`
|
||||
}
|
||||
var blob blobSidecar
|
||||
if err := json.Unmarshal(input, &blob); err != nil {
|
||||
return err
|
||||
}
|
||||
s.BlobTxSidecar = blob.BlobSidecar
|
||||
if blob.BlockNumber == nil {
|
||||
return errors.New("missing required field 'blockNumber' for BlobSidecar")
|
||||
}
|
||||
s.BlockNumber = blob.BlockNumber.ToInt()
|
||||
s.BlockHash = blob.BlockHash
|
||||
if blob.TxIndex == nil {
|
||||
return errors.New("missing required field 'txIndex' for BlobSidecar")
|
||||
}
|
||||
s.TxIndex = blob.TxIndex.ToInt().Uint64()
|
||||
s.TxHash = blob.TxHash
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package vote
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -20,13 +19,7 @@ import (
|
||||
|
||||
const blocksNumberSinceMining = 5 // the number of blocks need to wait before voting, counting from the validator begin to mine
|
||||
|
||||
var diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures
|
||||
var votesManagerCounter = metrics.NewRegisteredCounter("votesManager/local", nil)
|
||||
var notJustified = metrics.NewRegisteredCounter("votesManager/notJustified", nil)
|
||||
var inTurnJustified = metrics.NewRegisteredCounter("votesManager/inTurnJustified", nil)
|
||||
var notInTurnJustified = metrics.NewRegisteredCounter("votesManager/notInTurnJustified", nil)
|
||||
var continuousJustified = metrics.NewRegisteredCounter("votesManager/continuousJustified", nil)
|
||||
var notContinuousJustified = metrics.NewRegisteredCounter("votesManager/notContinuousJustified", nil)
|
||||
|
||||
// Backend wraps all methods required for voting.
|
||||
type Backend interface {
|
||||
@@ -162,7 +155,7 @@ func (voteManager *VoteManager) loop() {
|
||||
func(bLSPublicKey *types.BLSPublicKey) bool {
|
||||
return bytes.Equal(voteManager.signer.PubKey[:], bLSPublicKey[:])
|
||||
}) {
|
||||
log.Debug("local validator with voteKey is not within the validatorSet at curHead")
|
||||
log.Debug("cur validator is not within the validatorSet at curHead")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -209,36 +202,6 @@ func (voteManager *VoteManager) loop() {
|
||||
voteManager.pool.PutVote(voteMessage)
|
||||
votesManagerCounter.Inc(1)
|
||||
}
|
||||
|
||||
// check the latest justified block, which indicating the stability of the network
|
||||
curJustifiedNumber, _, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, []*types.Header{curHead})
|
||||
if err == nil && curJustifiedNumber != 0 {
|
||||
if curJustifiedNumber+1 != curHead.Number.Uint64() {
|
||||
log.Debug("not justified", "blockNumber", curHead.Number.Uint64()-1)
|
||||
notJustified.Inc(1)
|
||||
} else {
|
||||
parent := voteManager.chain.GetHeaderByHash(curHead.ParentHash)
|
||||
if parent != nil {
|
||||
if parent.Difficulty.Cmp(diffInTurn) == 0 {
|
||||
inTurnJustified.Inc(1)
|
||||
} else {
|
||||
log.Debug("not in turn block justified", "blockNumber", parent.Number.Int64(), "blockHash", parent.Hash())
|
||||
notInTurnJustified.Inc(1)
|
||||
}
|
||||
|
||||
lastJustifiedNumber, _, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, []*types.Header{parent})
|
||||
if err == nil {
|
||||
if lastJustifiedNumber == 0 || lastJustifiedNumber+1 == curJustifiedNumber {
|
||||
continuousJustified.Inc(1)
|
||||
} else {
|
||||
log.Debug("not continuous block justified", "lastJustified", lastJustifiedNumber, "curJustified", curJustifiedNumber)
|
||||
notContinuousJustified.Inc(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case event := <-voteManager.syncVoteCh:
|
||||
voteMessage := event.Vote
|
||||
if voteManager.eth.IsMining() || !bytes.Equal(voteManager.signer.PubKey[:], voteMessage.VoteAddress[:]) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package bn256
|
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields", Devegili et al.
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
import (
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user