Compare commits
19 Commits
faucet-rat
...
versa_base
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5b5805359 | ||
|
|
34bc9e02aa | ||
|
|
8a3d62e756 | ||
|
|
d4879836c0 | ||
|
|
4b00174821 | ||
|
|
3082da4e86 | ||
|
|
d334f520be | ||
|
|
cef6acec23 | ||
|
|
092fbafa3c | ||
|
|
c4e8ec7fea | ||
|
|
83a9b13771 | ||
|
|
c6cb43b7ca | ||
|
|
222e10810e | ||
|
|
26b236fb5f | ||
|
|
900cf26c65 | ||
|
|
75d162983a | ||
|
|
719412551a | ||
|
|
f0c7795542 | ||
|
|
4566ac7659 |
@@ -49,7 +49,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"golang.org/x/time/rate"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -217,8 +216,6 @@ type faucet struct {
|
|||||||
|
|
||||||
bep2eInfos map[string]bep2eInfo
|
bep2eInfos map[string]bep2eInfo
|
||||||
bep2eAbi abi.ABI
|
bep2eAbi abi.ABI
|
||||||
|
|
||||||
limiter *IPRateLimiter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wsConn wraps a websocket connection with a write mutex as the underlying
|
// wsConn wraps a websocket connection with a write mutex as the underlying
|
||||||
@@ -238,12 +235,6 @@ func newFaucet(genesis *core.Genesis, url string, ks *keystore.KeyStore, index [
|
|||||||
return nil, err
|
return nil, 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)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &faucet{
|
return &faucet{
|
||||||
config: genesis.Config,
|
config: genesis.Config,
|
||||||
client: client,
|
client: client,
|
||||||
@@ -254,7 +245,6 @@ func newFaucet(genesis *core.Genesis, url string, ks *keystore.KeyStore, index [
|
|||||||
update: make(chan struct{}, 1),
|
update: make(chan struct{}, 1),
|
||||||
bep2eInfos: bep2eInfos,
|
bep2eInfos: bep2eInfos,
|
||||||
bep2eAbi: bep2eAbi,
|
bep2eAbi: bep2eAbi,
|
||||||
limiter: limiter,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,20 +272,6 @@ func (f *faucet) webHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// apiHandler handles requests for Ether grants and transaction statuses.
|
// apiHandler handles requests for Ether grants and transaction statuses.
|
||||||
func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ip := r.RemoteAddr
|
|
||||||
if len(r.Header.Get("X-Forwarded-For")) > 0 {
|
|
||||||
ips := strings.Split(r.Header.Get("X-Forwarded-For"), ",")
|
|
||||||
if len(ips) > 0 {
|
|
||||||
ip = strings.TrimSpace(ips[len(ips)-1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !f.limiter.GetLimiter(ip).Allow() {
|
|
||||||
log.Warn("Too many requests from client: ", "client", ip)
|
|
||||||
http.Error(w, "Too many requests", http.StatusTooManyRequests)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
upgrader := websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
|
upgrader := websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
|
||||||
conn, err := upgrader.Upgrade(w, r, nil)
|
conn, err := upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -649,7 +625,6 @@ func (f *faucet) loop() {
|
|||||||
balance := new(big.Int).Div(f.balance, ether)
|
balance := new(big.Int).Div(f.balance, ether)
|
||||||
|
|
||||||
for _, conn := range f.conns {
|
for _, conn := range f.conns {
|
||||||
go func(conn *wsConn) {
|
|
||||||
if err := send(conn, map[string]interface{}{
|
if err := send(conn, map[string]interface{}{
|
||||||
"funds": balance,
|
"funds": balance,
|
||||||
"funded": f.nonce,
|
"funded": f.nonce,
|
||||||
@@ -657,14 +632,12 @@ func (f *faucet) loop() {
|
|||||||
}, time.Second); err != nil {
|
}, time.Second); err != nil {
|
||||||
log.Warn("Failed to send stats to client", "err", err)
|
log.Warn("Failed to send stats to client", "err", err)
|
||||||
conn.conn.Close()
|
conn.conn.Close()
|
||||||
return // Exit the goroutine if the first send fails
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := send(conn, head, time.Second); err != nil {
|
if err := send(conn, head, time.Second); err != nil {
|
||||||
log.Warn("Failed to send header to client", "err", err)
|
log.Warn("Failed to send header to client", "err", err)
|
||||||
conn.conn.Close()
|
conn.conn.Close()
|
||||||
}
|
}
|
||||||
}(conn)
|
|
||||||
}
|
}
|
||||||
f.lock.RUnlock()
|
f.lock.RUnlock()
|
||||||
}
|
}
|
||||||
@@ -683,12 +656,10 @@ func (f *faucet) loop() {
|
|||||||
// Pending requests updated, stream to clients
|
// Pending requests updated, stream to clients
|
||||||
f.lock.RLock()
|
f.lock.RLock()
|
||||||
for _, conn := range f.conns {
|
for _, conn := range f.conns {
|
||||||
go func(conn *wsConn) {
|
|
||||||
if err := send(conn, map[string]interface{}{"requests": f.reqs}, time.Second); err != nil {
|
if err := send(conn, map[string]interface{}{"requests": f.reqs}, time.Second); err != nil {
|
||||||
log.Warn("Failed to send requests to client", "err", err)
|
log.Warn("Failed to send requests to client", "err", err)
|
||||||
conn.conn.Close()
|
conn.conn.Close()
|
||||||
}
|
}
|
||||||
}(conn)
|
|
||||||
}
|
}
|
||||||
f.lock.RUnlock()
|
f.lock.RUnlock()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
lru "github.com/hashicorp/golang-lru"
|
|
||||||
"golang.org/x/time/rate"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IPRateLimiter struct {
|
|
||||||
ips *lru.Cache // LRU cache to store IP addresses and their associated rate limiters
|
|
||||||
r rate.Limit // the rate limit, e.g., 5 requests per second
|
|
||||||
b int // the burst size, e.g., allowing a burst of 10 requests at once. The rate limiter gets into action
|
|
||||||
// only after this number exceeds
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIPRateLimiter(r rate.Limit, b int, size int) (*IPRateLimiter, error) {
|
|
||||||
cache, err := lru.New(size)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
i := &IPRateLimiter{
|
|
||||||
ips: cache,
|
|
||||||
r: r,
|
|
||||||
b: b,
|
|
||||||
}
|
|
||||||
|
|
||||||
return i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *IPRateLimiter) addIP(ip string) *rate.Limiter {
|
|
||||||
limiter := rate.NewLimiter(i.r, i.b)
|
|
||||||
|
|
||||||
i.ips.Add(ip, limiter)
|
|
||||||
|
|
||||||
return limiter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter {
|
|
||||||
if limiter, exists := i.ips.Get(ip); exists {
|
|
||||||
return limiter.(*rate.Limiter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return i.addIP(ip)
|
|
||||||
}
|
|
||||||
@@ -33,7 +33,7 @@ node get_perf.js --rpc ${url} --startNum ${start} --endNum ${end}
|
|||||||
output as following
|
output as following
|
||||||
```bash
|
```bash
|
||||||
Get the performance between [ 19470 , 19670 )
|
Get the performance between [ 19470 , 19670 )
|
||||||
txCountPerBlock = 3142.81 txCountTotal = 628562 BlockCount = 200 avgBlockTime = 3.005 inturnBlocksRatio = 0.975 justifiedBlocksRatio = 0.98
|
txCountPerBlock = 3142.81 txCountTotal = 628562 BlockCount = 200 avgBlockTime = 3.005 inturnBlocksRatio = 0.975
|
||||||
txCountPerSecond = 1045.8602329450914 avgGasUsedPerBlock = 250.02062627 avgGasUsedPerSecond = 83.20153952412646
|
txCountPerSecond = 1045.8602329450914 avgGasUsedPerBlock = 250.02062627 avgGasUsedPerSecond = 83.20153952412646
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ const main = async () => {
|
|||||||
let txCountTotal = 0;
|
let txCountTotal = 0;
|
||||||
let gasUsedTotal = 0;
|
let gasUsedTotal = 0;
|
||||||
let inturnBlocks = 0;
|
let inturnBlocks = 0;
|
||||||
let justifiedBlocks = 0;
|
|
||||||
for (let i = program.startNum; i < program.endNum; i++) {
|
for (let i = program.startNum; i < program.endNum; i++) {
|
||||||
let txCount = await provider.send("eth_getBlockTransactionCountByNumber", [
|
let txCount = await provider.send("eth_getBlockTransactionCountByNumber", [
|
||||||
ethers.toQuantity(i)]);
|
ethers.toQuantity(i)]);
|
||||||
@@ -27,14 +26,6 @@ const main = async () => {
|
|||||||
inturnBlocks += 1
|
inturnBlocks += 1
|
||||||
}
|
}
|
||||||
let timestamp = eval(eval(header.timestamp).toString(10))
|
let timestamp = eval(eval(header.timestamp).toString(10))
|
||||||
|
|
||||||
let justifiedNumber = await provider.send("parlia_getJustifiedNumber", [
|
|
||||||
ethers.toQuantity(i)]);
|
|
||||||
if (justifiedNumber + 1 == i) {
|
|
||||||
justifiedBlocks += 1
|
|
||||||
} else {
|
|
||||||
console.log("justified unexpected", "BlockNumber =", i,"justifiedNumber",justifiedNumber)
|
|
||||||
}
|
|
||||||
console.log("BlockNumber =", i, "mod =", i%4, "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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,14 +41,13 @@ const main = async () => {
|
|||||||
let timeCost = endTime - startTime
|
let timeCost = endTime - startTime
|
||||||
let avgBlockTime = timeCost/blockCount
|
let avgBlockTime = timeCost/blockCount
|
||||||
let inturnBlocksRatio = inturnBlocks/blockCount
|
let inturnBlocksRatio = inturnBlocks/blockCount
|
||||||
let justifiedBlocksRatio = justifiedBlocks/blockCount
|
|
||||||
let tps = txCountTotal/timeCost
|
let tps = txCountTotal/timeCost
|
||||||
let M = 1000000
|
let M = 1000000
|
||||||
let avgGasUsedPerBlock = gasUsedTotal/blockCount/M
|
let avgGasUsedPerBlock = gasUsedTotal/blockCount/M
|
||||||
let avgGasUsedPerSecond = gasUsedTotal/timeCost/M
|
let avgGasUsedPerSecond = gasUsedTotal/timeCost/M
|
||||||
|
|
||||||
console.log("Get the performance between [", program.startNum, ",", program.endNum, ")");
|
console.log("Get the performance between [", program.startNum, ",", program.endNum, ")");
|
||||||
console.log("txCountPerBlock =", txCountPerBlock, "txCountTotal =", txCountTotal, "BlockCount =", blockCount, "avgBlockTime =", avgBlockTime, "inturnBlocksRatio =", inturnBlocksRatio, "justifiedBlocksRatio =", justifiedBlocksRatio);
|
console.log("txCountPerBlock =", txCountPerBlock, "txCountTotal =", txCountTotal, "BlockCount =", blockCount, "avgBlockTime =", avgBlockTime, "inturnBlocksRatio =", inturnBlocksRatio);
|
||||||
console.log("txCountPerSecond =", tps, "avgGasUsedPerBlock =", avgGasUsedPerBlock, "avgGasUsedPerSecond =", avgGasUsedPerSecond);
|
console.log("txCountPerSecond =", tps, "avgGasUsedPerBlock =", avgGasUsedPerBlock, "avgGasUsedPerSecond =", avgGasUsedPerSecond);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,6 @@ type ChainHeaderReader interface {
|
|||||||
// GetHighestVerifiedHeader retrieves the highest header verified.
|
// GetHighestVerifiedHeader retrieves the highest header verified.
|
||||||
GetHighestVerifiedHeader() *types.Header
|
GetHighestVerifiedHeader() *types.Header
|
||||||
|
|
||||||
// GetVerifiedBlockByHash retrieves the highest verified block.
|
|
||||||
GetVerifiedBlockByHash(hash common.Hash) *types.Header
|
|
||||||
|
|
||||||
// ChasingHead return the best chain head of peers.
|
// ChasingHead return the best chain head of peers.
|
||||||
ChasingHead() *types.Header
|
ChasingHead() *types.Header
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,13 @@ type API struct {
|
|||||||
|
|
||||||
// GetSnapshot retrieves the state snapshot at a given block.
|
// GetSnapshot retrieves the state snapshot at a given block.
|
||||||
func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
|
func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
|
||||||
header := api.getHeader(number)
|
// Retrieve the requested block number (or current if none requested)
|
||||||
|
var header *types.Header
|
||||||
|
if number == nil || *number == rpc.LatestBlockNumber {
|
||||||
|
header = api.chain.CurrentHeader()
|
||||||
|
} else {
|
||||||
|
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
||||||
|
}
|
||||||
// Ensure we have an actually valid block and return its snapshot
|
// Ensure we have an actually valid block and return its snapshot
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil, errUnknownBlock
|
return nil, errUnknownBlock
|
||||||
@@ -50,7 +56,13 @@ func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) {
|
|||||||
|
|
||||||
// GetValidators retrieves the list of validators at the specified block.
|
// GetValidators retrieves the list of validators at the specified block.
|
||||||
func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.Address, error) {
|
func (api *API) GetValidators(number *rpc.BlockNumber) ([]common.Address, error) {
|
||||||
header := api.getHeader(number)
|
// Retrieve the requested block number (or current if none requested)
|
||||||
|
var header *types.Header
|
||||||
|
if number == nil || *number == rpc.LatestBlockNumber {
|
||||||
|
header = api.chain.CurrentHeader()
|
||||||
|
} else {
|
||||||
|
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
||||||
|
}
|
||||||
// Ensure we have an actually valid block and return the validators from its snapshot
|
// Ensure we have an actually valid block and return the validators from its snapshot
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil, errUnknownBlock
|
return nil, errUnknownBlock
|
||||||
@@ -74,52 +86,3 @@ func (api *API) GetValidatorsAtHash(hash common.Hash) ([]common.Address, error)
|
|||||||
}
|
}
|
||||||
return snap.validators(), nil
|
return snap.validators(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) GetJustifiedNumber(number *rpc.BlockNumber) (uint64, 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.Attestation == nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return snap.Attestation.TargetNumber, 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
|
|
||||||
if header == nil {
|
|
||||||
return 0, errUnknownBlock
|
|
||||||
}
|
|
||||||
snap, err := api.parlia.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
|
||||||
if err != nil || snap.Attestation == nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return snap.Attestation.SourceNumber, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) getHeader(number *rpc.BlockNumber) (header *types.Header) {
|
|
||||||
currentHeader := api.chain.CurrentHeader()
|
|
||||||
|
|
||||||
if number == nil || *number == rpc.LatestBlockNumber {
|
|
||||||
header = currentHeader // current if none requested
|
|
||||||
} else if *number == rpc.SafeBlockNumber {
|
|
||||||
justifiedNumber, _, err := api.parlia.GetJustifiedNumberAndHash(api.chain, []*types.Header{currentHeader})
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
header = api.chain.GetHeaderByNumber(justifiedNumber)
|
|
||||||
} else if *number == rpc.FinalizedBlockNumber {
|
|
||||||
header = api.parlia.GetFinalizedHeader(api.chain, currentHeader)
|
|
||||||
} else if *number == rpc.PendingBlockNumber {
|
|
||||||
return nil // no pending blocks on bsc
|
|
||||||
} else if *number == rpc.EarliestBlockNumber {
|
|
||||||
header = api.chain.GetHeaderByNumber(0)
|
|
||||||
} else {
|
|
||||||
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -605,11 +604,15 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
|
|||||||
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
|
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
|
||||||
case header.BlobGasUsed != nil:
|
case header.BlobGasUsed != nil:
|
||||||
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
|
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
|
||||||
|
case header.ParentBeaconRoot != nil:
|
||||||
|
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
|
||||||
case header.WithdrawalsHash != nil:
|
case header.WithdrawalsHash != nil:
|
||||||
return fmt.Errorf("invalid WithdrawalsHash, have %#x, expected nil", header.WithdrawalsHash)
|
return fmt.Errorf("invalid WithdrawalsHash, have %#x, expected nil", header.WithdrawalsHash)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch {
|
switch {
|
||||||
|
case header.ParentBeaconRoot != nil:
|
||||||
|
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
|
||||||
case !header.EmptyWithdrawalsHash():
|
case !header.EmptyWithdrawalsHash():
|
||||||
return errors.New("header has wrong WithdrawalsHash")
|
return errors.New("header has wrong WithdrawalsHash")
|
||||||
}
|
}
|
||||||
@@ -618,17 +621,6 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bohr := chain.Config().IsBohr(header.Number, header.Time)
|
|
||||||
if !bohr {
|
|
||||||
if header.ParentBeaconRoot != nil {
|
|
||||||
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if header.ParentBeaconRoot == nil || *header.ParentBeaconRoot != (common.Hash{}) {
|
|
||||||
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected zero hash", header.ParentBeaconRoot)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All basic checks passed, verify cascading fields
|
// All basic checks passed, verify cascading fields
|
||||||
return p.verifyCascadingFields(chain, header, parents)
|
return p.verifyCascadingFields(chain, header, parents)
|
||||||
}
|
}
|
||||||
@@ -1370,7 +1362,7 @@ func (p *Parlia) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *
|
|||||||
func (p *Parlia) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteEnvelope) error {
|
func (p *Parlia) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteEnvelope) error {
|
||||||
targetNumber := vote.Data.TargetNumber
|
targetNumber := vote.Data.TargetNumber
|
||||||
targetHash := vote.Data.TargetHash
|
targetHash := vote.Data.TargetHash
|
||||||
header := chain.GetVerifiedBlockByHash(targetHash)
|
header := chain.GetHeaderByHash(targetHash)
|
||||||
if header == nil {
|
if header == nil {
|
||||||
log.Warn("BlockHeader at current voteBlockNumber is nil", "targetNumber", targetNumber, "targetHash", targetHash)
|
log.Warn("BlockHeader at current voteBlockNumber is nil", "targetNumber", targetNumber, "targetHash", targetHash)
|
||||||
return errors.New("BlockHeader at current voteBlockNumber is nil")
|
return errors.New("BlockHeader at current voteBlockNumber is nil")
|
||||||
@@ -1602,35 +1594,11 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
|
|||||||
return new(big.Int).Set(diffNoTurn)
|
return new(big.Int).Set(diffNoTurn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeSigHeaderWithoutVoteAttestation(w io.Writer, header *types.Header, chainId *big.Int) {
|
|
||||||
err := rlp.Encode(w, []interface{}{
|
|
||||||
chainId,
|
|
||||||
header.ParentHash,
|
|
||||||
header.UncleHash,
|
|
||||||
header.Coinbase,
|
|
||||||
header.Root,
|
|
||||||
header.TxHash,
|
|
||||||
header.ReceiptHash,
|
|
||||||
header.Bloom,
|
|
||||||
header.Difficulty,
|
|
||||||
header.Number,
|
|
||||||
header.GasLimit,
|
|
||||||
header.GasUsed,
|
|
||||||
header.Time,
|
|
||||||
header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
|
|
||||||
header.MixDigest,
|
|
||||||
header.Nonce,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic("can't encode: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SealHash returns the hash of a block without vote attestation prior to it being sealed.
|
// SealHash returns the hash of a block without vote attestation prior to it being sealed.
|
||||||
// So it's not the real hash of a block, just used as unique id to distinguish task
|
// So it's not the real hash of a block, just used as unique id to distinguish task
|
||||||
func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) {
|
func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) {
|
||||||
hasher := sha3.NewLegacyKeccak256()
|
hasher := sha3.NewLegacyKeccak256()
|
||||||
encodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
|
types.EncodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
|
||||||
hasher.Sum(hash[:0])
|
hasher.Sum(hash[:0])
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
@@ -268,19 +267,8 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
snap.Recents[number] = validator
|
snap.Recents[number] = validator
|
||||||
snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity])
|
|
||||||
snap.updateAttestation(header, chainConfig, s.config)
|
|
||||||
// change validator set
|
// change validator set
|
||||||
if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) {
|
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,
|
|
||||||
// then the unexpected second switch will happen, just skip it.
|
|
||||||
if _, ok := snap.Recents[epochKey]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents)
|
checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents)
|
||||||
if checkpointHeader == nil {
|
if checkpointHeader == nil {
|
||||||
return nil, consensus.ErrUnknownAncestor
|
return nil, consensus.ErrUnknownAncestor
|
||||||
@@ -301,12 +289,6 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if chainConfig.IsBohr(header.Number, header.Time) {
|
|
||||||
// BEP-404: Clear Miner History when Switching Validators Set
|
|
||||||
snap.Recents = make(map[uint64]common.Address)
|
|
||||||
snap.Recents[epochKey] = common.Address{}
|
|
||||||
log.Debug("Recents are cleared up", "blockNumber", number)
|
|
||||||
} else {
|
|
||||||
oldLimit := len(snap.Validators)/2 + 1
|
oldLimit := len(snap.Validators)/2 + 1
|
||||||
newLimit := len(newVals)/2 + 1
|
newLimit := len(newVals)/2 + 1
|
||||||
if newLimit < oldLimit {
|
if newLimit < oldLimit {
|
||||||
@@ -314,9 +296,8 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
|||||||
delete(snap.Recents, number-uint64(newLimit)-uint64(i))
|
delete(snap.Recents, number-uint64(newLimit)-uint64(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
oldLimit = len(snap.Validators)
|
||||||
oldLimit := len(snap.Validators)
|
newLimit = len(newVals)
|
||||||
newLimit := len(newVals)
|
|
||||||
if newLimit < oldLimit {
|
if newLimit < oldLimit {
|
||||||
for i := 0; i < oldLimit-newLimit; i++ {
|
for i := 0; i < oldLimit-newLimit; i++ {
|
||||||
delete(snap.RecentForkHashes, number-uint64(newLimit)-uint64(i))
|
delete(snap.RecentForkHashes, number-uint64(newLimit)-uint64(i))
|
||||||
@@ -330,6 +311,10 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snap.updateAttestation(header, chainConfig, s.config)
|
||||||
|
|
||||||
|
snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity])
|
||||||
}
|
}
|
||||||
snap.Number += uint64(len(headers))
|
snap.Number += uint64(len(headers))
|
||||||
snap.Hash = headers[len(headers)-1].Hash()
|
snap.Hash = headers[len(headers)-1].Hash()
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
)
|
)
|
||||||
@@ -40,6 +41,12 @@ func EnableRemoteVerifyManager(remoteValidator *remoteVerifyManager) BlockValida
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
validateBloomTimer = metrics.NewRegisteredTimer("validate/bloom/time", nil)
|
||||||
|
validateReceiptTimer = metrics.NewRegisteredTimer("validate/receipt/time", nil)
|
||||||
|
validateRootTimer = metrics.NewRegisteredTimer("validate/root/time", nil)
|
||||||
|
)
|
||||||
|
|
||||||
// BlockValidator is responsible for validating block headers, uncles and
|
// BlockValidator is responsible for validating block headers, uncles and
|
||||||
// processed state.
|
// processed state.
|
||||||
//
|
//
|
||||||
@@ -184,6 +191,10 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
// For valid blocks this should always validate to true.
|
// For valid blocks this should always validate to true.
|
||||||
validateFuns := []func() error{
|
validateFuns := []func() error{
|
||||||
func() error {
|
func() error {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
validateBloomTimer.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
|
|
||||||
rbloom := types.CreateBloom(receipts)
|
rbloom := types.CreateBloom(receipts)
|
||||||
if rbloom != header.Bloom {
|
if rbloom != header.Bloom {
|
||||||
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
||||||
@@ -191,6 +202,9 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
func() error {
|
func() error {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
validateReceiptTimer.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
|
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
|
||||||
if receiptSha != header.ReceiptHash {
|
if receiptSha != header.ReceiptHash {
|
||||||
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
|
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
|
||||||
@@ -209,6 +223,9 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
validateFuns = append(validateFuns, func() error {
|
validateFuns = append(validateFuns, func() error {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
validateRootTimer.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
||||||
return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error())
|
return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ var (
|
|||||||
blockInsertMgaspsGauge = metrics.NewRegisteredGauge("chain/insert/mgasps", nil)
|
blockInsertMgaspsGauge = metrics.NewRegisteredGauge("chain/insert/mgasps", nil)
|
||||||
|
|
||||||
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
|
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
|
||||||
|
mGasPsGauge = metrics.NewRegisteredGauge("chain/process/gas", nil)
|
||||||
|
|
||||||
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
|
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
|
||||||
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
|
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
|
||||||
@@ -95,6 +96,9 @@ var (
|
|||||||
blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil)
|
blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil)
|
||||||
blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil)
|
blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil)
|
||||||
blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil)
|
blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil)
|
||||||
|
blockValidationTotalTimer = metrics.NewRegisteredTimer("chain/total/validation", nil)
|
||||||
|
blockExecutionTotalTimer = metrics.NewRegisteredTimer("chain/total/execution", nil)
|
||||||
|
blockWriteTotalTimer = metrics.NewRegisteredTimer("chain/total/write", nil)
|
||||||
|
|
||||||
blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil)
|
blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil)
|
||||||
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
||||||
@@ -268,7 +272,6 @@ type BlockChain struct {
|
|||||||
logsFeed event.Feed
|
logsFeed event.Feed
|
||||||
blockProcFeed event.Feed
|
blockProcFeed event.Feed
|
||||||
finalizedHeaderFeed event.Feed
|
finalizedHeaderFeed event.Feed
|
||||||
highestVerifiedBlockFeed event.Feed
|
|
||||||
scope event.SubscriptionScope
|
scope event.SubscriptionScope
|
||||||
genesisBlock *types.Block
|
genesisBlock *types.Block
|
||||||
|
|
||||||
@@ -277,7 +280,6 @@ type BlockChain struct {
|
|||||||
chainmu *syncx.ClosableMutex
|
chainmu *syncx.ClosableMutex
|
||||||
|
|
||||||
highestVerifiedHeader atomic.Pointer[types.Header]
|
highestVerifiedHeader atomic.Pointer[types.Header]
|
||||||
highestVerifiedBlock atomic.Pointer[types.Header]
|
|
||||||
currentBlock atomic.Pointer[types.Header] // Current head of the chain
|
currentBlock atomic.Pointer[types.Header] // Current head of the chain
|
||||||
currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync
|
currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync
|
||||||
currentFinalBlock atomic.Pointer[types.Header] // Latest (consensus) finalized block
|
currentFinalBlock atomic.Pointer[types.Header] // Latest (consensus) finalized block
|
||||||
@@ -402,7 +404,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||||||
}
|
}
|
||||||
|
|
||||||
bc.highestVerifiedHeader.Store(nil)
|
bc.highestVerifiedHeader.Store(nil)
|
||||||
bc.highestVerifiedBlock.Store(nil)
|
|
||||||
bc.currentBlock.Store(nil)
|
bc.currentBlock.Store(nil)
|
||||||
bc.currentSnapBlock.Store(nil)
|
bc.currentSnapBlock.Store(nil)
|
||||||
bc.chasingHead.Store(nil)
|
bc.chasingHead.Store(nil)
|
||||||
@@ -1801,6 +1802,12 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||||||
if err := blockBatch.Write(); err != nil {
|
if err := blockBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to write block into disk", "err", err)
|
log.Crit("Failed to write block into disk", "err", err)
|
||||||
}
|
}
|
||||||
|
bc.hc.tdCache.Add(block.Hash(), externTd)
|
||||||
|
bc.blockCache.Add(block.Hash(), block)
|
||||||
|
bc.receiptsCache.Add(block.Hash(), receipts)
|
||||||
|
if bc.chainConfig.IsCancun(block.Number(), block.Time()) {
|
||||||
|
bc.sidecarsCache.Add(block.Hash(), block.Sidecars())
|
||||||
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -1911,34 +1918,26 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||||||
|
|
||||||
// WriteBlockAndSetHead writes the given block and all associated state to the database,
|
// WriteBlockAndSetHead writes the given block and all associated state to the database,
|
||||||
// and applies the block as the new chain head.
|
// 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, mux *event.TypeMux) (status WriteStatus, err error) {
|
func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
||||||
if !bc.chainmu.TryLock() {
|
if !bc.chainmu.TryLock() {
|
||||||
return NonStatTy, errChainStopped
|
return NonStatTy, errChainStopped
|
||||||
}
|
}
|
||||||
defer bc.chainmu.Unlock()
|
defer bc.chainmu.Unlock()
|
||||||
|
|
||||||
return bc.writeBlockAndSetHead(block, receipts, logs, state, emitHeadEvent, mux)
|
return bc.writeBlockAndSetHead(block, receipts, logs, state, emitHeadEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
||||||
// This function expects the chain mutex to be held.
|
// 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, mux *event.TypeMux) (status WriteStatus, err error) {
|
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
||||||
|
if err := bc.writeBlockWithState(block, receipts, state); err != nil {
|
||||||
|
return NonStatTy, err
|
||||||
|
}
|
||||||
currentBlock := bc.CurrentBlock()
|
currentBlock := bc.CurrentBlock()
|
||||||
reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock, block.Header())
|
reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock, block.Header())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NonStatTy, err
|
return NonStatTy, err
|
||||||
}
|
}
|
||||||
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 {
|
|
||||||
return NonStatTy, err
|
|
||||||
}
|
|
||||||
if reorg {
|
if reorg {
|
||||||
// Reorganise the chain if the parent is not the head block
|
// Reorganise the chain if the parent is not the head block
|
||||||
if block.ParentHash() != currentBlock.Hash() {
|
if block.ParentHash() != currentBlock.Hash() {
|
||||||
@@ -2273,6 +2272,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
|||||||
statedb.StopPrefetcher()
|
statedb.StopPrefetcher()
|
||||||
return it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
|
blockExecutionTotalTimer.UpdateSince(pstart)
|
||||||
|
|
||||||
ptime := time.Since(pstart)
|
ptime := time.Since(pstart)
|
||||||
|
|
||||||
// Validate the state using the default validator
|
// Validate the state using the default validator
|
||||||
@@ -2283,6 +2284,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
|||||||
statedb.StopPrefetcher()
|
statedb.StopPrefetcher()
|
||||||
return it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
|
blockValidationTotalTimer.UpdateSince(vstart)
|
||||||
|
|
||||||
vtime := time.Since(vstart)
|
vtime := time.Since(vstart)
|
||||||
proctime := time.Since(start) // processing + validation
|
proctime := time.Since(start) // processing + validation
|
||||||
|
|
||||||
@@ -2311,11 +2314,12 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
|||||||
// Don't set the head, only insert the block
|
// Don't set the head, only insert the block
|
||||||
err = bc.writeBlockWithState(block, receipts, statedb)
|
err = bc.writeBlockWithState(block, receipts, statedb)
|
||||||
} else {
|
} else {
|
||||||
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false, nil)
|
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
|
blockWriteTotalTimer.UpdateSince(wstart)
|
||||||
|
|
||||||
bc.cacheReceipts(block.Hash(), receipts, block)
|
bc.cacheReceipts(block.Hash(), receipts, block)
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn
|
|||||||
"blocks", st.processed, "txs", txs, "blobs", blobs, "mgas", float64(st.usedGas) / 1000000,
|
"blocks", st.processed, "txs", txs, "blobs", blobs, "mgas", float64(st.usedGas) / 1000000,
|
||||||
"elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps,
|
"elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps,
|
||||||
}
|
}
|
||||||
|
mGasPsGauge.Update(int64(mgasps))
|
||||||
blockInsertMgaspsGauge.Update(int64(mgasps))
|
blockInsertMgaspsGauge.Update(int64(mgasps))
|
||||||
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
|
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
|
||||||
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
||||||
|
|||||||
@@ -98,15 +98,6 @@ func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header {
|
|||||||
return bc.hc.GetHeaderByHash(hash)
|
return bc.hc.GetHeaderByHash(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVerifiedBlockByHash retrieves the header of a verified block, it may be only in memory.
|
|
||||||
func (bc *BlockChain) GetVerifiedBlockByHash(hash common.Hash) *types.Header {
|
|
||||||
highestVerifiedBlock := bc.highestVerifiedBlock.Load()
|
|
||||||
if highestVerifiedBlock != nil && highestVerifiedBlock.Hash() == hash {
|
|
||||||
return highestVerifiedBlock
|
|
||||||
}
|
|
||||||
return bc.hc.GetHeaderByHash(hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHeaderByNumber retrieves a block header from the database by number,
|
// GetHeaderByNumber retrieves a block header from the database by number,
|
||||||
// caching it (associated with its hash) if found.
|
// caching it (associated with its hash) if found.
|
||||||
func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
|
func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
|
||||||
@@ -495,11 +486,6 @@ func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Su
|
|||||||
return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
|
return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubscribeHighestVerifiedBlockEvent registers a subscription of HighestVerifiedBlockEvent.
|
|
||||||
func (bc *BlockChain) SubscribeHighestVerifiedHeaderEvent(ch chan<- HighestVerifiedBlockEvent) event.Subscription {
|
|
||||||
return bc.scope.Track(bc.highestVerifiedBlockFeed.Subscribe(ch))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubscribeChainBlockEvent registers a subscription of ChainBlockEvent.
|
// SubscribeChainBlockEvent registers a subscription of ChainBlockEvent.
|
||||||
func (bc *BlockChain) SubscribeChainBlockEvent(ch chan<- ChainHeadEvent) event.Subscription {
|
func (bc *BlockChain) SubscribeChainBlockEvent(ch chan<- ChainHeadEvent) event.Subscription {
|
||||||
return bc.scope.Track(bc.chainBlockFeed.Subscribe(ch))
|
return bc.scope.Track(bc.chainBlockFeed.Subscribe(ch))
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi
|
|||||||
if cm.config.Parlia != nil {
|
if cm.config.Parlia != nil {
|
||||||
header.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
header.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
||||||
}
|
}
|
||||||
if cm.config.Parlia == nil || cm.config.IsBohr(header.Number, header.Time) {
|
if cm.config.Parlia == nil {
|
||||||
header.ParentBeaconRoot = new(common.Hash)
|
header.ParentBeaconRoot = new(common.Hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -621,10 +621,6 @@ func (cm *chainMaker) GetHighestVerifiedHeader() *types.Header {
|
|||||||
panic("not supported")
|
panic("not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *chainMaker) GetVerifiedBlockByHash(hash common.Hash) *types.Header {
|
|
||||||
return cm.GetHeaderByHash(hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cm *chainMaker) ChasingHead() *types.Header {
|
func (cm *chainMaker) ChasingHead() *types.Header {
|
||||||
panic("not supported")
|
panic("not supported")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -365,10 +365,6 @@ func (r *mockDAHeaderReader) GetHighestVerifiedHeader() *types.Header {
|
|||||||
panic("not supported")
|
panic("not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *mockDAHeaderReader) GetVerifiedBlockByHash(hash common.Hash) *types.Header {
|
|
||||||
panic("not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
func createMockDATx(config *params.ChainConfig, sidecar *types.BlobTxSidecar) *types.Transaction {
|
func createMockDATx(config *params.ChainConfig, sidecar *types.BlobTxSidecar) *types.Transaction {
|
||||||
if sidecar == nil {
|
if sidecar == nil {
|
||||||
tx := &types.DynamicFeeTx{
|
tx := &types.DynamicFeeTx{
|
||||||
|
|||||||
@@ -27,10 +27,7 @@ type NewTxsEvent struct{ Txs []*types.Transaction }
|
|||||||
// ReannoTxsEvent is posted when a batch of local pending transactions exceed a specified duration.
|
// ReannoTxsEvent is posted when a batch of local pending transactions exceed a specified duration.
|
||||||
type ReannoTxsEvent struct{ Txs []*types.Transaction }
|
type ReannoTxsEvent struct{ Txs []*types.Transaction }
|
||||||
|
|
||||||
// NewSealedBlockEvent is posted when a block has been sealed.
|
// NewMinedBlockEvent is posted when a block has been imported.
|
||||||
type NewSealedBlockEvent struct{ Block *types.Block }
|
|
||||||
|
|
||||||
// NewMinedBlockEvent is posted when a block has been mined.
|
|
||||||
type NewMinedBlockEvent struct{ Block *types.Block }
|
type NewMinedBlockEvent struct{ Block *types.Block }
|
||||||
|
|
||||||
// RemovedLogsEvent is posted when a reorg happens
|
// RemovedLogsEvent is posted when a reorg happens
|
||||||
@@ -53,5 +50,3 @@ type ChainSideEvent struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ChainHeadEvent struct{ Block *types.Block }
|
type ChainHeadEvent struct{ Block *types.Block }
|
||||||
|
|
||||||
type HighestVerifiedBlockEvent struct{ Header *types.Header }
|
|
||||||
|
|||||||
@@ -121,12 +121,9 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (b
|
|||||||
if f.preserve != nil {
|
if f.preserve != nil {
|
||||||
currentPreserve, externPreserve = f.preserve(current), f.preserve(extern)
|
currentPreserve, externPreserve = f.preserve(current), f.preserve(extern)
|
||||||
}
|
}
|
||||||
doubleSign := (extern.Coinbase == current.Coinbase)
|
|
||||||
reorg = !currentPreserve && (externPreserve ||
|
reorg = !currentPreserve && (externPreserve ||
|
||||||
extern.Time < current.Time ||
|
extern.Time < current.Time ||
|
||||||
extern.Time == current.Time &&
|
extern.Time == current.Time && f.rand.Float64() < 0.5)
|
||||||
((doubleSign && extern.Hash().Cmp(current.Hash()) < 0) ||
|
|
||||||
(!doubleSign && f.rand.Float64() < 0.5)))
|
|
||||||
}
|
}
|
||||||
return reorg, nil
|
return reorg, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ func (g *Genesis) ToBlock() *types.Block {
|
|||||||
// EIP-4788: The parentBeaconBlockRoot of the genesis block is always
|
// EIP-4788: The parentBeaconBlockRoot of the genesis block is always
|
||||||
// the zero hash. This is because the genesis block does not have a parent
|
// the zero hash. This is because the genesis block does not have a parent
|
||||||
// by definition.
|
// by definition.
|
||||||
if conf.Parlia == nil || conf.IsBohr(num, g.Timestamp) {
|
if conf.Parlia == nil {
|
||||||
head.ParentBeaconRoot = new(common.Hash)
|
head.ParentBeaconRoot = new(common.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -436,10 +436,6 @@ func (hc *HeaderChain) GetHighestVerifiedHeader() *types.Header {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *HeaderChain) GetVerifiedBlockByHash(hash common.Hash) *types.Header {
|
|
||||||
return hc.GetHeaderByHash(hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hc *HeaderChain) ChasingHead() *types.Header {
|
func (hc *HeaderChain) ChasingHead() *types.Header {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,4 +34,7 @@ var (
|
|||||||
slotDeletionCount = metrics.NewRegisteredMeter("state/delete/storage/slot", nil)
|
slotDeletionCount = metrics.NewRegisteredMeter("state/delete/storage/slot", nil)
|
||||||
slotDeletionSize = metrics.NewRegisteredMeter("state/delete/storage/size", nil)
|
slotDeletionSize = metrics.NewRegisteredMeter("state/delete/storage/size", nil)
|
||||||
slotDeletionSkip = metrics.NewRegisteredGauge("state/delete/storage/skip", nil)
|
slotDeletionSkip = metrics.NewRegisteredGauge("state/delete/storage/skip", nil)
|
||||||
|
|
||||||
|
accountIntermediateRootTimer = metrics.NewRegisteredTimer("state/account/intermediate/root/time", nil)
|
||||||
|
storageIntermediateRootTimer = metrics.NewRegisteredTimer("state/storage/intermediate/root/time", nil)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -286,6 +286,13 @@ func (dl *diffLayer) Stale() bool {
|
|||||||
// Account directly retrieves the account associated with a particular hash in
|
// Account directly retrieves the account associated with a particular hash in
|
||||||
// the snapshot slim data format.
|
// the snapshot slim data format.
|
||||||
func (dl *diffLayer) Account(hash common.Hash) (*types.SlimAccount, error) {
|
func (dl *diffLayer) Account(hash common.Hash) (*types.SlimAccount, error) {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
snapGetTimer.UpdateSince(start)
|
||||||
|
snapGetQPS.Mark(1)
|
||||||
|
snapGetAccountTimer.UpdateSince(start)
|
||||||
|
snapGetAccountQPS.Mark(1)
|
||||||
|
}(time.Now())
|
||||||
|
|
||||||
data, err := dl.AccountRLP(hash)
|
data, err := dl.AccountRLP(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -394,6 +401,13 @@ func (dl *diffLayer) accountRLP(hash common.Hash, depth int) ([]byte, error) {
|
|||||||
//
|
//
|
||||||
// Note the returned slot is not a copy, please don't modify it.
|
// Note the returned slot is not a copy, please don't modify it.
|
||||||
func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, error) {
|
func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, error) {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
snapGetTimer.UpdateSince(start)
|
||||||
|
snapGetQPS.Mark(1)
|
||||||
|
snapGetStorageTimer.UpdateSince(start)
|
||||||
|
snapGetStorageQPS.Mark(1)
|
||||||
|
}(time.Now())
|
||||||
|
|
||||||
// Check the bloom filter first whether there's even a point in reaching into
|
// Check the bloom filter first whether there's even a point in reaching into
|
||||||
// all the maps in all the layers below
|
// all the maps in all the layers below
|
||||||
dl.lock.RLock()
|
dl.lock.RLock()
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package snapshot
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/fastcache"
|
"github.com/VictoriaMetrics/fastcache"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@@ -136,7 +137,12 @@ func (dl *diskLayer) AccountRLP(hash common.Hash) ([]byte, error) {
|
|||||||
return blob, nil
|
return blob, nil
|
||||||
}
|
}
|
||||||
// Cache doesn't contain account, pull from disk and cache for later
|
// Cache doesn't contain account, pull from disk and cache for later
|
||||||
|
// TODO:
|
||||||
|
snapNodeQPS.Mark(1)
|
||||||
|
startLoadSnapNode := time.Now()
|
||||||
blob := rawdb.ReadAccountSnapshot(dl.diskdb, hash)
|
blob := rawdb.ReadAccountSnapshot(dl.diskdb, hash)
|
||||||
|
snapNodeTime.Mark(time.Since(startLoadSnapNode).Nanoseconds())
|
||||||
|
|
||||||
dl.cache.Set(hash[:], blob)
|
dl.cache.Set(hash[:], blob)
|
||||||
|
|
||||||
snapshotCleanAccountMissMeter.Mark(1)
|
snapshotCleanAccountMissMeter.Mark(1)
|
||||||
@@ -176,7 +182,11 @@ func (dl *diskLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
|
|||||||
return blob, nil
|
return blob, nil
|
||||||
}
|
}
|
||||||
// Cache doesn't contain storage slot, pull from disk and cache for later
|
// Cache doesn't contain storage slot, pull from disk and cache for later
|
||||||
|
// TODO:
|
||||||
|
snapNodeQPS.Mark(1)
|
||||||
|
startLoadSnapNode := time.Now()
|
||||||
blob := rawdb.ReadStorageSnapshot(dl.diskdb, accountHash, storageHash)
|
blob := rawdb.ReadStorageSnapshot(dl.diskdb, accountHash, storageHash)
|
||||||
|
snapNodeTime.Mark(time.Since(startLoadSnapNode).Nanoseconds())
|
||||||
dl.cache.Set(key, blob)
|
dl.cache.Set(key, blob)
|
||||||
|
|
||||||
snapshotCleanStorageMissMeter.Mark(1)
|
snapshotCleanStorageMissMeter.Mark(1)
|
||||||
|
|||||||
@@ -50,4 +50,15 @@ var (
|
|||||||
snapStorageWriteCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/write", nil)
|
snapStorageWriteCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/write", nil)
|
||||||
// snapStorageCleanCounter measures time spent on deleting storages
|
// snapStorageCleanCounter measures time spent on deleting storages
|
||||||
snapStorageCleanCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/clean", nil)
|
snapStorageCleanCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/clean", nil)
|
||||||
|
|
||||||
|
snapNodeQPS = metrics.NewRegisteredMeter("pbss/snap/node/qps", nil)
|
||||||
|
snapNodeTime = metrics.NewRegisteredMeter("pbss/snap/node/time", nil)
|
||||||
|
|
||||||
|
snapGetTimer = metrics.NewRegisteredTimer("snap/get/time", nil)
|
||||||
|
snapGetQPS = metrics.NewRegisteredMeter("snap/get/qps", nil)
|
||||||
|
|
||||||
|
snapGetAccountTimer = metrics.NewRegisteredTimer("snap/account/get/time", nil)
|
||||||
|
snapGetAccountQPS = metrics.NewRegisteredMeter("snap/account/get/qps", nil)
|
||||||
|
snapGetStorageTimer = metrics.NewRegisteredTimer("snap/storage/get/time", nil)
|
||||||
|
snapGetStorageQPS = metrics.NewRegisteredMeter("snap/storage/get/qps", nil)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -223,6 +223,14 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
|||||||
return common.Hash{}
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
// If no live objects are available, attempt to use snapshots
|
// If no live objects are available, attempt to use snapshots
|
||||||
|
|
||||||
|
defer func(start time.Time) {
|
||||||
|
stateDBGetTimer.UpdateSince(start)
|
||||||
|
stateDBGetQPS.Mark(1)
|
||||||
|
stateDBGetStorageTimer.UpdateSince(start)
|
||||||
|
stateDBGetStorageQPS.Mark(1)
|
||||||
|
}(time.Now())
|
||||||
|
|
||||||
var (
|
var (
|
||||||
enc []byte
|
enc []byte
|
||||||
err error
|
err error
|
||||||
|
|||||||
@@ -54,6 +54,16 @@ type revision struct {
|
|||||||
journalIndex int
|
journalIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
stateDBGetTimer = metrics.NewRegisteredTimer("statedb/get/time", nil)
|
||||||
|
stateDBGetQPS = metrics.NewRegisteredMeter("statedb/get/qps", nil)
|
||||||
|
|
||||||
|
stateDBGetAccountTimer = metrics.NewRegisteredTimer("statedb/account/get/time", nil)
|
||||||
|
stateDBGetAccountQPS = metrics.NewRegisteredMeter("statedb/account/get/qps", nil)
|
||||||
|
stateDBGetStorageTimer = metrics.NewRegisteredTimer("statedb/storage/get/time", nil)
|
||||||
|
stateDBGetStorageQPS = metrics.NewRegisteredMeter("statedb/storage/get/qps", nil)
|
||||||
|
)
|
||||||
|
|
||||||
// StateDB structs within the ethereum protocol are used to store anything
|
// StateDB structs within the ethereum protocol are used to store anything
|
||||||
// within the merkle trie. StateDBs take care of caching and storing
|
// within the merkle trie. StateDBs take care of caching and storing
|
||||||
// nested states. It's the general query interface to retrieve:
|
// nested states. It's the general query interface to retrieve:
|
||||||
@@ -166,7 +176,7 @@ func NewWithSharedPool(root common.Hash, db Database, snaps *snapshot.Tree) (*St
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
statedb.storagePool = NewStoragePool()
|
//statedb.storagePool = NewStoragePool()
|
||||||
return statedb, nil
|
return statedb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,6 +726,14 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
|
|||||||
if obj := s.stateObjects[addr]; obj != nil {
|
if obj := s.stateObjects[addr]; obj != nil {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func(start time.Time) {
|
||||||
|
stateDBGetTimer.UpdateSince(start)
|
||||||
|
stateDBGetQPS.Mark(1)
|
||||||
|
stateDBGetAccountTimer.UpdateSince(start)
|
||||||
|
stateDBGetAccountQPS.Mark(1)
|
||||||
|
}(time.Now())
|
||||||
|
|
||||||
// If no live objects are available, attempt to use snapshots
|
// If no live objects are available, attempt to use snapshots
|
||||||
var data *types.StateAccount
|
var data *types.StateAccount
|
||||||
if s.snap != nil {
|
if s.snap != nil {
|
||||||
@@ -1147,6 +1165,10 @@ func (s *StateDB) populateSnapStorage(obj *stateObject) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) AccountsIntermediateRoot() {
|
func (s *StateDB) AccountsIntermediateRoot() {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
storageIntermediateRootTimer.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
|
|
||||||
tasks := make(chan func())
|
tasks := make(chan func())
|
||||||
finishCh := make(chan struct{})
|
finishCh := make(chan struct{})
|
||||||
defer close(finishCh)
|
defer close(finishCh)
|
||||||
@@ -1191,6 +1213,9 @@ func (s *StateDB) AccountsIntermediateRoot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) StateIntermediateRoot() common.Hash {
|
func (s *StateDB) StateIntermediateRoot() common.Hash {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
accountIntermediateRootTimer.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
// If there was a trie prefetcher operating, it gets aborted and irrevocably
|
// If there was a trie prefetcher operating, it gets aborted and irrevocably
|
||||||
// modified after we start retrieving tries. Remove it from the statedb after
|
// modified after we start retrieving tries. Remove it from the statedb after
|
||||||
// this round of use.
|
// this round of use.
|
||||||
|
|||||||
@@ -673,7 +673,10 @@ type DiffAccountsInBlock struct {
|
|||||||
Transactions []DiffAccountsInTx
|
Transactions []DiffAccountsInTx
|
||||||
}
|
}
|
||||||
|
|
||||||
var extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
var (
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
// SealHash returns the hash of a block prior to it being sealed.
|
// SealHash returns the hash of a block prior to it being sealed.
|
||||||
func SealHash(header *Header, chainId *big.Int) (hash common.Hash) {
|
func SealHash(header *Header, chainId *big.Int) (hash common.Hash) {
|
||||||
@@ -684,33 +687,7 @@ func SealHash(header *Header, chainId *big.Int) (hash common.Hash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) {
|
func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) {
|
||||||
var err error
|
err := rlp.Encode(w, []interface{}{
|
||||||
if header.ParentBeaconRoot != nil && *header.ParentBeaconRoot == (common.Hash{}) {
|
|
||||||
err = rlp.Encode(w, []interface{}{
|
|
||||||
chainId,
|
|
||||||
header.ParentHash,
|
|
||||||
header.UncleHash,
|
|
||||||
header.Coinbase,
|
|
||||||
header.Root,
|
|
||||||
header.TxHash,
|
|
||||||
header.ReceiptHash,
|
|
||||||
header.Bloom,
|
|
||||||
header.Difficulty,
|
|
||||||
header.Number,
|
|
||||||
header.GasLimit,
|
|
||||||
header.GasUsed,
|
|
||||||
header.Time,
|
|
||||||
header.Extra[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader
|
|
||||||
header.MixDigest,
|
|
||||||
header.Nonce,
|
|
||||||
header.BaseFee,
|
|
||||||
header.WithdrawalsHash,
|
|
||||||
header.BlobGasUsed,
|
|
||||||
header.ExcessBlobGas,
|
|
||||||
header.ParentBeaconRoot,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
err = rlp.Encode(w, []interface{}{
|
|
||||||
chainId,
|
chainId,
|
||||||
header.ParentHash,
|
header.ParentHash,
|
||||||
header.UncleHash,
|
header.UncleHash,
|
||||||
@@ -728,7 +705,30 @@ func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) {
|
|||||||
header.MixDigest,
|
header.MixDigest,
|
||||||
header.Nonce,
|
header.Nonce,
|
||||||
})
|
})
|
||||||
}
|
if err != nil {
|
||||||
|
panic("can't encode: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodeSigHeaderWithoutVoteAttestation(w io.Writer, header *Header, chainId *big.Int) {
|
||||||
|
err := rlp.Encode(w, []interface{}{
|
||||||
|
chainId,
|
||||||
|
header.ParentHash,
|
||||||
|
header.UncleHash,
|
||||||
|
header.Coinbase,
|
||||||
|
header.Root,
|
||||||
|
header.TxHash,
|
||||||
|
header.ReceiptHash,
|
||||||
|
header.Bloom,
|
||||||
|
header.Difficulty,
|
||||||
|
header.Number,
|
||||||
|
header.GasLimit,
|
||||||
|
header.GasUsed,
|
||||||
|
header.Time,
|
||||||
|
header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
|
||||||
|
header.MixDigest,
|
||||||
|
header.Nonce,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("can't encode: " + err.Error())
|
panic("can't encode: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ type VoteManager struct {
|
|||||||
|
|
||||||
chain *core.BlockChain
|
chain *core.BlockChain
|
||||||
|
|
||||||
highestVerifiedBlockCh chan core.HighestVerifiedBlockEvent
|
chainHeadCh chan core.ChainHeadEvent
|
||||||
highestVerifiedBlockSub event.Subscription
|
chainHeadSub event.Subscription
|
||||||
|
|
||||||
// used for backup validators to sync votes from corresponding mining validator
|
// used for backup validators to sync votes from corresponding mining validator
|
||||||
syncVoteCh chan core.NewVoteEvent
|
syncVoteCh chan core.NewVoteEvent
|
||||||
@@ -51,7 +51,7 @@ func NewVoteManager(eth Backend, chain *core.BlockChain, pool *VotePool, journal
|
|||||||
voteManager := &VoteManager{
|
voteManager := &VoteManager{
|
||||||
eth: eth,
|
eth: eth,
|
||||||
chain: chain,
|
chain: chain,
|
||||||
highestVerifiedBlockCh: make(chan core.HighestVerifiedBlockEvent, highestVerifiedBlockChanSize),
|
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
||||||
syncVoteCh: make(chan core.NewVoteEvent, voteBufferForPut),
|
syncVoteCh: make(chan core.NewVoteEvent, voteBufferForPut),
|
||||||
pool: pool,
|
pool: pool,
|
||||||
engine: engine,
|
engine: engine,
|
||||||
@@ -74,7 +74,7 @@ func NewVoteManager(eth Backend, chain *core.BlockChain, pool *VotePool, journal
|
|||||||
voteManager.journal = voteJournal
|
voteManager.journal = voteJournal
|
||||||
|
|
||||||
// Subscribe to chain head event.
|
// Subscribe to chain head event.
|
||||||
voteManager.highestVerifiedBlockSub = voteManager.chain.SubscribeHighestVerifiedHeaderEvent(voteManager.highestVerifiedBlockCh)
|
voteManager.chainHeadSub = voteManager.chain.SubscribeChainHeadEvent(voteManager.chainHeadCh)
|
||||||
voteManager.syncVoteSub = voteManager.pool.SubscribeNewVoteEvent(voteManager.syncVoteCh)
|
voteManager.syncVoteSub = voteManager.pool.SubscribeNewVoteEvent(voteManager.syncVoteCh)
|
||||||
|
|
||||||
go voteManager.loop()
|
go voteManager.loop()
|
||||||
@@ -84,7 +84,7 @@ func NewVoteManager(eth Backend, chain *core.BlockChain, pool *VotePool, journal
|
|||||||
|
|
||||||
func (voteManager *VoteManager) loop() {
|
func (voteManager *VoteManager) loop() {
|
||||||
log.Debug("vote manager routine loop started")
|
log.Debug("vote manager routine loop started")
|
||||||
defer voteManager.highestVerifiedBlockSub.Unsubscribe()
|
defer voteManager.chainHeadSub.Unsubscribe()
|
||||||
defer voteManager.syncVoteSub.Unsubscribe()
|
defer voteManager.syncVoteSub.Unsubscribe()
|
||||||
|
|
||||||
events := voteManager.eth.EventMux().Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{})
|
events := voteManager.eth.EventMux().Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{})
|
||||||
@@ -119,7 +119,7 @@ func (voteManager *VoteManager) loop() {
|
|||||||
log.Debug("downloader is in DoneEvent mode, set the startVote flag to true")
|
log.Debug("downloader is in DoneEvent mode, set the startVote flag to true")
|
||||||
startVote = true
|
startVote = true
|
||||||
}
|
}
|
||||||
case cHead := <-voteManager.highestVerifiedBlockCh:
|
case cHead := <-voteManager.chainHeadCh:
|
||||||
if !startVote {
|
if !startVote {
|
||||||
log.Debug("startVote flag is false, continue")
|
log.Debug("startVote flag is false, continue")
|
||||||
continue
|
continue
|
||||||
@@ -135,12 +135,12 @@ func (voteManager *VoteManager) loop() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if cHead.Header == nil {
|
if cHead.Block == nil {
|
||||||
log.Debug("cHead.Header is nil, continue")
|
log.Debug("cHead.Block is nil, continue")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
curHead := cHead.Header
|
curHead := cHead.Block.Header()
|
||||||
if p, ok := voteManager.engine.(*parlia.Parlia); ok {
|
if p, ok := voteManager.engine.(*parlia.Parlia); ok {
|
||||||
nextBlockMinedTime := time.Unix(int64((curHead.Time + p.Period())), 0)
|
nextBlockMinedTime := time.Unix(int64((curHead.Time + p.Period())), 0)
|
||||||
timeForBroadcast := 50 * time.Millisecond // enough to broadcast a vote
|
timeForBroadcast := 50 * time.Millisecond // enough to broadcast a vote
|
||||||
@@ -217,7 +217,7 @@ func (voteManager *VoteManager) loop() {
|
|||||||
case <-voteManager.syncVoteSub.Err():
|
case <-voteManager.syncVoteSub.Err():
|
||||||
log.Debug("voteManager subscribed votes failed")
|
log.Debug("voteManager subscribed votes failed")
|
||||||
return
|
return
|
||||||
case <-voteManager.highestVerifiedBlockSub.Err():
|
case <-voteManager.chainHeadSub.Err():
|
||||||
log.Debug("voteManager subscribed chainHead failed")
|
log.Debug("voteManager subscribed chainHead failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const (
|
|||||||
lowerLimitOfVoteBlockNumber = 256
|
lowerLimitOfVoteBlockNumber = 256
|
||||||
upperLimitOfVoteBlockNumber = 11 // refer to fetcher.maxUncleDist
|
upperLimitOfVoteBlockNumber = 11 // refer to fetcher.maxUncleDist
|
||||||
|
|
||||||
highestVerifiedBlockChanSize = 10 // highestVerifiedBlockChanSize is the size of channel listening to HighestVerifiedBlockEvent.
|
chainHeadChanSize = 10 // chainHeadChanSize is the size of channel listening to ChainHeadEvent.
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -57,8 +57,8 @@ type VotePool struct {
|
|||||||
curVotesPq *votesPriorityQueue
|
curVotesPq *votesPriorityQueue
|
||||||
futureVotesPq *votesPriorityQueue
|
futureVotesPq *votesPriorityQueue
|
||||||
|
|
||||||
highestVerifiedBlockCh chan core.HighestVerifiedBlockEvent
|
chainHeadCh chan core.ChainHeadEvent
|
||||||
highestVerifiedBlockSub event.Subscription
|
chainHeadSub event.Subscription
|
||||||
|
|
||||||
votesCh chan *types.VoteEnvelope
|
votesCh chan *types.VoteEnvelope
|
||||||
|
|
||||||
@@ -75,13 +75,13 @@ func NewVotePool(chain *core.BlockChain, engine consensus.PoSA) *VotePool {
|
|||||||
futureVotes: make(map[common.Hash]*VoteBox),
|
futureVotes: make(map[common.Hash]*VoteBox),
|
||||||
curVotesPq: &votesPriorityQueue{},
|
curVotesPq: &votesPriorityQueue{},
|
||||||
futureVotesPq: &votesPriorityQueue{},
|
futureVotesPq: &votesPriorityQueue{},
|
||||||
highestVerifiedBlockCh: make(chan core.HighestVerifiedBlockEvent, highestVerifiedBlockChanSize),
|
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
||||||
votesCh: make(chan *types.VoteEnvelope, voteBufferForPut),
|
votesCh: make(chan *types.VoteEnvelope, voteBufferForPut),
|
||||||
engine: engine,
|
engine: engine,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subscribe events from blockchain and start the main event loop.
|
// Subscribe events from blockchain and start the main event loop.
|
||||||
votePool.highestVerifiedBlockSub = votePool.chain.SubscribeHighestVerifiedHeaderEvent(votePool.highestVerifiedBlockCh)
|
votePool.chainHeadSub = votePool.chain.SubscribeChainHeadEvent(votePool.chainHeadCh)
|
||||||
|
|
||||||
go votePool.loop()
|
go votePool.loop()
|
||||||
return votePool
|
return votePool
|
||||||
@@ -89,18 +89,18 @@ func NewVotePool(chain *core.BlockChain, engine consensus.PoSA) *VotePool {
|
|||||||
|
|
||||||
// loop is the vote pool's main even loop, waiting for and reacting to outside blockchain events and votes channel event.
|
// loop is the vote pool's main even loop, waiting for and reacting to outside blockchain events and votes channel event.
|
||||||
func (pool *VotePool) loop() {
|
func (pool *VotePool) loop() {
|
||||||
defer pool.highestVerifiedBlockSub.Unsubscribe()
|
defer pool.chainHeadSub.Unsubscribe()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
// Handle ChainHeadEvent.
|
// Handle ChainHeadEvent.
|
||||||
case ev := <-pool.highestVerifiedBlockCh:
|
case ev := <-pool.chainHeadCh:
|
||||||
if ev.Header != nil {
|
if ev.Block != nil {
|
||||||
latestBlockNumber := ev.Header.Number.Uint64()
|
latestBlockNumber := ev.Block.NumberU64()
|
||||||
pool.prune(latestBlockNumber)
|
pool.prune(latestBlockNumber)
|
||||||
pool.transferVotesFromFutureToCur(ev.Header)
|
pool.transferVotesFromFutureToCur(ev.Block.Header())
|
||||||
}
|
}
|
||||||
case <-pool.highestVerifiedBlockSub.Err():
|
case <-pool.chainHeadSub.Err():
|
||||||
return
|
return
|
||||||
|
|
||||||
// Handle votes channel and put the vote into vote pool.
|
// Handle votes channel and put the vote into vote pool.
|
||||||
@@ -135,7 +135,7 @@ func (pool *VotePool) putIntoVotePool(vote *types.VoteEnvelope) bool {
|
|||||||
var votesPq *votesPriorityQueue
|
var votesPq *votesPriorityQueue
|
||||||
isFutureVote := false
|
isFutureVote := false
|
||||||
|
|
||||||
voteBlock := pool.chain.GetVerifiedBlockByHash(targetHash)
|
voteBlock := pool.chain.GetHeaderByHash(targetHash)
|
||||||
if voteBlock == nil {
|
if voteBlock == nil {
|
||||||
votes = pool.futureVotes
|
votes = pool.futureVotes
|
||||||
votesPq = pool.futureVotesPq
|
votesPq = pool.futureVotesPq
|
||||||
@@ -226,7 +226,7 @@ func (pool *VotePool) transferVotesFromFutureToCur(latestBlockHeader *types.Head
|
|||||||
futurePqBuffer := make([]*types.VoteData, 0)
|
futurePqBuffer := make([]*types.VoteData, 0)
|
||||||
for futurePq.Len() > 0 && futurePq.Peek().TargetNumber <= latestBlockNumber {
|
for futurePq.Len() > 0 && futurePq.Peek().TargetNumber <= latestBlockNumber {
|
||||||
blockHash := futurePq.Peek().TargetHash
|
blockHash := futurePq.Peek().TargetHash
|
||||||
header := pool.chain.GetVerifiedBlockByHash(blockHash)
|
header := pool.chain.GetHeaderByHash(blockHash)
|
||||||
if header == nil {
|
if header == nil {
|
||||||
// Put into pq buffer used for later put again into futurePq
|
// Put into pq buffer used for later put again into futurePq
|
||||||
futurePqBuffer = append(futurePqBuffer, heap.Pop(futurePq).(*types.VoteData))
|
futurePqBuffer = append(futurePqBuffer, heap.Pop(futurePq).(*types.VoteData))
|
||||||
|
|||||||
@@ -729,7 +729,7 @@ func (h *handler) Start(maxPeers int, maxPeersPerIP int) {
|
|||||||
|
|
||||||
// broadcast mined blocks
|
// broadcast mined blocks
|
||||||
h.wg.Add(1)
|
h.wg.Add(1)
|
||||||
h.minedBlockSub = h.eventMux.Subscribe(core.NewMinedBlockEvent{}, core.NewSealedBlockEvent{})
|
h.minedBlockSub = h.eventMux.Subscribe(core.NewMinedBlockEvent{})
|
||||||
go h.minedBroadcastLoop()
|
go h.minedBroadcastLoop()
|
||||||
|
|
||||||
// start sync handlers
|
// start sync handlers
|
||||||
@@ -946,9 +946,8 @@ func (h *handler) minedBroadcastLoop() {
|
|||||||
if obj == nil {
|
if obj == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev, ok := obj.Data.(core.NewSealedBlockEvent); ok {
|
if ev, ok := obj.Data.(core.NewMinedBlockEvent); ok {
|
||||||
h.BroadcastBlock(ev.Block, true) // Propagate block to peers
|
h.BroadcastBlock(ev.Block, true) // First propagate block to peers
|
||||||
} else if ev, ok := obj.Data.(core.NewMinedBlockEvent); ok {
|
|
||||||
h.BroadcastBlock(ev.Block, false) // Only then announce to the rest
|
h.BroadcastBlock(ev.Block, false) // Only then announce to the rest
|
||||||
}
|
}
|
||||||
case <-h.stopCh:
|
case <-h.stopCh:
|
||||||
|
|||||||
6
go.mod
6
go.mod
@@ -24,7 +24,7 @@ require (
|
|||||||
github.com/deckarep/golang-set/v2 v2.5.0
|
github.com/deckarep/golang-set/v2 v2.5.0
|
||||||
github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127
|
github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127
|
||||||
github.com/ethereum/c-kzg-4844 v0.4.0
|
github.com/ethereum/c-kzg-4844 v0.4.0
|
||||||
github.com/fatih/color v1.14.1
|
github.com/fatih/color v1.16.0
|
||||||
github.com/fatih/structs v1.1.0
|
github.com/fatih/structs v1.1.0
|
||||||
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e
|
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e
|
||||||
github.com/fjl/memsize v0.0.2
|
github.com/fjl/memsize v0.0.2
|
||||||
@@ -82,7 +82,7 @@ require (
|
|||||||
golang.org/x/crypto v0.21.0
|
golang.org/x/crypto v0.21.0
|
||||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
|
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
|
||||||
golang.org/x/sync v0.6.0
|
golang.org/x/sync v0.6.0
|
||||||
golang.org/x/sys v0.18.0
|
golang.org/x/sys v0.20.0
|
||||||
golang.org/x/text v0.14.0
|
golang.org/x/text v0.14.0
|
||||||
golang.org/x/time v0.5.0
|
golang.org/x/time v0.5.0
|
||||||
golang.org/x/tools v0.18.0
|
golang.org/x/tools v0.18.0
|
||||||
@@ -159,7 +159,7 @@ require (
|
|||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 // indirect
|
||||||
github.com/gtank/merlin v0.1.1 // indirect
|
github.com/gtank/merlin v0.1.1 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
|
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
|
||||||
github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e // indirect
|
github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e // indirect
|
||||||
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
|
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
|
||||||
|
|||||||
18
go.sum
18
go.sum
@@ -326,8 +326,9 @@ github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R
|
|||||||
github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
|
github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
|
||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
|
||||||
@@ -580,14 +581,13 @@ github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn
|
|||||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
||||||
github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
|
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||||
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
|
||||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA=
|
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
||||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||||
@@ -1503,8 +1503,8 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
|||||||
@@ -665,7 +665,7 @@ func (w *worker) resultLoop() {
|
|||||||
// Commit block and state to database.
|
// Commit block and state to database.
|
||||||
task.state.SetExpectedStateRoot(block.Root())
|
task.state.SetExpectedStateRoot(block.Root())
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
status, err := w.chain.WriteBlockAndSetHead(block, receipts, logs, task.state, true, w.mux)
|
status, err := w.chain.WriteBlockAndSetHead(block, receipts, logs, task.state, true)
|
||||||
if status != core.CanonStatTy {
|
if status != core.CanonStatTy {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed writing block to chain", "err", err, "status", status)
|
log.Error("Failed writing block to chain", "err", err, "status", status)
|
||||||
@@ -1032,8 +1032,6 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
|
|||||||
}
|
}
|
||||||
if w.chainConfig.Parlia == nil {
|
if w.chainConfig.Parlia == nil {
|
||||||
header.ParentBeaconRoot = genParams.beaconRoot
|
header.ParentBeaconRoot = genParams.beaconRoot
|
||||||
} else if w.chainConfig.IsBohr(header.Number, header.Time) {
|
|
||||||
header.ParentBeaconRoot = new(common.Hash)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Could potentially happen if starting to mine in an odd state.
|
// Could potentially happen if starting to mine in an odd state.
|
||||||
|
|||||||
@@ -17,13 +17,48 @@
|
|||||||
package trie
|
package trie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
"github.com/ethereum/go-ethereum/triedb/database"
|
"github.com/ethereum/go-ethereum/triedb/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
StateTreeOpenQPS = metrics.NewRegisteredMeter("state/tree/open/qps", nil)
|
||||||
|
StateTreeOpenTime = metrics.NewRegisteredTimer("state/tree/open/time", nil)
|
||||||
|
|
||||||
|
StateTreeGetQPS = metrics.NewRegisteredMeter("state/tree/get/qps", nil)
|
||||||
|
StateTreeGetTime = metrics.NewRegisteredTimer("state/tree/get/time", nil)
|
||||||
|
StateAccountTreeGetQPS = metrics.NewRegisteredMeter("state/tree/account/get/qps", nil)
|
||||||
|
StateAccountTreeGetTime = metrics.NewRegisteredTimer("state/tree/account/get/time", nil)
|
||||||
|
StateStorageTreeGetQPS = metrics.NewRegisteredMeter("state/tree/storage/get/qps", nil)
|
||||||
|
StateStorageTreeGetTime = metrics.NewRegisteredTimer("state/tree/storage/get/time", nil)
|
||||||
|
|
||||||
|
StateTreePutQPS = metrics.NewRegisteredMeter("state/tree/put/qps", nil)
|
||||||
|
StateTreePutTime = metrics.NewRegisteredTimer("state/tree/put/time", nil)
|
||||||
|
StateAccountTreePutQPS = metrics.NewRegisteredMeter("state/tree/account/put/qps", nil)
|
||||||
|
StateAccountTreePutTime = metrics.NewRegisteredTimer("state/tree/account/put/time", nil)
|
||||||
|
StateStorageTreePutQPS = metrics.NewRegisteredMeter("state/tree/storage/put/qps", nil)
|
||||||
|
StateStorageTreePutTime = metrics.NewRegisteredTimer("state/tree/storage/put/time", nil)
|
||||||
|
|
||||||
|
StateTreeDelQPS = metrics.NewRegisteredMeter("state/tree/del/qps", nil)
|
||||||
|
StateTreeDelTime = metrics.NewRegisteredTimer("state/tree/del/time", nil)
|
||||||
|
StateAccountTreeDelQPS = metrics.NewRegisteredMeter("state/tree/account/del/qps", nil)
|
||||||
|
StateAccountTreeDelTime = metrics.NewRegisteredTimer("state/tree/account/del/time", nil)
|
||||||
|
StateStorageTreeDelQPS = metrics.NewRegisteredMeter("state/tree/storage/del/qps", nil)
|
||||||
|
StateStorageTreeDelTime = metrics.NewRegisteredTimer("state/tree/storage/del/time", nil)
|
||||||
|
|
||||||
|
StateTreeCommitQPS = metrics.NewRegisteredMeter("state/tree/commit/qps", nil)
|
||||||
|
StateTreeCommitTime = metrics.NewRegisteredTimer("state/tree/commit/time", nil)
|
||||||
|
|
||||||
|
StateTreeCalcQPS = metrics.NewRegisteredMeter("state/tree/calc/qps", nil)
|
||||||
|
StateTreeCalcTime = metrics.NewRegisteredTimer("state/tree/calc/time", nil)
|
||||||
|
)
|
||||||
|
|
||||||
// SecureTrie is the old name of StateTrie.
|
// SecureTrie is the old name of StateTrie.
|
||||||
// Deprecated: use StateTrie.
|
// Deprecated: use StateTrie.
|
||||||
type SecureTrie = StateTrie
|
type SecureTrie = StateTrie
|
||||||
@@ -63,6 +98,11 @@ type StateTrie struct {
|
|||||||
// trie is initially empty. Otherwise, New will panic if db is nil
|
// trie is initially empty. Otherwise, New will panic if db is nil
|
||||||
// and returns MissingNodeError if the root node cannot be found.
|
// and returns MissingNodeError if the root node cannot be found.
|
||||||
func NewStateTrie(id *ID, db database.Database) (*StateTrie, error) {
|
func NewStateTrie(id *ID, db database.Database) (*StateTrie, error) {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreeOpenQPS.Mark(1)
|
||||||
|
StateTreeOpenTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
|
|
||||||
if db == nil {
|
if db == nil {
|
||||||
panic("trie.NewStateTrie called without a database")
|
panic("trie.NewStateTrie called without a database")
|
||||||
}
|
}
|
||||||
@@ -87,6 +127,12 @@ func (t *StateTrie) MustGet(key []byte) []byte {
|
|||||||
// If the specified storage slot is not in the trie, nil will be returned.
|
// If the specified storage slot is not in the trie, nil will be returned.
|
||||||
// If a trie node is not found in the database, a MissingNodeError is returned.
|
// If a trie node is not found in the database, a MissingNodeError is returned.
|
||||||
func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
|
func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreeGetQPS.Mark(1)
|
||||||
|
StateTreeGetTime.UpdateSince(start)
|
||||||
|
StateStorageTreeGetQPS.Mark(1)
|
||||||
|
StateStorageTreeGetTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
enc, err := t.trie.Get(t.hashKey(key))
|
enc, err := t.trie.Get(t.hashKey(key))
|
||||||
if err != nil || len(enc) == 0 {
|
if err != nil || len(enc) == 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -99,6 +145,12 @@ func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
|
|||||||
// If the specified account is not in the trie, nil will be returned.
|
// If the specified account is not in the trie, nil will be returned.
|
||||||
// If a trie node is not found in the database, a MissingNodeError is returned.
|
// If a trie node is not found in the database, a MissingNodeError is returned.
|
||||||
func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, error) {
|
func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, error) {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreeGetQPS.Mark(1)
|
||||||
|
StateTreeGetTime.UpdateSince(start)
|
||||||
|
StateAccountTreeGetQPS.Mark(1)
|
||||||
|
StateAccountTreeGetTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
res, err := t.trie.Get(t.hashKey(address.Bytes()))
|
res, err := t.trie.Get(t.hashKey(address.Bytes()))
|
||||||
if res == nil || err != nil {
|
if res == nil || err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -153,6 +205,12 @@ func (t *StateTrie) MustUpdate(key, value []byte) {
|
|||||||
//
|
//
|
||||||
// If a node is not found in the database, a MissingNodeError is returned.
|
// If a node is not found in the database, a MissingNodeError is returned.
|
||||||
func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
|
func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreePutQPS.Mark(1)
|
||||||
|
StateTreePutTime.UpdateSince(start)
|
||||||
|
StateStorageTreePutQPS.Mark(1)
|
||||||
|
StateStorageTreePutTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
hk := t.hashKey(key)
|
hk := t.hashKey(key)
|
||||||
v, _ := rlp.EncodeToBytes(value)
|
v, _ := rlp.EncodeToBytes(value)
|
||||||
err := t.trie.Update(hk, v)
|
err := t.trie.Update(hk, v)
|
||||||
@@ -165,6 +223,12 @@ func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
|
|||||||
|
|
||||||
// UpdateAccount will abstract the write of an account to the secure trie.
|
// UpdateAccount will abstract the write of an account to the secure trie.
|
||||||
func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount) error {
|
func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount) error {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreePutQPS.Mark(1)
|
||||||
|
StateTreePutTime.UpdateSince(start)
|
||||||
|
StateAccountTreePutQPS.Mark(1)
|
||||||
|
StateAccountTreePutTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
hk := t.hashKey(address.Bytes())
|
hk := t.hashKey(address.Bytes())
|
||||||
data, err := rlp.EncodeToBytes(acc)
|
data, err := rlp.EncodeToBytes(acc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -193,6 +257,12 @@ func (t *StateTrie) MustDelete(key []byte) {
|
|||||||
// If the specified trie node is not in the trie, nothing will be changed.
|
// If the specified trie node is not in the trie, nothing will be changed.
|
||||||
// If a node is not found in the database, a MissingNodeError is returned.
|
// If a node is not found in the database, a MissingNodeError is returned.
|
||||||
func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
|
func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreeDelQPS.Mark(1)
|
||||||
|
StateTreeDelTime.UpdateSince(start)
|
||||||
|
StateStorageTreeDelQPS.Mark(1)
|
||||||
|
StateStorageTreeDelTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
hk := t.hashKey(key)
|
hk := t.hashKey(key)
|
||||||
delete(t.getSecKeyCache(), string(hk))
|
delete(t.getSecKeyCache(), string(hk))
|
||||||
return t.trie.Delete(hk)
|
return t.trie.Delete(hk)
|
||||||
@@ -200,6 +270,12 @@ func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
|
|||||||
|
|
||||||
// DeleteAccount abstracts an account deletion from the trie.
|
// DeleteAccount abstracts an account deletion from the trie.
|
||||||
func (t *StateTrie) DeleteAccount(address common.Address) error {
|
func (t *StateTrie) DeleteAccount(address common.Address) error {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreeDelQPS.Mark(1)
|
||||||
|
StateTreeDelTime.UpdateSince(start)
|
||||||
|
StateAccountTreeDelQPS.Mark(1)
|
||||||
|
StateAccountTreeDelTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
hk := t.hashKey(address.Bytes())
|
hk := t.hashKey(address.Bytes())
|
||||||
delete(t.getSecKeyCache(), string(hk))
|
delete(t.getSecKeyCache(), string(hk))
|
||||||
return t.trie.Delete(hk)
|
return t.trie.Delete(hk)
|
||||||
@@ -222,6 +298,10 @@ func (t *StateTrie) GetKey(shaKey []byte) []byte {
|
|||||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||||
// be created with new root and updated trie database for following usage
|
// be created with new root and updated trie database for following usage
|
||||||
func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
|
func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreeCommitQPS.Mark(1)
|
||||||
|
StateTreeCommitTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
// Write all the pre-images to the actual disk database
|
// Write all the pre-images to the actual disk database
|
||||||
if len(t.getSecKeyCache()) > 0 {
|
if len(t.getSecKeyCache()) > 0 {
|
||||||
preimages := make(map[common.Hash][]byte)
|
preimages := make(map[common.Hash][]byte)
|
||||||
@@ -238,6 +318,10 @@ func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, er
|
|||||||
// Hash returns the root hash of StateTrie. It does not write to the
|
// Hash returns the root hash of StateTrie. It does not write to the
|
||||||
// database and can be used even if the trie doesn't have one.
|
// database and can be used even if the trie doesn't have one.
|
||||||
func (t *StateTrie) Hash() common.Hash {
|
func (t *StateTrie) Hash() common.Hash {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
StateTreeCalcQPS.Mark(1)
|
||||||
|
StateTreeCalcTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
return t.trie.Hash()
|
return t.trie.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -246,6 +246,10 @@ func (db *Database) Reader(root common.Hash) (layer, error) {
|
|||||||
// The passed in maps(nodes, states) will be retained to avoid copying everything.
|
// The passed in maps(nodes, states) will be retained to avoid copying everything.
|
||||||
// Therefore, these maps must not be changed afterwards.
|
// Therefore, these maps must not be changed afterwards.
|
||||||
func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error {
|
func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error {
|
||||||
|
defer func(start time.Time) {
|
||||||
|
PbssUpdateDiffQPS.Mark(1)
|
||||||
|
PbssUpdateDiffTime.UpdateSince(start)
|
||||||
|
}(time.Now())
|
||||||
// Hold the lock to prevent concurrent mutations.
|
// Hold the lock to prevent concurrent mutations.
|
||||||
db.lock.Lock()
|
db.lock.Lock()
|
||||||
defer db.lock.Unlock()
|
defer db.lock.Unlock()
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/fastcache"
|
"github.com/VictoriaMetrics/fastcache"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@@ -197,11 +198,15 @@ func (dl *diskLayer) Node(owner common.Hash, path []byte, hash common.Hash) ([]b
|
|||||||
nBlob []byte
|
nBlob []byte
|
||||||
nHash common.Hash
|
nHash common.Hash
|
||||||
)
|
)
|
||||||
|
// TODO:
|
||||||
|
trieNodeQPS.Mark(1)
|
||||||
|
startLoadTrieNode := time.Now()
|
||||||
if owner == (common.Hash{}) {
|
if owner == (common.Hash{}) {
|
||||||
nBlob, nHash = rawdb.ReadAccountTrieNode(dl.db.diskdb, path)
|
nBlob, nHash = rawdb.ReadAccountTrieNode(dl.db.diskdb, path)
|
||||||
} else {
|
} else {
|
||||||
nBlob, nHash = rawdb.ReadStorageTrieNode(dl.db.diskdb, owner, path)
|
nBlob, nHash = rawdb.ReadStorageTrieNode(dl.db.diskdb, owner, path)
|
||||||
}
|
}
|
||||||
|
trieNodeTime.Mark(time.Since(startLoadTrieNode).Nanoseconds())
|
||||||
if nHash != hash {
|
if nHash != hash {
|
||||||
diskFalseMeter.Mark(1)
|
diskFalseMeter.Mark(1)
|
||||||
log.Error("Unexpected trie node in disk", "owner", owner, "path", path, "expect", hash, "got", nHash)
|
log.Error("Unexpected trie node in disk", "owner", owner, "path", path, "expect", hash, "got", nHash)
|
||||||
|
|||||||
@@ -53,4 +53,10 @@ var (
|
|||||||
diffHashCacheMissMeter = metrics.NewRegisteredMeter("pathdb/difflayer/hashcache/miss", nil)
|
diffHashCacheMissMeter = metrics.NewRegisteredMeter("pathdb/difflayer/hashcache/miss", nil)
|
||||||
diffHashCacheSlowPathMeter = metrics.NewRegisteredMeter("pathdb/difflayer/hashcache/slowpath", nil)
|
diffHashCacheSlowPathMeter = metrics.NewRegisteredMeter("pathdb/difflayer/hashcache/slowpath", nil)
|
||||||
diffHashCacheLengthGauge = metrics.NewRegisteredGauge("pathdb/difflayer/hashcache/size", nil)
|
diffHashCacheLengthGauge = metrics.NewRegisteredGauge("pathdb/difflayer/hashcache/size", nil)
|
||||||
|
|
||||||
|
PbssUpdateDiffQPS = metrics.NewRegisteredMeter("pbss/difflayer/update/qps", nil)
|
||||||
|
PbssUpdateDiffTime = metrics.NewRegisteredTimer("pbss/difflayer/update/time", nil)
|
||||||
|
|
||||||
|
trieNodeQPS = metrics.NewRegisteredMeter("pbss/trie/node/qps", nil)
|
||||||
|
trieNodeTime = metrics.NewRegisteredMeter("pbss/trie/node/time", nil)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user