mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
Merge branch 'peerdas-devnet-7' into engine-getblobs-v2-metrics
This commit is contained in:
commit
3b8caf1f93
96 changed files with 1610 additions and 1021 deletions
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/beacon/params"
|
"github.com/ethereum/go-ethereum/beacon/params"
|
||||||
"github.com/ethereum/go-ethereum/beacon/types"
|
"github.com/ethereum/go-ethereum/beacon/types"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ctypes "github.com/ethereum/go-ethereum/core/types"
|
ctypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
@ -104,7 +105,11 @@ func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent)
|
||||||
method = "engine_newPayloadV4"
|
method = "engine_newPayloadV4"
|
||||||
parentBeaconRoot := event.BeaconHead.ParentRoot
|
parentBeaconRoot := event.BeaconHead.ParentRoot
|
||||||
blobHashes := collectBlobHashes(event.Block)
|
blobHashes := collectBlobHashes(event.Block)
|
||||||
params = append(params, blobHashes, parentBeaconRoot, event.ExecRequests)
|
hexRequests := make([]hexutil.Bytes, len(event.ExecRequests))
|
||||||
|
for i := range event.ExecRequests {
|
||||||
|
hexRequests[i] = hexutil.Bytes(event.ExecRequests[i])
|
||||||
|
}
|
||||||
|
params = append(params, blobHashes, parentBeaconRoot, hexRequests)
|
||||||
case "deneb":
|
case "deneb":
|
||||||
method = "engine_newPayloadV3"
|
method = "engine_newPayloadV3"
|
||||||
parentBeaconRoot := event.BeaconHead.ParentRoot
|
parentBeaconRoot := event.BeaconHead.ParentRoot
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ func (s *Suite) EthTests() []utesting.Test {
|
||||||
{Name: "Status", Fn: s.TestStatus},
|
{Name: "Status", Fn: s.TestStatus},
|
||||||
// get block headers
|
// get block headers
|
||||||
{Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders},
|
{Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders},
|
||||||
|
{Name: "GetNonexistentBlockHeaders", Fn: s.TestGetNonexistentBlockHeaders},
|
||||||
{Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests},
|
{Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests},
|
||||||
{Name: "SameRequestID", Fn: s.TestSameRequestID},
|
{Name: "SameRequestID", Fn: s.TestSameRequestID},
|
||||||
{Name: "ZeroRequestID", Fn: s.TestZeroRequestID},
|
{Name: "ZeroRequestID", Fn: s.TestZeroRequestID},
|
||||||
|
|
@ -158,6 +159,48 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Suite) TestGetNonexistentBlockHeaders(t *utesting.T) {
|
||||||
|
t.Log(`This test sends GetBlockHeaders requests for nonexistent blocks (using max uint64 value)
|
||||||
|
to check if the node disconnects after receiving multiple invalid requests.`)
|
||||||
|
|
||||||
|
conn, err := s.dial()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("dial failed: %v", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
if err := conn.peer(s.chain, nil); err != nil {
|
||||||
|
t.Fatalf("peering failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create request with max uint64 value for a nonexistent block
|
||||||
|
badReq := ð.GetBlockHeadersPacket{
|
||||||
|
GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
|
||||||
|
Origin: eth.HashOrNumber{Number: ^uint64(0)},
|
||||||
|
Amount: 1,
|
||||||
|
Skip: 0,
|
||||||
|
Reverse: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request 10 times. Some clients are lient on the first few invalids.
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
badReq.RequestId = uint64(i)
|
||||||
|
if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, badReq); err != nil {
|
||||||
|
if err == errDisc {
|
||||||
|
t.Fatalf("peer disconnected after %d requests", i+1)
|
||||||
|
}
|
||||||
|
t.Fatalf("write failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if peer disconnects at the end.
|
||||||
|
code, _, err := conn.Read()
|
||||||
|
if err == errDisc || code == discMsg {
|
||||||
|
t.Fatal("peer improperly disconnected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
|
func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
|
||||||
t.Log(`This test requests blocks headers from the node, performing two requests
|
t.Log(`This test requests blocks headers from the node, performing two requests
|
||||||
concurrently, with different request IDs.`)
|
concurrently, with different request IDs.`)
|
||||||
|
|
|
||||||
|
|
@ -246,10 +246,13 @@ func initGenesis(ctx *cli.Context) error {
|
||||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
_, hash, _, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
_, hash, compatErr, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to write genesis block: %v", err)
|
utils.Fatalf("Failed to write genesis block: %v", err)
|
||||||
}
|
}
|
||||||
|
if compatErr != nil {
|
||||||
|
utils.Fatalf("Failed to write chain config: %v", compatErr)
|
||||||
|
}
|
||||||
log.Info("Successfully wrote genesis state", "database", "chaindata", "hash", hash)
|
log.Info("Successfully wrote genesis state", "database", "chaindata", "hash", hash)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,8 @@ const (
|
||||||
// child g gets a temporary data directory.
|
// child g gets a temporary data directory.
|
||||||
func runMinimalGeth(t *testing.T, args ...string) *testgeth {
|
func runMinimalGeth(t *testing.T, args ...string) *testgeth {
|
||||||
// --holesky to make the 'writing genesis to disk' faster (no accounts)
|
// --holesky to make the 'writing genesis to disk' faster (no accounts)
|
||||||
// --networkid=1337 to avoid cache bump
|
|
||||||
// --syncmode=full to avoid allocating fast sync bloom
|
// --syncmode=full to avoid allocating fast sync bloom
|
||||||
allArgs := []string{"--holesky", "--networkid", "1337", "--authrpc.port", "0", "--syncmode=full", "--port", "0",
|
allArgs := []string{"--holesky", "--authrpc.port", "0", "--syncmode=full", "--port", "0",
|
||||||
"--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64",
|
"--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64",
|
||||||
"--datadir.minfreedisk", "0"}
|
"--datadir.minfreedisk", "0"}
|
||||||
return runGeth(t, append(allArgs, args...)...)
|
return runGeth(t, append(allArgs, args...)...)
|
||||||
|
|
@ -103,17 +102,17 @@ func TestAttachWelcome(t *testing.T) {
|
||||||
"--http", "--http.port", httpPort,
|
"--http", "--http.port", httpPort,
|
||||||
"--ws", "--ws.port", wsPort)
|
"--ws", "--ws.port", wsPort)
|
||||||
t.Run("ipc", func(t *testing.T) {
|
t.Run("ipc", func(t *testing.T) {
|
||||||
waitForEndpoint(t, ipc, 4*time.Second)
|
waitForEndpoint(t, ipc, 2*time.Minute)
|
||||||
testAttachWelcome(t, geth, "ipc:"+ipc, ipcAPIs)
|
testAttachWelcome(t, geth, "ipc:"+ipc, ipcAPIs)
|
||||||
})
|
})
|
||||||
t.Run("http", func(t *testing.T) {
|
t.Run("http", func(t *testing.T) {
|
||||||
endpoint := "http://127.0.0.1:" + httpPort
|
endpoint := "http://127.0.0.1:" + httpPort
|
||||||
waitForEndpoint(t, endpoint, 4*time.Second)
|
waitForEndpoint(t, endpoint, 2*time.Minute)
|
||||||
testAttachWelcome(t, geth, endpoint, httpAPIs)
|
testAttachWelcome(t, geth, endpoint, httpAPIs)
|
||||||
})
|
})
|
||||||
t.Run("ws", func(t *testing.T) {
|
t.Run("ws", func(t *testing.T) {
|
||||||
endpoint := "ws://127.0.0.1:" + wsPort
|
endpoint := "ws://127.0.0.1:" + wsPort
|
||||||
waitForEndpoint(t, endpoint, 4*time.Second)
|
waitForEndpoint(t, endpoint, 2*time.Minute)
|
||||||
testAttachWelcome(t, geth, endpoint, httpAPIs)
|
testAttachWelcome(t, geth, endpoint, httpAPIs)
|
||||||
})
|
})
|
||||||
geth.Kill()
|
geth.Kill()
|
||||||
|
|
|
||||||
|
|
@ -1571,8 +1571,8 @@ func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
|
|
||||||
// SetEthConfig applies eth-related command line flags to the config.
|
// SetEthConfig applies eth-related command line flags to the config.
|
||||||
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// Avoid conflicting network flags
|
// Avoid conflicting network flags, don't allow network id override on preset networks
|
||||||
flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag, HoodiFlag)
|
flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag, HoodiFlag, NetworkIdFlag)
|
||||||
flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
||||||
|
|
||||||
// Set configurations from CLI flags
|
// Set configurations from CLI flags
|
||||||
|
|
@ -1743,33 +1743,23 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// Override any default configs for hard coded networks.
|
// Override any default configs for hard coded networks.
|
||||||
switch {
|
switch {
|
||||||
case ctx.Bool(MainnetFlag.Name):
|
case ctx.Bool(MainnetFlag.Name):
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
|
||||||
cfg.NetworkId = 1
|
cfg.NetworkId = 1
|
||||||
}
|
|
||||||
cfg.Genesis = core.DefaultGenesisBlock()
|
cfg.Genesis = core.DefaultGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
|
||||||
case ctx.Bool(HoleskyFlag.Name):
|
case ctx.Bool(HoleskyFlag.Name):
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
|
||||||
cfg.NetworkId = 17000
|
cfg.NetworkId = 17000
|
||||||
}
|
|
||||||
cfg.Genesis = core.DefaultHoleskyGenesisBlock()
|
cfg.Genesis = core.DefaultHoleskyGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.HoleskyGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.HoleskyGenesisHash)
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
|
||||||
cfg.NetworkId = 11155111
|
cfg.NetworkId = 11155111
|
||||||
}
|
|
||||||
cfg.Genesis = core.DefaultSepoliaGenesisBlock()
|
cfg.Genesis = core.DefaultSepoliaGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
|
||||||
case ctx.Bool(HoodiFlag.Name):
|
case ctx.Bool(HoodiFlag.Name):
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
|
||||||
cfg.NetworkId = 560048
|
cfg.NetworkId = 560048
|
||||||
}
|
|
||||||
cfg.Genesis = core.DefaultHoodiGenesisBlock()
|
cfg.Genesis = core.DefaultHoodiGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.HoodiGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.HoodiGenesisHash)
|
||||||
case ctx.Bool(DeveloperFlag.Name):
|
case ctx.Bool(DeveloperFlag.Name):
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
|
||||||
cfg.NetworkId = 1337
|
cfg.NetworkId = 1337
|
||||||
}
|
|
||||||
cfg.SyncMode = ethconfig.FullSync
|
cfg.SyncMode = ethconfig.FullSync
|
||||||
// Create new developer account or reuse existing one
|
// Create new developer account or reuse existing one
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||||
if !disk {
|
if !disk {
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
} else {
|
} else {
|
||||||
pdb, err := pebble.New(b.TempDir(), 128, 128, "", false, true)
|
pdb, err := pebble.New(b.TempDir(), 128, 128, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("cannot create temporary database: %v", err)
|
b.Fatalf("cannot create temporary database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -303,7 +303,7 @@ func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uin
|
||||||
func benchWriteChain(b *testing.B, full bool, count uint64) {
|
func benchWriteChain(b *testing.B, full bool, count uint64) {
|
||||||
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false, true)
|
pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database: %v", err)
|
b.Fatalf("error opening database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +316,7 @@ func benchWriteChain(b *testing.B, full bool, count uint64) {
|
||||||
func benchReadChain(b *testing.B, full bool, count uint64) {
|
func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
dir := b.TempDir()
|
dir := b.TempDir()
|
||||||
|
|
||||||
pdb, err := pebble.New(dir, 1024, 128, "", false, true)
|
pdb, err := pebble.New(dir, 1024, 128, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database: %v", err)
|
b.Fatalf("error opening database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -332,7 +332,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
pdb, err = pebble.New(dir, 1024, 128, "", false, true)
|
pdb, err = pebble.New(dir, 1024, 128, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database: %v", err)
|
b.Fatalf("error opening database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,10 @@ var (
|
||||||
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
||||||
blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil)
|
blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil)
|
||||||
|
|
||||||
blockPrefetchExecuteTimer = metrics.NewRegisteredTimer("chain/prefetch/executes", nil)
|
blockPrefetchExecuteTimer = metrics.NewRegisteredResettingTimer("chain/prefetch/executes", nil)
|
||||||
blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil)
|
blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil)
|
||||||
|
blockPrefetchTxsInvalidMeter = metrics.NewRegisteredMeter("chain/prefetch/txs/invalid", nil)
|
||||||
|
blockPrefetchTxsValidMeter = metrics.NewRegisteredMeter("chain/prefetch/txs/valid", nil)
|
||||||
|
|
||||||
errInsertionInterrupted = errors.New("insertion is interrupted")
|
errInsertionInterrupted = errors.New("insertion is interrupted")
|
||||||
errChainStopped = errors.New("blockchain is stopped")
|
errChainStopped = errors.New("blockchain is stopped")
|
||||||
|
|
@ -979,17 +981,16 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||||
// Ignore the error here since light client won't hit this path
|
// Ignore the error here since light client won't hit this path
|
||||||
frozen, _ := bc.db.Ancients()
|
frozen, _ := bc.db.Ancients()
|
||||||
if num+1 <= frozen {
|
if num+1 <= frozen {
|
||||||
// Truncate all relative data(header, total difficulty, body, receipt
|
// The chain segment, such as the block header, canonical hash,
|
||||||
// and canonical hash) from ancient store.
|
// body, and receipt, will be removed from the ancient store
|
||||||
if _, err := bc.db.TruncateHead(num); err != nil {
|
// in one go.
|
||||||
log.Crit("Failed to truncate ancient data", "number", num, "err", err)
|
//
|
||||||
}
|
// The hash-to-number mapping in the key-value store will be
|
||||||
// Remove the hash <-> number mapping from the active store.
|
// removed by the hc.SetHead function.
|
||||||
rawdb.DeleteHeaderNumber(db, hash)
|
|
||||||
} else {
|
} else {
|
||||||
// Remove relative body and receipts from the active store.
|
// Remove the associated body and receipts from the key-value store.
|
||||||
// The header, total difficulty and canonical hash will be
|
// The header, hash-to-number mapping, and canonical hash will be
|
||||||
// removed in the hc.SetHead function.
|
// removed by the hc.SetHead function.
|
||||||
rawdb.DeleteBody(db, hash, num)
|
rawdb.DeleteBody(db, hash, num)
|
||||||
rawdb.DeleteReceipts(db, hash, num)
|
rawdb.DeleteReceipts(db, hash, num)
|
||||||
}
|
}
|
||||||
|
|
@ -1361,7 +1362,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
size += writeSize
|
size += writeSize
|
||||||
|
|
||||||
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
|
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
|
||||||
if err := bc.db.Sync(); err != nil {
|
if err := bc.db.SyncAncient(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
// Write hash to number mappings
|
// Write hash to number mappings
|
||||||
|
|
@ -1759,18 +1760,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
||||||
bc.reportBlock(block, nil, err)
|
bc.reportBlock(block, nil, err)
|
||||||
return nil, it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
// No validation errors for the first block (or chain prefix skipped)
|
|
||||||
var activeState *state.StateDB
|
|
||||||
defer func() {
|
|
||||||
// The chain importer is starting and stopping trie prefetchers. If a bad
|
|
||||||
// block or other error is hit however, an early return may not properly
|
|
||||||
// terminate the background threads. This defer ensures that we clean up
|
|
||||||
// and dangling prefetcher, without deferring each and holding on live refs.
|
|
||||||
if activeState != nil {
|
|
||||||
activeState.StopPrefetcher()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Track the singleton witness from this chain insertion (if any)
|
// Track the singleton witness from this chain insertion (if any)
|
||||||
var witness *stateless.Witness
|
var witness *stateless.Witness
|
||||||
|
|
||||||
|
|
@ -1826,63 +1815,20 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Retrieve the parent block and it's state to execute on top
|
// Retrieve the parent block and it's state to execute on top
|
||||||
start := time.Now()
|
|
||||||
parent := it.previous()
|
parent := it.previous()
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
||||||
}
|
}
|
||||||
statedb, err := state.New(parent.Root, bc.statedb)
|
|
||||||
if err != nil {
|
|
||||||
return nil, it.index, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are past Byzantium, enable prefetching to pull in trie node paths
|
|
||||||
// while processing transactions. Before Byzantium the prefetcher is mostly
|
|
||||||
// useless due to the intermediate root hashing after each transaction.
|
|
||||||
if bc.chainConfig.IsByzantium(block.Number()) {
|
|
||||||
// Generate witnesses either if we're self-testing, or if it's the
|
|
||||||
// only block being inserted. A bit crude, but witnesses are huge,
|
|
||||||
// so we refuse to make an entire chain of them.
|
|
||||||
if bc.vmConfig.StatelessSelfValidation || (makeWitness && len(chain) == 1) {
|
|
||||||
witness, err = stateless.NewWitness(block.Header(), bc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, it.index, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
statedb.StartPrefetcher("chain", witness)
|
|
||||||
}
|
|
||||||
activeState = statedb
|
|
||||||
|
|
||||||
// If we have a followup block, run that against the current state to pre-cache
|
|
||||||
// transactions and probabilistically some of the account/storage trie nodes.
|
|
||||||
var followupInterrupt atomic.Bool
|
|
||||||
if !bc.cacheConfig.TrieCleanNoPrefetch {
|
|
||||||
if followup, err := it.peek(); followup != nil && err == nil {
|
|
||||||
throwaway, _ := state.New(parent.Root, bc.statedb)
|
|
||||||
|
|
||||||
go func(start time.Time, followup *types.Block, throwaway *state.StateDB) {
|
|
||||||
// Disable tracing for prefetcher executions.
|
|
||||||
vmCfg := bc.vmConfig
|
|
||||||
vmCfg.Tracer = nil
|
|
||||||
bc.prefetcher.Prefetch(followup, throwaway, vmCfg, &followupInterrupt)
|
|
||||||
|
|
||||||
blockPrefetchExecuteTimer.Update(time.Since(start))
|
|
||||||
if followupInterrupt.Load() {
|
|
||||||
blockPrefetchInterruptMeter.Mark(1)
|
|
||||||
}
|
|
||||||
}(time.Now(), followup, throwaway)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The traced section of block import.
|
// The traced section of block import.
|
||||||
res, err := bc.processBlock(block, statedb, start, setHead)
|
start := time.Now()
|
||||||
followupInterrupt.Store(true)
|
res, err := bc.processBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, it.index, err
|
return nil, it.index, err
|
||||||
}
|
}
|
||||||
// Report the import stats before returning the various results
|
// Report the import stats before returning the various results
|
||||||
stats.processed++
|
stats.processed++
|
||||||
stats.usedGas += res.usedGas
|
stats.usedGas += res.usedGas
|
||||||
|
witness = res.witness
|
||||||
|
|
||||||
var snapDiffItems, snapBufItems common.StorageSize
|
var snapDiffItems, snapBufItems common.StorageSize
|
||||||
if bc.snaps != nil {
|
if bc.snaps != nil {
|
||||||
|
|
@ -1938,11 +1884,74 @@ type blockProcessingResult struct {
|
||||||
usedGas uint64
|
usedGas uint64
|
||||||
procTime time.Duration
|
procTime time.Duration
|
||||||
status WriteStatus
|
status WriteStatus
|
||||||
|
witness *stateless.Witness
|
||||||
}
|
}
|
||||||
|
|
||||||
// processBlock executes and validates the given block. If there was no error
|
// processBlock executes and validates the given block. If there was no error
|
||||||
// it writes the block and associated state to database.
|
// it writes the block and associated state to database.
|
||||||
func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, start time.Time, setHead bool) (_ *blockProcessingResult, blockEndErr error) {
|
func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
startTime = time.Now()
|
||||||
|
statedb *state.StateDB
|
||||||
|
interrupt atomic.Bool
|
||||||
|
)
|
||||||
|
defer interrupt.Store(true) // terminate the prefetch at the end
|
||||||
|
|
||||||
|
if bc.cacheConfig.TrieCleanNoPrefetch {
|
||||||
|
statedb, err = state.New(parentRoot, bc.statedb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If prefetching is enabled, run that against the current state to pre-cache
|
||||||
|
// transactions and probabilistically some of the account/storage trie nodes.
|
||||||
|
//
|
||||||
|
// Note: the main processor and prefetcher share the same reader with a local
|
||||||
|
// cache for mitigating the overhead of state access.
|
||||||
|
reader, err := bc.statedb.ReaderWithCache(parentRoot)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
throwaway, err := state.NewWithReader(parentRoot, bc.statedb, reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
statedb, err = state.NewWithReader(parentRoot, bc.statedb, reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
go func(start time.Time, throwaway *state.StateDB, block *types.Block) {
|
||||||
|
// Disable tracing for prefetcher executions.
|
||||||
|
vmCfg := bc.vmConfig
|
||||||
|
vmCfg.Tracer = nil
|
||||||
|
bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt)
|
||||||
|
|
||||||
|
blockPrefetchExecuteTimer.Update(time.Since(start))
|
||||||
|
if interrupt.Load() {
|
||||||
|
blockPrefetchInterruptMeter.Mark(1)
|
||||||
|
}
|
||||||
|
}(time.Now(), throwaway, block)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are past Byzantium, enable prefetching to pull in trie node paths
|
||||||
|
// while processing transactions. Before Byzantium the prefetcher is mostly
|
||||||
|
// useless due to the intermediate root hashing after each transaction.
|
||||||
|
var witness *stateless.Witness
|
||||||
|
if bc.chainConfig.IsByzantium(block.Number()) {
|
||||||
|
// Generate witnesses either if we're self-testing, or if it's the
|
||||||
|
// only block being inserted. A bit crude, but witnesses are huge,
|
||||||
|
// so we refuse to make an entire chain of them.
|
||||||
|
if bc.vmConfig.StatelessSelfValidation || makeWitness {
|
||||||
|
witness, err = stateless.NewWitness(block.Header(), bc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statedb.StartPrefetcher("chain", witness)
|
||||||
|
defer statedb.StopPrefetcher()
|
||||||
|
}
|
||||||
|
|
||||||
if bc.logger != nil && bc.logger.OnBlockStart != nil {
|
if bc.logger != nil && bc.logger.OnBlockStart != nil {
|
||||||
bc.logger.OnBlockStart(tracing.BlockEvent{
|
bc.logger.OnBlockStart(tracing.BlockEvent{
|
||||||
Block: block,
|
Block: block,
|
||||||
|
|
@ -2001,7 +2010,7 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xvtime := time.Since(xvstart)
|
xvtime := time.Since(xvstart)
|
||||||
proctime := time.Since(start) // processing + validation + cross validation
|
proctime := time.Since(startTime) // processing + validation + cross validation
|
||||||
|
|
||||||
// Update the metrics touched during block processing and validation
|
// Update the metrics touched during block processing and validation
|
||||||
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
||||||
|
|
@ -2042,9 +2051,14 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them
|
triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them
|
||||||
|
|
||||||
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
|
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
|
||||||
blockInsertTimer.UpdateSince(start)
|
blockInsertTimer.UpdateSince(startTime)
|
||||||
|
|
||||||
return &blockProcessingResult{usedGas: res.GasUsed, procTime: proctime, status: status}, nil
|
return &blockProcessingResult{
|
||||||
|
usedGas: res.GasUsed,
|
||||||
|
procTime: proctime,
|
||||||
|
status: status,
|
||||||
|
witness: witness,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertSideChain is called when an import batch hits upon a pruned ancestor
|
// insertSideChain is called when an import batch hits upon a pruned ancestor
|
||||||
|
|
@ -2627,7 +2641,8 @@ func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, e
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if err := bc.db.Sync(); err != nil {
|
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
|
||||||
|
if err := bc.db.SyncAncient(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
// Write hash to number mappings
|
// Write hash to number mappings
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ func (it *insertIterator) next() (*types.Block, error) {
|
||||||
//
|
//
|
||||||
// Both header and body validation errors (nil too) is cached into the iterator
|
// Both header and body validation errors (nil too) is cached into the iterator
|
||||||
// to avoid duplicating work on the following next() call.
|
// to avoid duplicating work on the following next() call.
|
||||||
|
// nolint:unused
|
||||||
func (it *insertIterator) peek() (*types.Block, error) {
|
func (it *insertIterator) peek() (*types.Block, error) {
|
||||||
// If we reached the end of the chain, abort
|
// If we reached the end of the chain, abort
|
||||||
if it.index+1 >= len(it.chain) {
|
if it.index+1 >= len(it.chain) {
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,14 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
|
||||||
return receipts
|
return receipts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bc *BlockChain) GetRawReceiptsByHash(hash common.Hash) types.Receipts {
|
||||||
|
number := rawdb.ReadHeaderNumber(bc.db, hash)
|
||||||
|
if number == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return rawdb.ReadRawReceipts(bc.db, hash, *number)
|
||||||
|
}
|
||||||
|
|
||||||
// GetUnclesInChain retrieves all the uncles from a given block backwards until
|
// GetUnclesInChain retrieves all the uncles from a given block backwards until
|
||||||
// a specific distance is reached.
|
// a specific distance is reached.
|
||||||
func (bc *BlockChain) GetUnclesInChain(block *types.Block, length int) []*types.Header {
|
func (bc *BlockChain) GetUnclesInChain(block *types.Block, length int) []*types.Header {
|
||||||
|
|
@ -262,42 +270,20 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max
|
||||||
// GetTransactionLookup retrieves the lookup along with the transaction
|
// GetTransactionLookup retrieves the lookup along with the transaction
|
||||||
// itself associate with the given transaction hash.
|
// itself associate with the given transaction hash.
|
||||||
//
|
//
|
||||||
// An error will be returned if the transaction is not found, and background
|
// A null will be returned if the transaction is not found. This can be due to
|
||||||
// indexing for transactions is still in progress. The transaction might be
|
// the transaction indexer not being finished. The caller must explicitly check
|
||||||
// reachable shortly once it's indexed.
|
// the indexer progress.
|
||||||
//
|
func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction) {
|
||||||
// A null will be returned in the transaction is not found and background
|
|
||||||
// transaction indexing is already finished. The transaction is not existent
|
|
||||||
// from the node's perspective.
|
|
||||||
func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction, error) {
|
|
||||||
bc.txLookupLock.RLock()
|
bc.txLookupLock.RLock()
|
||||||
defer bc.txLookupLock.RUnlock()
|
defer bc.txLookupLock.RUnlock()
|
||||||
|
|
||||||
// Short circuit if the txlookup already in the cache, retrieve otherwise
|
// Short circuit if the txlookup already in the cache, retrieve otherwise
|
||||||
if item, exist := bc.txLookupCache.Get(hash); exist {
|
if item, exist := bc.txLookupCache.Get(hash); exist {
|
||||||
return item.lookup, item.transaction, nil
|
return item.lookup, item.transaction
|
||||||
}
|
}
|
||||||
tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash)
|
tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash)
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
progress, err := bc.TxIndexProgress()
|
return nil, nil
|
||||||
if err != nil {
|
|
||||||
// No error is returned if the transaction indexing progress is unreachable
|
|
||||||
// due to unexpected internal errors. In such cases, it is impossible to
|
|
||||||
// determine whether the transaction does not exist or has simply not been
|
|
||||||
// indexed yet without a progress marker.
|
|
||||||
//
|
|
||||||
// In such scenarios, the transaction is treated as unreachable, though
|
|
||||||
// this is clearly an unintended and unexpected situation.
|
|
||||||
return nil, nil, nil
|
|
||||||
}
|
|
||||||
// The transaction indexing is not finished yet, returning an
|
|
||||||
// error to explicitly indicate it.
|
|
||||||
if !progress.Done() {
|
|
||||||
return nil, nil, errors.New("transaction indexing still in progress")
|
|
||||||
}
|
|
||||||
// The transaction is already indexed, the transaction is either
|
|
||||||
// not existent or not in the range of index, returning null.
|
|
||||||
return nil, nil, nil
|
|
||||||
}
|
}
|
||||||
lookup := &rawdb.LegacyTxLookupEntry{
|
lookup := &rawdb.LegacyTxLookupEntry{
|
||||||
BlockHash: blockHash,
|
BlockHash: blockHash,
|
||||||
|
|
@ -308,7 +294,23 @@ func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLoo
|
||||||
lookup: lookup,
|
lookup: lookup,
|
||||||
transaction: tx,
|
transaction: tx,
|
||||||
})
|
})
|
||||||
return lookup, tx, nil
|
return lookup, tx
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxIndexDone returns true if the transaction indexer has finished indexing.
|
||||||
|
func (bc *BlockChain) TxIndexDone() bool {
|
||||||
|
progress, err := bc.TxIndexProgress()
|
||||||
|
if err != nil {
|
||||||
|
// No error is returned if the transaction indexing progress is unreachable
|
||||||
|
// due to unexpected internal errors. In such cases, it is impossible to
|
||||||
|
// determine whether the transaction does not exist or has simply not been
|
||||||
|
// indexed yet without a progress marker.
|
||||||
|
//
|
||||||
|
// In such scenarios, the transaction is treated as unreachable, though
|
||||||
|
// this is clearly an unintended and unexpected situation.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return progress.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasState checks if state trie is fully present in the database or not.
|
// HasState checks if state trie is fully present in the database or not.
|
||||||
|
|
@ -404,7 +406,7 @@ func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
|
||||||
if bc.txIndexer == nil {
|
if bc.txIndexer == nil {
|
||||||
return TxIndexProgress{}, errors.New("tx indexer is not enabled")
|
return TxIndexProgress{}, errors.New("tx indexer is not enabled")
|
||||||
}
|
}
|
||||||
return bc.txIndexer.txIndexProgress()
|
return bc.txIndexer.txIndexProgress(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HistoryPruningCutoff returns the configured history pruning point.
|
// HistoryPruningCutoff returns the configured history pruning point.
|
||||||
|
|
|
||||||
|
|
@ -1765,7 +1765,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false, true)
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1850,7 +1850,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||||
chain.stopWithoutSaving()
|
chain.stopWithoutSaving()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
pdb, err = pebble.New(datadir, 0, 0, "", false, true)
|
pdb, err = pebble.New(datadir, 0, 0, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to reopen persistent key-value database: %v", err)
|
t.Fatalf("Failed to reopen persistent key-value database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1915,7 +1915,7 @@ func testIssue23496(t *testing.T, scheme string) {
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false, true)
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1973,7 +1973,7 @@ func testIssue23496(t *testing.T, scheme string) {
|
||||||
chain.stopWithoutSaving()
|
chain.stopWithoutSaving()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
pdb, err = pebble.New(datadir, 0, 0, "", false, true)
|
pdb, err = pebble.New(datadir, 0, 0, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to reopen persistent key-value database: %v", err)
|
t.Fatalf("Failed to reopen persistent key-value database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1969,7 +1969,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false, true)
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false, true)
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +257,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
||||||
chain.triedb.Close()
|
chain.triedb.Close()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false, true)
|
pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2492,7 +2492,7 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) {
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := path.Join(datadir, "ancient")
|
ancient := path.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false, true)
|
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ type blockchain interface {
|
||||||
GetHeader(hash common.Hash, number uint64) *types.Header
|
GetHeader(hash common.Hash, number uint64) *types.Header
|
||||||
GetCanonicalHash(number uint64) common.Hash
|
GetCanonicalHash(number uint64) common.Hash
|
||||||
GetReceiptsByHash(hash common.Hash) types.Receipts
|
GetReceiptsByHash(hash common.Hash) types.Receipts
|
||||||
|
GetRawReceiptsByHash(hash common.Hash) types.Receipts
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChainView represents an immutable view of a chain with a block id and a set
|
// ChainView represents an immutable view of a chain with a block id and a set
|
||||||
|
|
@ -102,10 +103,23 @@ func (cv *ChainView) Receipts(number uint64) types.Receipts {
|
||||||
blockHash := cv.BlockHash(number)
|
blockHash := cv.BlockHash(number)
|
||||||
if blockHash == (common.Hash{}) {
|
if blockHash == (common.Hash{}) {
|
||||||
log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber)
|
log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return cv.chain.GetReceiptsByHash(blockHash)
|
return cv.chain.GetReceiptsByHash(blockHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RawReceipts returns the set of receipts belonging to the block at the given
|
||||||
|
// block number. Does not derive the fields of the receipts, should only be
|
||||||
|
// used during creation of the filter maps, please use cv.Receipts during querying.
|
||||||
|
func (cv *ChainView) RawReceipts(number uint64) types.Receipts {
|
||||||
|
blockHash := cv.BlockHash(number)
|
||||||
|
if blockHash == (common.Hash{}) {
|
||||||
|
log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return cv.chain.GetRawReceiptsByHash(blockHash)
|
||||||
|
}
|
||||||
|
|
||||||
// SharedRange returns the block range shared by two chain views.
|
// SharedRange returns the block range shared by two chain views.
|
||||||
func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
|
func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
|
||||||
cv.lock.Lock()
|
cv.lock.Lock()
|
||||||
|
|
@ -121,14 +135,6 @@ func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
|
||||||
return common.NewRange(0, sharedLen)
|
return common.NewRange(0, sharedLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
// limitedView returns a new chain view that is a truncated version of the parent view.
|
|
||||||
func (cv *ChainView) limitedView(newHead uint64) *ChainView {
|
|
||||||
if newHead >= cv.headNumber {
|
|
||||||
return cv
|
|
||||||
}
|
|
||||||
return NewChainView(cv.chain, newHead, cv.BlockHash(newHead))
|
|
||||||
}
|
|
||||||
|
|
||||||
// equalViews returns true if the two chain views are equivalent.
|
// equalViews returns true if the two chain views are equivalent.
|
||||||
func equalViews(cv1, cv2 *ChainView) bool {
|
func equalViews(cv1, cv2 *ChainView) bool {
|
||||||
if cv1 == nil || cv2 == nil {
|
if cv1 == nil || cv2 == nil {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
databaseVersion = 1 // reindexed if database version does not match
|
databaseVersion = 2 // reindexed if database version does not match
|
||||||
cachedLastBlocks = 1000 // last block of map pointers
|
cachedLastBlocks = 1000 // last block of map pointers
|
||||||
cachedLvPointers = 1000 // first log value pointer of block pointers
|
cachedLvPointers = 1000 // first log value pointer of block pointers
|
||||||
cachedBaseRows = 100 // groups of base layer filter row data
|
cachedBaseRows = 100 // groups of base layer filter row data
|
||||||
|
|
@ -244,6 +244,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
|
||||||
disabledCh: make(chan struct{}),
|
disabledCh: make(chan struct{}),
|
||||||
exportFileName: config.ExportFileName,
|
exportFileName: config.ExportFileName,
|
||||||
Params: params,
|
Params: params,
|
||||||
|
targetView: initView,
|
||||||
|
indexedView: initView,
|
||||||
indexedRange: filterMapsRange{
|
indexedRange: filterMapsRange{
|
||||||
initialized: initialized,
|
initialized: initialized,
|
||||||
headIndexed: rs.HeadIndexed,
|
headIndexed: rs.HeadIndexed,
|
||||||
|
|
@ -265,16 +267,8 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
|
||||||
baseRowsCache: lru.NewCache[uint64, [][]uint32](cachedBaseRows),
|
baseRowsCache: lru.NewCache[uint64, [][]uint32](cachedBaseRows),
|
||||||
renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots),
|
renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots),
|
||||||
}
|
}
|
||||||
|
f.checkRevertRange() // revert maps that are inconsistent with the current chain view
|
||||||
|
|
||||||
// Set initial indexer target.
|
|
||||||
f.targetView = initView
|
|
||||||
if f.indexedRange.initialized {
|
|
||||||
f.indexedView = f.initChainView(f.targetView)
|
|
||||||
f.indexedRange.headIndexed = f.indexedRange.blocks.AfterLast() == f.indexedView.HeadNumber()+1
|
|
||||||
if !f.indexedRange.headIndexed {
|
|
||||||
f.indexedRange.headDelimiter = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if f.indexedRange.hasIndexedBlocks() {
|
if f.indexedRange.hasIndexedBlocks() {
|
||||||
log.Info("Initialized log indexer",
|
log.Info("Initialized log indexer",
|
||||||
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
|
|
@ -303,29 +297,40 @@ func (f *FilterMaps) Stop() {
|
||||||
f.closeWg.Wait()
|
f.closeWg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// initChainView returns a chain view consistent with both the current target
|
// checkRevertRange checks whether the existing index is consistent with the
|
||||||
// view and the current state of the log index as found in the database, based
|
// current indexed view and reverts inconsistent maps if necessary.
|
||||||
// on the last block of stored maps.
|
func (f *FilterMaps) checkRevertRange() {
|
||||||
// Note that the returned view might be shorter than the existing index if
|
if f.indexedRange.maps.Count() == 0 {
|
||||||
// the latest maps are not consistent with targetView.
|
return
|
||||||
func (f *FilterMaps) initChainView(chainView *ChainView) *ChainView {
|
|
||||||
mapIndex := f.indexedRange.maps.AfterLast()
|
|
||||||
for {
|
|
||||||
var ok bool
|
|
||||||
mapIndex, ok = f.lastMapBoundaryBefore(mapIndex)
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
lastBlockNumber, lastBlockId, err := f.getLastBlockOfMap(mapIndex)
|
lastMap := f.indexedRange.maps.Last()
|
||||||
|
lastBlockNumber, lastBlockId, err := f.getLastBlockOfMap(lastMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Could not initialize indexed chain view", "error", err)
|
log.Error("Error initializing log index database; resetting log index", "error", err)
|
||||||
break
|
f.reset()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if lastBlockNumber <= chainView.HeadNumber() && chainView.BlockId(lastBlockNumber) == lastBlockId {
|
for lastBlockNumber > f.indexedView.HeadNumber() || f.indexedView.BlockId(lastBlockNumber) != lastBlockId {
|
||||||
return chainView.limitedView(lastBlockNumber)
|
// revert last map
|
||||||
|
if f.indexedRange.maps.Count() == 1 {
|
||||||
|
f.reset() // reset database if no rendered maps remained
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
lastMap--
|
||||||
|
newRange := f.indexedRange
|
||||||
|
newRange.maps.SetLast(lastMap)
|
||||||
|
lastBlockNumber, lastBlockId, err = f.getLastBlockOfMap(lastMap)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error initializing log index database; resetting log index", "error", err)
|
||||||
|
f.reset()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newRange.blocks.SetAfterLast(lastBlockNumber) // lastBlockNumber is probably partially indexed
|
||||||
|
newRange.headIndexed = false
|
||||||
|
newRange.headDelimiter = 0
|
||||||
|
// only shorten range and leave map data; next head render will overwrite it
|
||||||
|
f.setRange(f.db, f.indexedView, newRange, false)
|
||||||
}
|
}
|
||||||
return chainView.limitedView(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset un-initializes the FilterMaps structure and removes all related data from
|
// reset un-initializes the FilterMaps structure and removes all related data from
|
||||||
|
|
@ -662,15 +667,11 @@ func (f *FilterMaps) mapRowIndex(mapIndex, rowIndex uint32) uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getBlockLvPointer returns the starting log value index where the log values
|
// getBlockLvPointer returns the starting log value index where the log values
|
||||||
// generated by the given block are located. If blockNumber is beyond the current
|
// generated by the given block are located.
|
||||||
// head then the first unoccupied log value index is returned.
|
|
||||||
//
|
//
|
||||||
// Note that this function assumes that the indexer read lock is being held when
|
// Note that this function assumes that the indexer read lock is being held when
|
||||||
// called from outside the indexerLoop goroutine.
|
// called from outside the indexerLoop goroutine.
|
||||||
func (f *FilterMaps) getBlockLvPointer(blockNumber uint64) (uint64, error) {
|
func (f *FilterMaps) getBlockLvPointer(blockNumber uint64) (uint64, error) {
|
||||||
if blockNumber >= f.indexedRange.blocks.AfterLast() && f.indexedRange.headIndexed {
|
|
||||||
return f.indexedRange.headDelimiter + 1, nil
|
|
||||||
}
|
|
||||||
if lvPointer, ok := f.lvPointerCache.Get(blockNumber); ok {
|
if lvPointer, ok := f.lvPointerCache.Get(blockNumber); ok {
|
||||||
return lvPointer, nil
|
return lvPointer, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ func (f *FilterMaps) tryIndexHead() error {
|
||||||
((!f.loggedHeadIndex && time.Since(f.startedHeadIndexAt) > headLogDelay) ||
|
((!f.loggedHeadIndex && time.Since(f.startedHeadIndexAt) > headLogDelay) ||
|
||||||
time.Since(f.lastLogHeadIndex) > logFrequency) {
|
time.Since(f.lastLogHeadIndex) > logFrequency) {
|
||||||
log.Info("Log index head rendering in progress",
|
log.Info("Log index head rendering in progress",
|
||||||
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
"firstblock", f.indexedRange.blocks.First(), "lastblock", f.indexedRange.blocks.Last(),
|
||||||
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
|
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
|
||||||
"remaining", f.indexedView.HeadNumber()-f.indexedRange.blocks.Last(),
|
"remaining", f.indexedView.HeadNumber()-f.indexedRange.blocks.Last(),
|
||||||
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
|
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
|
||||||
|
|
@ -266,7 +266,7 @@ func (f *FilterMaps) tryIndexHead() error {
|
||||||
}
|
}
|
||||||
if f.loggedHeadIndex && f.indexedRange.hasIndexedBlocks() {
|
if f.loggedHeadIndex && f.indexedRange.hasIndexedBlocks() {
|
||||||
log.Info("Log index head rendering finished",
|
log.Info("Log index head rendering finished",
|
||||||
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
"firstblock", f.indexedRange.blocks.First(), "lastblock", f.indexedRange.blocks.Last(),
|
||||||
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
|
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
|
||||||
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
|
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
|
||||||
}
|
}
|
||||||
|
|
@ -323,7 +323,7 @@ func (f *FilterMaps) tryIndexTail() (bool, error) {
|
||||||
if f.indexedRange.hasIndexedBlocks() && f.ptrTailIndex >= f.indexedRange.blocks.First() &&
|
if f.indexedRange.hasIndexedBlocks() && f.ptrTailIndex >= f.indexedRange.blocks.First() &&
|
||||||
(!f.loggedTailIndex || time.Since(f.lastLogTailIndex) > logFrequency) {
|
(!f.loggedTailIndex || time.Since(f.lastLogTailIndex) > logFrequency) {
|
||||||
log.Info("Log index tail rendering in progress",
|
log.Info("Log index tail rendering in progress",
|
||||||
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
"firstblock", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
"processed", f.ptrTailIndex-f.indexedRange.blocks.First()+tpb,
|
"processed", f.ptrTailIndex-f.indexedRange.blocks.First()+tpb,
|
||||||
"remaining", remaining,
|
"remaining", remaining,
|
||||||
"next tail epoch percentage", f.indexedRange.tailPartialEpoch*100/f.mapsPerEpoch,
|
"next tail epoch percentage", f.indexedRange.tailPartialEpoch*100/f.mapsPerEpoch,
|
||||||
|
|
@ -346,7 +346,7 @@ func (f *FilterMaps) tryIndexTail() (bool, error) {
|
||||||
}
|
}
|
||||||
if f.loggedTailIndex && f.indexedRange.hasIndexedBlocks() {
|
if f.loggedTailIndex && f.indexedRange.hasIndexedBlocks() {
|
||||||
log.Info("Log index tail rendering finished",
|
log.Info("Log index tail rendering finished",
|
||||||
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
"firstblock", f.indexedRange.blocks.First(), "lastblock", f.indexedRange.blocks.Last(),
|
||||||
"processed", f.ptrTailIndex-f.indexedRange.blocks.First(),
|
"processed", f.ptrTailIndex-f.indexedRange.blocks.First(),
|
||||||
"elapsed", common.PrettyDuration(time.Since(f.startedTailIndexAt)))
|
"elapsed", common.PrettyDuration(time.Since(f.startedTailIndexAt)))
|
||||||
f.loggedTailIndex = false
|
f.loggedTailIndex = false
|
||||||
|
|
|
||||||
|
|
@ -515,6 +515,13 @@ func (tc *testChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
|
||||||
return tc.receipts[hash]
|
return tc.receipts[hash]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tc *testChain) GetRawReceiptsByHash(hash common.Hash) types.Receipts {
|
||||||
|
tc.lock.RLock()
|
||||||
|
defer tc.lock.RUnlock()
|
||||||
|
|
||||||
|
return tc.receipts[hash]
|
||||||
|
}
|
||||||
|
|
||||||
func (tc *testChain) addBlocks(count, maxTxPerBlock, maxLogsPerReceipt, maxTopicsPerLog int, random bool) {
|
func (tc *testChain) addBlocks(count, maxTxPerBlock, maxLogsPerReceipt, maxTopicsPerLog int, random bool) {
|
||||||
tc.lock.Lock()
|
tc.lock.Lock()
|
||||||
blockGen := func(i int, gen *core.BlockGen) {
|
blockGen := func(i int, gen *core.BlockGen) {
|
||||||
|
|
|
||||||
|
|
@ -468,15 +468,25 @@ func (r *mapRenderer) writeFinishedMaps(pauseCb func() bool) error {
|
||||||
r.f.filterMapCache.Remove(mapIndex)
|
r.f.filterMapCache.Remove(mapIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var blockNumber uint64
|
||||||
|
if r.finished.First() > 0 {
|
||||||
|
// in order to always ensure continuous block pointers, initialize
|
||||||
|
// blockNumber based on the last block of the previous map, then verify
|
||||||
|
// against the first block associated with each rendered map
|
||||||
|
lastBlock, _, err := r.f.getLastBlockOfMap(r.finished.First() - 1)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get last block of previous map %d: %v", r.finished.First()-1, err)
|
||||||
|
}
|
||||||
|
blockNumber = lastBlock + 1
|
||||||
|
}
|
||||||
// add or update block pointers
|
// add or update block pointers
|
||||||
blockNumber := r.finishedMaps[r.finished.First()].firstBlock()
|
|
||||||
for mapIndex := range r.finished.Iter() {
|
for mapIndex := range r.finished.Iter() {
|
||||||
renderedMap := r.finishedMaps[mapIndex]
|
renderedMap := r.finishedMaps[mapIndex]
|
||||||
|
if blockNumber != renderedMap.firstBlock() {
|
||||||
|
return fmt.Errorf("non-continuous block numbers in rendered map %d (next expected: %d first rendered: %d)", mapIndex, blockNumber, renderedMap.firstBlock())
|
||||||
|
}
|
||||||
r.f.storeLastBlockOfMap(batch, mapIndex, renderedMap.lastBlock, renderedMap.lastBlockId)
|
r.f.storeLastBlockOfMap(batch, mapIndex, renderedMap.lastBlock, renderedMap.lastBlockId)
|
||||||
checkWriteCnt()
|
checkWriteCnt()
|
||||||
if blockNumber != renderedMap.firstBlock() {
|
|
||||||
panic("non-continuous block numbers")
|
|
||||||
}
|
|
||||||
for _, lvPtr := range renderedMap.blockLvPtrs {
|
for _, lvPtr := range renderedMap.blockLvPtrs {
|
||||||
r.f.storeBlockLvPointer(batch, blockNumber, lvPtr)
|
r.f.storeBlockLvPointer(batch, blockNumber, lvPtr)
|
||||||
checkWriteCnt()
|
checkWriteCnt()
|
||||||
|
|
@ -693,7 +703,7 @@ func (f *FilterMaps) newLogIteratorFromMapBoundary(mapIndex uint32, startBlock,
|
||||||
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", startBlock, f.targetView.HeadNumber())
|
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", startBlock, f.targetView.HeadNumber())
|
||||||
}
|
}
|
||||||
// get block receipts
|
// get block receipts
|
||||||
receipts := f.targetView.Receipts(startBlock)
|
receipts := f.targetView.RawReceipts(startBlock)
|
||||||
if receipts == nil {
|
if receipts == nil {
|
||||||
return nil, fmt.Errorf("receipts not found for start block %d", startBlock)
|
return nil, fmt.Errorf("receipts not found for start block %d", startBlock)
|
||||||
}
|
}
|
||||||
|
|
@ -760,7 +770,7 @@ func (l *logIterator) next() error {
|
||||||
if l.delimiter {
|
if l.delimiter {
|
||||||
l.delimiter = false
|
l.delimiter = false
|
||||||
l.blockNumber++
|
l.blockNumber++
|
||||||
l.receipts = l.chainView.Receipts(l.blockNumber)
|
l.receipts = l.chainView.RawReceipts(l.blockNumber)
|
||||||
if l.receipts == nil {
|
if l.receipts == nil {
|
||||||
return fmt.Errorf("receipts not found for block %d", l.blockNumber)
|
return fmt.Errorf("receipts not found for block %d", l.blockNumber)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,13 +82,26 @@ func (fm *FilterMapsMatcherBackend) GetFilterMapRow(ctx context.Context, mapInde
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlockLvPointer returns the starting log value index where the log values
|
// GetBlockLvPointer returns the starting log value index where the log values
|
||||||
// generated by the given block are located. If blockNumber is beyond the current
|
// generated by the given block are located. If blockNumber is beyond the last
|
||||||
// head then the first unoccupied log value index is returned.
|
// indexed block then the pointer will point right after this block, ensuring
|
||||||
|
// that the matcher does not fail and can return a set of results where the
|
||||||
|
// valid range is correct.
|
||||||
// GetBlockLvPointer implements MatcherBackend.
|
// GetBlockLvPointer implements MatcherBackend.
|
||||||
func (fm *FilterMapsMatcherBackend) GetBlockLvPointer(ctx context.Context, blockNumber uint64) (uint64, error) {
|
func (fm *FilterMapsMatcherBackend) GetBlockLvPointer(ctx context.Context, blockNumber uint64) (uint64, error) {
|
||||||
fm.f.indexLock.RLock()
|
fm.f.indexLock.RLock()
|
||||||
defer fm.f.indexLock.RUnlock()
|
defer fm.f.indexLock.RUnlock()
|
||||||
|
|
||||||
|
if blockNumber >= fm.f.indexedRange.blocks.AfterLast() {
|
||||||
|
if fm.f.indexedRange.headIndexed {
|
||||||
|
// return index after head block
|
||||||
|
return fm.f.indexedRange.headDelimiter + 1, nil
|
||||||
|
}
|
||||||
|
if fm.f.indexedRange.blocks.Count() > 0 {
|
||||||
|
// return index at the beginning of the last, partially indexed
|
||||||
|
// block (after the last fully indexed one)
|
||||||
|
blockNumber = fm.f.indexedRange.blocks.Last()
|
||||||
|
}
|
||||||
|
}
|
||||||
return fm.f.getBlockLvPointer(blockNumber)
|
return fm.f.getBlockLvPointer(blockNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -591,17 +591,50 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
|
||||||
hashes = append(hashes, hdr.Hash())
|
hashes = append(hashes, hdr.Hash())
|
||||||
}
|
}
|
||||||
for _, hash := range hashes {
|
for _, hash := range hashes {
|
||||||
|
// Remove the associated block body and receipts if required.
|
||||||
|
//
|
||||||
|
// If the block is in the chain freezer, then this delete operation
|
||||||
|
// is actually ineffective.
|
||||||
if delFn != nil {
|
if delFn != nil {
|
||||||
delFn(batch, hash, num)
|
delFn(batch, hash, num)
|
||||||
}
|
}
|
||||||
|
// Remove the hash->number mapping along with the header itself
|
||||||
rawdb.DeleteHeader(batch, hash, num)
|
rawdb.DeleteHeader(batch, hash, num)
|
||||||
}
|
}
|
||||||
|
// Remove the number->hash mapping
|
||||||
rawdb.DeleteCanonicalHash(batch, num)
|
rawdb.DeleteCanonicalHash(batch, num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Flush all accumulated deletions.
|
// Flush all accumulated deletions.
|
||||||
if err := batch.Write(); err != nil {
|
if err := batch.Write(); err != nil {
|
||||||
log.Crit("Failed to rewind block", "error", err)
|
log.Crit("Failed to commit batch in setHead", "err", err)
|
||||||
|
}
|
||||||
|
// Explicitly flush the pending writes in the key-value store to disk, ensuring
|
||||||
|
// data durability of the previous deletions.
|
||||||
|
if err := hc.chainDb.SyncKeyValue(); err != nil {
|
||||||
|
log.Crit("Failed to sync the key-value store in setHead", "err", err)
|
||||||
|
}
|
||||||
|
// Truncate the excessive chain segments in the ancient store.
|
||||||
|
// These are actually deferred deletions from the loop above.
|
||||||
|
//
|
||||||
|
// This step must be performed after synchronizing the key-value store;
|
||||||
|
// otherwise, in the event of a panic, it's theoretically possible to
|
||||||
|
// lose recent key-value store writes while the ancient store deletions
|
||||||
|
// remain, leading to data inconsistency, e.g., the gap between the key
|
||||||
|
// value store and ancient can be created due to unclean shutdown.
|
||||||
|
if delFn != nil {
|
||||||
|
// Ignore the error here since light client won't hit this path
|
||||||
|
frozen, _ := hc.chainDb.Ancients()
|
||||||
|
header := hc.CurrentHeader()
|
||||||
|
|
||||||
|
// Truncate the excessive chain segment above the current chain head
|
||||||
|
// in the ancient store.
|
||||||
|
if header.Number.Uint64()+1 < frozen {
|
||||||
|
_, err := hc.chainDb.TruncateHead(header.Number.Uint64() + 1)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Failed to truncate head block", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Clear out any stale content from the caches
|
// Clear out any stale content from the caches
|
||||||
hc.headerCache.Purge()
|
hc.headerCache.Purge()
|
||||||
|
|
|
||||||
|
|
@ -258,13 +258,21 @@ func ReadStateHistory(db ethdb.AncientReaderOp, id uint64) ([]byte, []byte, []by
|
||||||
// WriteStateHistory writes the provided state history to database. Compute the
|
// WriteStateHistory writes the provided state history to database. Compute the
|
||||||
// position of state history in freezer by minus one since the id of first state
|
// position of state history in freezer by minus one since the id of first state
|
||||||
// history starts from one(zero for initial state).
|
// history starts from one(zero for initial state).
|
||||||
func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) {
|
func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) error {
|
||||||
db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
_, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
||||||
op.AppendRaw(stateHistoryMeta, id-1, meta)
|
if err := op.AppendRaw(stateHistoryMeta, id-1, meta); err != nil {
|
||||||
op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex)
|
return err
|
||||||
op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex)
|
}
|
||||||
op.AppendRaw(stateHistoryAccountData, id-1, accounts)
|
if err := op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex); err != nil {
|
||||||
op.AppendRaw(stateHistoryStorageData, id-1, storages)
|
return err
|
||||||
return nil
|
}
|
||||||
|
if err := op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := op.AppendRaw(stateHistoryAccountData, id-1, accounts); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return op.AppendRaw(stateHistoryStorageData, id-1, storages)
|
||||||
})
|
})
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package rawdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
@ -45,25 +44,6 @@ const HashScheme = "hash"
|
||||||
// on extra state diffs to survive deep reorg.
|
// on extra state diffs to survive deep reorg.
|
||||||
const PathScheme = "path"
|
const PathScheme = "path"
|
||||||
|
|
||||||
// hasher is used to compute the sha256 hash of the provided data.
|
|
||||||
type hasher struct{ sha crypto.KeccakState }
|
|
||||||
|
|
||||||
var hasherPool = sync.Pool{
|
|
||||||
New: func() interface{} { return &hasher{sha: crypto.NewKeccakState()} },
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHasher() *hasher {
|
|
||||||
return hasherPool.Get().(*hasher)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *hasher) hash(data []byte) common.Hash {
|
|
||||||
return crypto.HashData(h.sha, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *hasher) release() {
|
|
||||||
hasherPool.Put(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadAccountTrieNode retrieves the account trie node with the specified node path.
|
// ReadAccountTrieNode retrieves the account trie node with the specified node path.
|
||||||
func ReadAccountTrieNode(db ethdb.KeyValueReader, path []byte) []byte {
|
func ReadAccountTrieNode(db ethdb.KeyValueReader, path []byte) []byte {
|
||||||
data, _ := db.Get(accountTrieNodeKey(path))
|
data, _ := db.Get(accountTrieNodeKey(path))
|
||||||
|
|
@ -170,9 +150,7 @@ func HasTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash c
|
||||||
if len(blob) == 0 {
|
if len(blob) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
h := newHasher()
|
return crypto.Keccak256Hash(blob) == hash // exists but not match
|
||||||
defer h.release()
|
|
||||||
return h.hash(blob) == hash // exists but not match
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Unknown scheme %v", scheme))
|
panic(fmt.Sprintf("Unknown scheme %v", scheme))
|
||||||
}
|
}
|
||||||
|
|
@ -194,9 +172,7 @@ func ReadTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash
|
||||||
if len(blob) == 0 {
|
if len(blob) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
h := newHasher()
|
if crypto.Keccak256Hash(blob) != hash {
|
||||||
defer h.release()
|
|
||||||
if h.hash(blob) != hash {
|
|
||||||
return nil // exists but not match
|
return nil // exists but not match
|
||||||
}
|
}
|
||||||
return blob
|
return blob
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Batch of blocks have been frozen, flush them before wiping from key-value store
|
// Batch of blocks have been frozen, flush them before wiping from key-value store
|
||||||
if err := f.Sync(); err != nil {
|
if err := f.SyncAncient(); err != nil {
|
||||||
log.Crit("Failed to flush frozen tables", "err", err)
|
log.Crit("Failed to flush frozen tables", "err", err)
|
||||||
}
|
}
|
||||||
// Wipe out all data from the active database
|
// Wipe out all data from the active database
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,8 @@ func (db *nofreezedb) TruncateTail(items uint64) (uint64, error) {
|
||||||
return 0, errNotSupported
|
return 0, errNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync returns an error as we don't have a backing chain freezer.
|
// SyncAncient returns an error as we don't have a backing chain freezer.
|
||||||
func (db *nofreezedb) Sync() error {
|
func (db *nofreezedb) SyncAncient() error {
|
||||||
return errNotSupported
|
return errNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -325,8 +325,8 @@ func (f *Freezer) TruncateTail(tail uint64) (uint64, error) {
|
||||||
return old, nil
|
return old, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync flushes all data tables to disk.
|
// SyncAncient flushes all data tables to disk.
|
||||||
func (f *Freezer) Sync() error {
|
func (f *Freezer) SyncAncient() error {
|
||||||
var errs []error
|
var errs []error
|
||||||
for _, table := range f.tables {
|
for _, table := range f.tables {
|
||||||
if err := table.Sync(); err != nil {
|
if err := table.Sync(); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -395,8 +395,8 @@ func (f *MemoryFreezer) TruncateTail(tail uint64) (uint64, error) {
|
||||||
return old, nil
|
return old, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync flushes all data tables to disk.
|
// SyncAncient flushes all data tables to disk.
|
||||||
func (f *MemoryFreezer) Sync() error {
|
func (f *MemoryFreezer) SyncAncient() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -194,12 +194,12 @@ func (f *resettableFreezer) TruncateTail(tail uint64) (uint64, error) {
|
||||||
return f.freezer.TruncateTail(tail)
|
return f.freezer.TruncateTail(tail)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync flushes all data tables to disk.
|
// SyncAncient flushes all data tables to disk.
|
||||||
func (f *resettableFreezer) Sync() error {
|
func (f *resettableFreezer) SyncAncient() error {
|
||||||
f.lock.RLock()
|
f.lock.RLock()
|
||||||
defer f.lock.RUnlock()
|
defer f.lock.RUnlock()
|
||||||
|
|
||||||
return f.freezer.Sync()
|
return f.freezer.SyncAncient()
|
||||||
}
|
}
|
||||||
|
|
||||||
// AncientDatadir returns the path of the ancient store.
|
// AncientDatadir returns the path of the ancient store.
|
||||||
|
|
|
||||||
|
|
@ -392,7 +392,7 @@ func TestFreezerCloseSync(t *testing.T) {
|
||||||
if err := f.Close(); err != nil {
|
if err := f.Close(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := f.Sync(); err == nil {
|
if err := f.SyncAncient(); err == nil {
|
||||||
t.Fatalf("want error, have nil")
|
t.Fatalf("want error, have nil")
|
||||||
} else if have, want := err.Error(), "[closed closed]"; have != want {
|
} else if have, want := err.Error(), "[closed closed]"; have != want {
|
||||||
t.Fatalf("want %v, have %v", have, want)
|
t.Fatalf("want %v, have %v", have, want)
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,10 @@ func (t *table) TruncateTail(items uint64) (uint64, error) {
|
||||||
return t.db.TruncateTail(items)
|
return t.db.TruncateTail(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync is a noop passthrough that just forwards the request to the underlying
|
// SyncAncient is a noop passthrough that just forwards the request to the underlying
|
||||||
// database.
|
// database.
|
||||||
func (t *table) Sync() error {
|
func (t *table) SyncAncient() error {
|
||||||
return t.db.Sync()
|
return t.db.SyncAncient()
|
||||||
}
|
}
|
||||||
|
|
||||||
// AncientDatadir returns the ancient datadir of the underlying database.
|
// AncientDatadir returns the ancient datadir of the underlying database.
|
||||||
|
|
@ -188,6 +188,12 @@ func (t *table) Compact(start []byte, limit []byte) error {
|
||||||
return t.db.Compact(start, limit)
|
return t.db.Compact(start, limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncKeyValue ensures that all pending writes are flushed to disk,
|
||||||
|
// guaranteeing data durability up to the point.
|
||||||
|
func (t *table) SyncKeyValue() error {
|
||||||
|
return t.db.SyncKeyValue()
|
||||||
|
}
|
||||||
|
|
||||||
// NewBatch creates a write-only database that buffers changes to its host db
|
// NewBatch creates a write-only database that buffers changes to its host db
|
||||||
// until a final write is called, each operation prefixing all keys with the
|
// until a final write is called, each operation prefixing all keys with the
|
||||||
// pre-configured string.
|
// pre-configured string.
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Number of codehash->size associations to keep.
|
// Number of codehash->size associations to keep.
|
||||||
codeSizeCacheSize = 100000
|
codeSizeCacheSize = 1_000_000 // 4 megabytes in total
|
||||||
|
|
||||||
// Cache size granted for caching clean code.
|
// Cache size granted for caching clean code.
|
||||||
codeCacheSize = 64 * 1024 * 1024
|
codeCacheSize = 256 * 1024 * 1024
|
||||||
|
|
||||||
// Number of address->curve point associations to keep.
|
// Number of address->curve point associations to keep.
|
||||||
pointCacheSize = 4096
|
pointCacheSize = 4096
|
||||||
|
|
@ -208,6 +208,15 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
|
||||||
return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), combined), nil
|
return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), combined), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReaderWithCache creates a state reader with internal local cache.
|
||||||
|
func (db *CachingDB) ReaderWithCache(stateRoot common.Hash) (Reader, error) {
|
||||||
|
reader, err := db.Reader(stateRoot)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return newReaderWithCache(reader), nil
|
||||||
|
}
|
||||||
|
|
||||||
// OpenTrie opens the main account trie at a specific root hash.
|
// OpenTrie opens the main account trie at a specific root hash.
|
||||||
func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||||
if db.triedb.IsVerkle() {
|
if db.triedb.IsVerkle() {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/lru"
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
|
|
@ -51,6 +52,9 @@ type ContractCodeReader interface {
|
||||||
|
|
||||||
// StateReader defines the interface for accessing accounts and storage slots
|
// StateReader defines the interface for accessing accounts and storage slots
|
||||||
// associated with a specific state.
|
// associated with a specific state.
|
||||||
|
//
|
||||||
|
// StateReader is assumed to be thread-safe and implementation must take care
|
||||||
|
// of the concurrency issue by themselves.
|
||||||
type StateReader interface {
|
type StateReader interface {
|
||||||
// Account retrieves the account associated with a particular address.
|
// Account retrieves the account associated with a particular address.
|
||||||
//
|
//
|
||||||
|
|
@ -70,6 +74,9 @@ type StateReader interface {
|
||||||
|
|
||||||
// Reader defines the interface for accessing accounts, storage slots and contract
|
// Reader defines the interface for accessing accounts, storage slots and contract
|
||||||
// code associated with a specific state.
|
// code associated with a specific state.
|
||||||
|
//
|
||||||
|
// Reader is assumed to be thread-safe and implementation must take care of the
|
||||||
|
// concurrency issue by themselves.
|
||||||
type Reader interface {
|
type Reader interface {
|
||||||
ContractCodeReader
|
ContractCodeReader
|
||||||
StateReader
|
StateReader
|
||||||
|
|
@ -77,6 +84,8 @@ type Reader interface {
|
||||||
|
|
||||||
// cachingCodeReader implements ContractCodeReader, accessing contract code either in
|
// cachingCodeReader implements ContractCodeReader, accessing contract code either in
|
||||||
// local key-value store or the shared code cache.
|
// local key-value store or the shared code cache.
|
||||||
|
//
|
||||||
|
// cachingCodeReader is safe for concurrent access.
|
||||||
type cachingCodeReader struct {
|
type cachingCodeReader struct {
|
||||||
db ethdb.KeyValueReader
|
db ethdb.KeyValueReader
|
||||||
|
|
||||||
|
|
@ -123,18 +132,14 @@ func (r *cachingCodeReader) CodeSize(addr common.Address, codeHash common.Hash)
|
||||||
return len(code), nil
|
return len(code), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// flatReader wraps a database state reader.
|
// flatReader wraps a database state reader and is safe for concurrent access.
|
||||||
type flatReader struct {
|
type flatReader struct {
|
||||||
reader database.StateReader
|
reader database.StateReader
|
||||||
buff crypto.KeccakState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFlatReader constructs a state reader with on the given state root.
|
// newFlatReader constructs a state reader with on the given state root.
|
||||||
func newFlatReader(reader database.StateReader) *flatReader {
|
func newFlatReader(reader database.StateReader) *flatReader {
|
||||||
return &flatReader{
|
return &flatReader{reader: reader}
|
||||||
reader: reader,
|
|
||||||
buff: crypto.NewKeccakState(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account implements StateReader, retrieving the account specified by the address.
|
// Account implements StateReader, retrieving the account specified by the address.
|
||||||
|
|
@ -144,7 +149,7 @@ func newFlatReader(reader database.StateReader) *flatReader {
|
||||||
//
|
//
|
||||||
// The returned account might be nil if it's not existent.
|
// The returned account might be nil if it's not existent.
|
||||||
func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) {
|
func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
account, err := r.reader.Account(crypto.HashData(r.buff, addr.Bytes()))
|
account, err := r.reader.Account(crypto.Keccak256Hash(addr.Bytes()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -174,8 +179,8 @@ func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
//
|
//
|
||||||
// The returned storage slot might be empty if it's not existent.
|
// The returned storage slot might be empty if it's not existent.
|
||||||
func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
||||||
addrHash := crypto.HashData(r.buff, addr.Bytes())
|
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||||
slotHash := crypto.HashData(r.buff, key.Bytes())
|
slotHash := crypto.Keccak256Hash(key.Bytes())
|
||||||
ret, err := r.reader.Storage(addrHash, slotHash)
|
ret, err := r.reader.Storage(addrHash, slotHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
|
|
@ -196,13 +201,20 @@ func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash,
|
||||||
|
|
||||||
// trieReader implements the StateReader interface, providing functions to access
|
// trieReader implements the StateReader interface, providing functions to access
|
||||||
// state from the referenced trie.
|
// state from the referenced trie.
|
||||||
|
//
|
||||||
|
// trieReader is safe for concurrent read.
|
||||||
type trieReader struct {
|
type trieReader struct {
|
||||||
root common.Hash // State root which uniquely represent a state
|
root common.Hash // State root which uniquely represent a state
|
||||||
db *triedb.Database // Database for loading trie
|
db *triedb.Database // Database for loading trie
|
||||||
buff crypto.KeccakState // Buffer for keccak256 hashing
|
buff crypto.KeccakState // Buffer for keccak256 hashing
|
||||||
mainTrie Trie // Main trie, resolved in constructor
|
|
||||||
|
// Main trie, resolved in constructor. Note either the Merkle-Patricia-tree
|
||||||
|
// or Verkle-tree is not safe for concurrent read.
|
||||||
|
mainTrie Trie
|
||||||
|
|
||||||
subRoots map[common.Address]common.Hash // Set of storage roots, cached when the account is resolved
|
subRoots map[common.Address]common.Hash // Set of storage roots, cached when the account is resolved
|
||||||
subTries map[common.Address]Trie // Group of storage tries, cached when it's resolved
|
subTries map[common.Address]Trie // Group of storage tries, cached when it's resolved
|
||||||
|
lock sync.Mutex // Lock for protecting concurrent read
|
||||||
}
|
}
|
||||||
|
|
||||||
// trieReader constructs a trie reader of the specific state. An error will be
|
// trieReader constructs a trie reader of the specific state. An error will be
|
||||||
|
|
@ -230,11 +242,8 @@ func newTrieReader(root common.Hash, db *triedb.Database, cache *utils.PointCach
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account implements StateReader, retrieving the account specified by the address.
|
// account is the inner version of Account and assumes the r.lock is already held.
|
||||||
//
|
func (r *trieReader) account(addr common.Address) (*types.StateAccount, error) {
|
||||||
// An error will be returned if the trie state is corrupted. An nil account
|
|
||||||
// will be returned if it's not existent in the trie.
|
|
||||||
func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) {
|
|
||||||
account, err := r.mainTrie.GetAccount(addr)
|
account, err := r.mainTrie.GetAccount(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -247,12 +256,26 @@ func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
return account, nil
|
return account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Account implements StateReader, retrieving the account specified by the address.
|
||||||
|
//
|
||||||
|
// An error will be returned if the trie state is corrupted. An nil account
|
||||||
|
// will be returned if it's not existent in the trie.
|
||||||
|
func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
r.lock.Lock()
|
||||||
|
defer r.lock.Unlock()
|
||||||
|
|
||||||
|
return r.account(addr)
|
||||||
|
}
|
||||||
|
|
||||||
// Storage implements StateReader, retrieving the storage slot specified by the
|
// Storage implements StateReader, retrieving the storage slot specified by the
|
||||||
// address and slot key.
|
// address and slot key.
|
||||||
//
|
//
|
||||||
// An error will be returned if the trie state is corrupted. An empty storage
|
// An error will be returned if the trie state is corrupted. An empty storage
|
||||||
// slot will be returned if it's not existent in the trie.
|
// slot will be returned if it's not existent in the trie.
|
||||||
func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
||||||
|
r.lock.Lock()
|
||||||
|
defer r.lock.Unlock()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tr Trie
|
tr Trie
|
||||||
found bool
|
found bool
|
||||||
|
|
@ -268,7 +291,7 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash,
|
||||||
// The storage slot is accessed without account caching. It's unexpected
|
// The storage slot is accessed without account caching. It's unexpected
|
||||||
// behavior but try to resolve the account first anyway.
|
// behavior but try to resolve the account first anyway.
|
||||||
if !ok {
|
if !ok {
|
||||||
_, err := r.Account(addr)
|
_, err := r.account(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -293,6 +316,9 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash,
|
||||||
// multiStateReader is the aggregation of a list of StateReader interface,
|
// multiStateReader is the aggregation of a list of StateReader interface,
|
||||||
// providing state access by leveraging all readers. The checking priority
|
// providing state access by leveraging all readers. The checking priority
|
||||||
// is determined by the position in the reader list.
|
// is determined by the position in the reader list.
|
||||||
|
//
|
||||||
|
// multiStateReader is safe for concurrent read and assumes all underlying
|
||||||
|
// readers are thread-safe as well.
|
||||||
type multiStateReader struct {
|
type multiStateReader struct {
|
||||||
readers []StateReader // List of state readers, sorted by checking priority
|
readers []StateReader // List of state readers, sorted by checking priority
|
||||||
}
|
}
|
||||||
|
|
@ -358,3 +384,95 @@ func newReader(codeReader ContractCodeReader, stateReader StateReader) *reader {
|
||||||
StateReader: stateReader,
|
StateReader: stateReader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readerWithCache is a wrapper around Reader that maintains additional state caches
|
||||||
|
// to support concurrent state access.
|
||||||
|
type readerWithCache struct {
|
||||||
|
Reader // safe for concurrent read
|
||||||
|
|
||||||
|
// Previously resolved state entries.
|
||||||
|
accounts map[common.Address]*types.StateAccount
|
||||||
|
accountLock sync.RWMutex
|
||||||
|
|
||||||
|
// List of storage buckets, each of which is thread-safe.
|
||||||
|
// This reader is typically used in scenarios requiring concurrent
|
||||||
|
// access to storage. Using multiple buckets helps mitigate
|
||||||
|
// the overhead caused by locking.
|
||||||
|
storageBuckets [16]struct {
|
||||||
|
lock sync.RWMutex
|
||||||
|
storages map[common.Address]map[common.Hash]common.Hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newReaderWithCache constructs the reader with local cache.
|
||||||
|
func newReaderWithCache(reader Reader) *readerWithCache {
|
||||||
|
r := &readerWithCache{
|
||||||
|
Reader: reader,
|
||||||
|
accounts: make(map[common.Address]*types.StateAccount),
|
||||||
|
}
|
||||||
|
for i := range r.storageBuckets {
|
||||||
|
r.storageBuckets[i].storages = make(map[common.Address]map[common.Hash]common.Hash)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account implements StateReader, retrieving the account specified by the address.
|
||||||
|
// The returned account might be nil if it's not existent.
|
||||||
|
//
|
||||||
|
// An error will be returned if the state is corrupted in the underlying reader.
|
||||||
|
func (r *readerWithCache) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
// Try to resolve the requested account in the local cache
|
||||||
|
r.accountLock.RLock()
|
||||||
|
acct, ok := r.accounts[addr]
|
||||||
|
r.accountLock.RUnlock()
|
||||||
|
if ok {
|
||||||
|
return acct, nil
|
||||||
|
}
|
||||||
|
// Try to resolve the requested account from the underlying reader
|
||||||
|
acct, err := r.Reader.Account(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r.accountLock.Lock()
|
||||||
|
r.accounts[addr] = acct
|
||||||
|
r.accountLock.Unlock()
|
||||||
|
return acct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implements StateReader, retrieving the storage slot specified by the
|
||||||
|
// address and slot key. The returned storage slot might be empty if it's not
|
||||||
|
// existent.
|
||||||
|
//
|
||||||
|
// An error will be returned if the state is corrupted in the underlying reader.
|
||||||
|
func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common.Hash, error) {
|
||||||
|
var (
|
||||||
|
value common.Hash
|
||||||
|
ok bool
|
||||||
|
bucket = &r.storageBuckets[addr[0]&0x0f]
|
||||||
|
)
|
||||||
|
// Try to resolve the requested storage slot in the local cache
|
||||||
|
bucket.lock.RLock()
|
||||||
|
slots, ok := bucket.storages[addr]
|
||||||
|
if ok {
|
||||||
|
value, ok = slots[slot]
|
||||||
|
}
|
||||||
|
bucket.lock.RUnlock()
|
||||||
|
if ok {
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
// Try to resolve the requested storage slot from the underlying reader
|
||||||
|
value, err := r.Reader.Storage(addr, slot)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
bucket.lock.Lock()
|
||||||
|
slots, ok = bucket.storages[addr]
|
||||||
|
if !ok {
|
||||||
|
slots = make(map[common.Hash]common.Hash)
|
||||||
|
bucket.storages[addr] = slots
|
||||||
|
}
|
||||||
|
slots[slot] = value
|
||||||
|
bucket.lock.Unlock()
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,11 +159,17 @@ type StateDB struct {
|
||||||
|
|
||||||
// New creates a new state from a given trie.
|
// New creates a new state from a given trie.
|
||||||
func New(root common.Hash, db Database) (*StateDB, error) {
|
func New(root common.Hash, db Database) (*StateDB, error) {
|
||||||
tr, err := db.OpenTrie(root)
|
reader, err := db.Reader(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
reader, err := db.Reader(root)
|
return NewWithReader(root, db, reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithReader creates a new state for the specified state root. Unlike New,
|
||||||
|
// this function accepts an additional Reader which is bound to the given root.
|
||||||
|
func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, error) {
|
||||||
|
tr, err := db.OpenTrie(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -392,6 +398,12 @@ func (s *StateDB) Database() Database {
|
||||||
return s.db
|
return s.db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reader retrieves the low level database reader supporting the
|
||||||
|
// lower level operations.
|
||||||
|
func (s *StateDB) Reader() Reader {
|
||||||
|
return s.reader
|
||||||
|
}
|
||||||
|
|
||||||
func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
|
func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
|
||||||
stateObject := s.getStateObject(addr)
|
stateObject := s.getStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
|
|
@ -650,11 +662,10 @@ func (s *StateDB) CreateContract(addr common.Address) {
|
||||||
// Snapshots of the copied state cannot be applied to the copy.
|
// Snapshots of the copied state cannot be applied to the copy.
|
||||||
func (s *StateDB) Copy() *StateDB {
|
func (s *StateDB) Copy() *StateDB {
|
||||||
// Copy all the basic fields, initialize the memory ones
|
// Copy all the basic fields, initialize the memory ones
|
||||||
reader, _ := s.db.Reader(s.originalRoot) // impossible to fail
|
|
||||||
state := &StateDB{
|
state := &StateDB{
|
||||||
db: s.db,
|
db: s.db,
|
||||||
trie: mustCopyTrie(s.trie),
|
trie: mustCopyTrie(s.trie),
|
||||||
reader: reader,
|
reader: s.reader,
|
||||||
originalRoot: s.originalRoot,
|
originalRoot: s.originalRoot,
|
||||||
stateObjects: make(map[common.Address]*stateObject, len(s.stateObjects)),
|
stateObjects: make(map[common.Address]*stateObject, len(s.stateObjects)),
|
||||||
stateObjectsDestruct: make(map[common.Address]*stateObject, len(s.stateObjectsDestruct)),
|
stateObjectsDestruct: make(map[common.Address]*stateObject, len(s.stateObjectsDestruct)),
|
||||||
|
|
|
||||||
|
|
@ -17,17 +17,22 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"runtime"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"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/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// statePrefetcher is a basic Prefetcher, which blindly executes a block on top
|
// statePrefetcher is a basic Prefetcher that executes transactions from a block
|
||||||
// of an arbitrary state with the goal of prefetching potentially useful state
|
// on top of the parent state, aiming to prefetch potentially useful state data
|
||||||
// data from disk before the main block processor start executing.
|
// from disk. Transactions are executed in parallel to fully leverage the
|
||||||
|
// SSD's read performance.
|
||||||
type statePrefetcher struct {
|
type statePrefetcher struct {
|
||||||
config *params.ChainConfig // Chain configuration options
|
config *params.ChainConfig // Chain configuration options
|
||||||
chain *HeaderChain // Canonical block chain
|
chain *HeaderChain // Canonical block chain
|
||||||
|
|
@ -43,41 +48,81 @@ func newStatePrefetcher(config *params.ChainConfig, chain *HeaderChain) *statePr
|
||||||
|
|
||||||
// Prefetch processes the state changes according to the Ethereum rules by running
|
// Prefetch processes the state changes according to the Ethereum rules by running
|
||||||
// the transaction messages using the statedb, but any changes are discarded. The
|
// the transaction messages using the statedb, but any changes are discarded. The
|
||||||
// only goal is to pre-cache transaction signatures and state trie nodes.
|
// only goal is to warm the state caches.
|
||||||
func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) {
|
func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) {
|
||||||
var (
|
var (
|
||||||
|
fails atomic.Int64
|
||||||
header = block.Header()
|
header = block.Header()
|
||||||
gaspool = new(GasPool).AddGas(block.GasLimit())
|
|
||||||
blockContext = NewEVMBlockContext(header, p.chain, nil)
|
|
||||||
evm = vm.NewEVM(blockContext, statedb, p.config, cfg)
|
|
||||||
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||||
|
workers errgroup.Group
|
||||||
|
reader = statedb.Reader()
|
||||||
)
|
)
|
||||||
|
workers.SetLimit(runtime.NumCPU() / 2)
|
||||||
|
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
byzantium := p.config.IsByzantium(block.Number())
|
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
|
stateCpy := statedb.Copy() // closure
|
||||||
|
workers.Go(func() error {
|
||||||
// If block precaching was interrupted, abort
|
// If block precaching was interrupted, abort
|
||||||
if interrupt != nil && interrupt.Load() {
|
if interrupt != nil && interrupt.Load() {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
// Preload the touched accounts and storage slots in advance
|
||||||
|
sender, err := types.Sender(signer, tx)
|
||||||
|
if err != nil {
|
||||||
|
fails.Add(1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
reader.Account(sender)
|
||||||
|
|
||||||
|
if tx.To() != nil {
|
||||||
|
account, _ := reader.Account(*tx.To())
|
||||||
|
|
||||||
|
// Preload the contract code if the destination has non-empty code
|
||||||
|
if account != nil && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
|
||||||
|
reader.Code(*tx.To(), common.BytesToHash(account.CodeHash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, list := range tx.AccessList() {
|
||||||
|
reader.Account(list.Address)
|
||||||
|
if len(list.StorageKeys) > 0 {
|
||||||
|
for _, slot := range list.StorageKeys {
|
||||||
|
reader.Storage(list.Address, slot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Execute the message to preload the implicit touched states
|
||||||
|
evm := vm.NewEVM(NewEVMBlockContext(header, p.chain, nil), stateCpy, p.config, cfg)
|
||||||
|
|
||||||
// Convert the transaction into an executable message and pre-cache its sender
|
// Convert the transaction into an executable message and pre-cache its sender
|
||||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return // Also invalid block, bail out
|
fails.Add(1)
|
||||||
|
return nil // Also invalid block, bail out
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
// Disable the nonce check
|
||||||
|
msg.SkipNonceChecks = true
|
||||||
|
|
||||||
|
stateCpy.SetTxContext(tx.Hash(), i)
|
||||||
|
|
||||||
// We attempt to apply a transaction. The goal is not to execute
|
// We attempt to apply a transaction. The goal is not to execute
|
||||||
// the transaction successfully, rather to warm up touched data slots.
|
// the transaction successfully, rather to warm up touched data slots.
|
||||||
if _, err := ApplyMessage(evm, msg, gaspool); err != nil {
|
if _, err := ApplyMessage(evm, msg, new(GasPool).AddGas(block.GasLimit())); err != nil {
|
||||||
return // Ugh, something went horribly wrong, bail out
|
fails.Add(1)
|
||||||
|
return nil // Ugh, something went horribly wrong, bail out
|
||||||
}
|
}
|
||||||
// If we're pre-byzantium, pre-load trie nodes for the intermediate root
|
// Pre-load trie nodes for the intermediate root.
|
||||||
if !byzantium {
|
//
|
||||||
statedb.IntermediateRoot(true)
|
// This operation incurs significant memory allocations due to
|
||||||
}
|
// trie hashing and node decoding. TODO(rjl493456442): investigate
|
||||||
}
|
// ways to mitigate this overhead.
|
||||||
// If were post-byzantium, pre-load trie nodes for the final root hash
|
stateCpy.IntermediateRoot(true)
|
||||||
if byzantium {
|
return nil
|
||||||
statedb.IntermediateRoot(true)
|
})
|
||||||
}
|
}
|
||||||
|
workers.Wait()
|
||||||
|
|
||||||
|
blockPrefetchTxsValidMeter.Mark(int64(len(block.Transactions())) - fails.Load())
|
||||||
|
blockPrefetchTxsInvalidMeter.Mark(fails.Load())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ import (
|
||||||
// message no matter the execution itself is successful or not.
|
// message no matter the execution itself is successful or not.
|
||||||
type ExecutionResult struct {
|
type ExecutionResult struct {
|
||||||
UsedGas uint64 // Total used gas, not including the refunded gas
|
UsedGas uint64 // Total used gas, not including the refunded gas
|
||||||
RefundedGas uint64 // Total gas refunded after execution
|
MaxUsedGas uint64 // Maximum gas consumed during execution, excluding gas refunds.
|
||||||
Err error // Any error encountered during the execution(listed in core/vm/errors.go)
|
Err error // Any error encountered during the execution(listed in core/vm/errors.go)
|
||||||
ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode)
|
ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode)
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +159,9 @@ type Message struct {
|
||||||
|
|
||||||
// When SkipNonceChecks is true, the message nonce is not checked against the
|
// When SkipNonceChecks is true, the message nonce is not checked against the
|
||||||
// account nonce in state.
|
// account nonce in state.
|
||||||
// This field will be set to true for operations like RPC eth_call.
|
//
|
||||||
|
// This field will be set to true for operations like RPC eth_call
|
||||||
|
// or the state prefetching.
|
||||||
SkipNonceChecks bool
|
SkipNonceChecks bool
|
||||||
|
|
||||||
// When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
|
// When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
|
||||||
|
|
@ -509,9 +511,12 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
ret, st.gasRemaining, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining, value)
|
ret, st.gasRemaining, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record the gas used excluding gas refunds. This value represents the actual
|
||||||
|
// gas allowance required to complete execution.
|
||||||
|
peakGasUsed := st.gasUsed()
|
||||||
|
|
||||||
// Compute refund counter, capped to a refund quotient.
|
// Compute refund counter, capped to a refund quotient.
|
||||||
gasRefund := st.calcRefund()
|
st.gasRemaining += st.calcRefund()
|
||||||
st.gasRemaining += gasRefund
|
|
||||||
if rules.IsPrague {
|
if rules.IsPrague {
|
||||||
// After EIP-7623: Data-heavy transactions pay the floor gas.
|
// After EIP-7623: Data-heavy transactions pay the floor gas.
|
||||||
if st.gasUsed() < floorDataGas {
|
if st.gasUsed() < floorDataGas {
|
||||||
|
|
@ -521,6 +526,9 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
t.OnGasChange(prev, st.gasRemaining, tracing.GasChangeTxDataFloor)
|
t.OnGasChange(prev, st.gasRemaining, tracing.GasChangeTxDataFloor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if peakGasUsed < floorDataGas {
|
||||||
|
peakGasUsed = floorDataGas
|
||||||
|
}
|
||||||
}
|
}
|
||||||
st.returnGas()
|
st.returnGas()
|
||||||
|
|
||||||
|
|
@ -550,7 +558,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
|
|
||||||
return &ExecutionResult{
|
return &ExecutionResult{
|
||||||
UsedGas: st.gasUsed(),
|
UsedGas: st.gasUsed(),
|
||||||
RefundedGas: gasRefund,
|
MaxUsedGas: peakGasUsed,
|
||||||
Err: vmerr,
|
Err: vmerr,
|
||||||
ReturnData: ret,
|
ReturnData: ret,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
|
@ -47,11 +47,21 @@ type txIndexer struct {
|
||||||
// and all others shouldn't.
|
// and all others shouldn't.
|
||||||
limit uint64
|
limit uint64
|
||||||
|
|
||||||
|
// The current head of blockchain for transaction indexing. This field
|
||||||
|
// is accessed by both the indexer and the indexing progress queries.
|
||||||
|
head atomic.Uint64
|
||||||
|
|
||||||
|
// The current tail of the indexed transactions, null indicates
|
||||||
|
// that no transactions have been indexed yet.
|
||||||
|
//
|
||||||
|
// This field is accessed by both the indexer and the indexing
|
||||||
|
// progress queries.
|
||||||
|
tail atomic.Pointer[uint64]
|
||||||
|
|
||||||
// cutoff denotes the block number before which the chain segment should
|
// cutoff denotes the block number before which the chain segment should
|
||||||
// be pruned and not available locally.
|
// be pruned and not available locally.
|
||||||
cutoff uint64
|
cutoff uint64
|
||||||
db ethdb.Database
|
db ethdb.Database
|
||||||
progress chan chan TxIndexProgress
|
|
||||||
term chan chan struct{}
|
term chan chan struct{}
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
@ -63,10 +73,12 @@ func newTxIndexer(limit uint64, chain *BlockChain) *txIndexer {
|
||||||
limit: limit,
|
limit: limit,
|
||||||
cutoff: cutoff,
|
cutoff: cutoff,
|
||||||
db: chain.db,
|
db: chain.db,
|
||||||
progress: make(chan chan TxIndexProgress),
|
|
||||||
term: make(chan chan struct{}),
|
term: make(chan chan struct{}),
|
||||||
closed: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
indexer.head.Store(indexer.resolveHead())
|
||||||
|
indexer.tail.Store(rawdb.ReadTxIndexTail(chain.db))
|
||||||
|
|
||||||
go indexer.loop(chain)
|
go indexer.loop(chain)
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
|
|
@ -154,6 +166,7 @@ func (indexer *txIndexer) repair(head uint64) {
|
||||||
// A crash may occur between the two delete operations,
|
// A crash may occur between the two delete operations,
|
||||||
// potentially leaving dangling indexes in the database.
|
// potentially leaving dangling indexes in the database.
|
||||||
// However, this is considered acceptable.
|
// However, this is considered acceptable.
|
||||||
|
indexer.tail.Store(nil)
|
||||||
rawdb.DeleteTxIndexTail(indexer.db)
|
rawdb.DeleteTxIndexTail(indexer.db)
|
||||||
rawdb.DeleteAllTxLookupEntries(indexer.db, nil)
|
rawdb.DeleteAllTxLookupEntries(indexer.db, nil)
|
||||||
log.Warn("Purge transaction indexes", "head", head, "tail", *tail)
|
log.Warn("Purge transaction indexes", "head", head, "tail", *tail)
|
||||||
|
|
@ -174,6 +187,7 @@ func (indexer *txIndexer) repair(head uint64) {
|
||||||
// Traversing the database directly within the transaction
|
// Traversing the database directly within the transaction
|
||||||
// index namespace might be slow and expensive, but we
|
// index namespace might be slow and expensive, but we
|
||||||
// have no choice.
|
// have no choice.
|
||||||
|
indexer.tail.Store(nil)
|
||||||
rawdb.DeleteTxIndexTail(indexer.db)
|
rawdb.DeleteTxIndexTail(indexer.db)
|
||||||
rawdb.DeleteAllTxLookupEntries(indexer.db, nil)
|
rawdb.DeleteAllTxLookupEntries(indexer.db, nil)
|
||||||
log.Warn("Purge transaction indexes", "head", head, "cutoff", indexer.cutoff)
|
log.Warn("Purge transaction indexes", "head", head, "cutoff", indexer.cutoff)
|
||||||
|
|
@ -187,6 +201,7 @@ func (indexer *txIndexer) repair(head uint64) {
|
||||||
// A crash may occur between the two delete operations,
|
// A crash may occur between the two delete operations,
|
||||||
// potentially leaving dangling indexes in the database.
|
// potentially leaving dangling indexes in the database.
|
||||||
// However, this is considered acceptable.
|
// However, this is considered acceptable.
|
||||||
|
indexer.tail.Store(&indexer.cutoff)
|
||||||
rawdb.WriteTxIndexTail(indexer.db, indexer.cutoff)
|
rawdb.WriteTxIndexTail(indexer.db, indexer.cutoff)
|
||||||
rawdb.DeleteAllTxLookupEntries(indexer.db, func(txhash common.Hash, blob []byte) bool {
|
rawdb.DeleteAllTxLookupEntries(indexer.db, func(txhash common.Hash, blob []byte) bool {
|
||||||
n := rawdb.DecodeTxLookupEntry(blob, indexer.db)
|
n := rawdb.DecodeTxLookupEntry(blob, indexer.db)
|
||||||
|
|
@ -218,14 +233,13 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
|
||||||
var (
|
var (
|
||||||
stop chan struct{} // Non-nil if background routine is active
|
stop chan struct{} // Non-nil if background routine is active
|
||||||
done chan struct{} // Non-nil if background routine is active
|
done chan struct{} // Non-nil if background routine is active
|
||||||
head = indexer.resolveHead() // The latest announced chain head
|
|
||||||
|
|
||||||
headCh = make(chan ChainHeadEvent)
|
headCh = make(chan ChainHeadEvent)
|
||||||
sub = chain.SubscribeChainHeadEvent(headCh)
|
sub = chain.SubscribeChainHeadEvent(headCh)
|
||||||
)
|
)
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
// Validate the transaction indexes and repair if necessary
|
// Validate the transaction indexes and repair if necessary
|
||||||
|
head := indexer.head.Load()
|
||||||
indexer.repair(head)
|
indexer.repair(head)
|
||||||
|
|
||||||
// Launch the initial processing if chain is not empty (head != genesis).
|
// Launch the initial processing if chain is not empty (head != genesis).
|
||||||
|
|
@ -238,17 +252,18 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case h := <-headCh:
|
case h := <-headCh:
|
||||||
|
indexer.head.Store(h.Header.Number.Uint64())
|
||||||
if done == nil {
|
if done == nil {
|
||||||
stop = make(chan struct{})
|
stop = make(chan struct{})
|
||||||
done = make(chan struct{})
|
done = make(chan struct{})
|
||||||
go indexer.run(h.Header.Number.Uint64(), stop, done)
|
go indexer.run(h.Header.Number.Uint64(), stop, done)
|
||||||
}
|
}
|
||||||
head = h.Header.Number.Uint64()
|
|
||||||
case <-done:
|
case <-done:
|
||||||
stop = nil
|
stop = nil
|
||||||
done = nil
|
done = nil
|
||||||
case ch := <-indexer.progress:
|
indexer.tail.Store(rawdb.ReadTxIndexTail(indexer.db))
|
||||||
ch <- indexer.report(head)
|
|
||||||
case ch := <-indexer.term:
|
case ch := <-indexer.term:
|
||||||
if stop != nil {
|
if stop != nil {
|
||||||
close(stop)
|
close(stop)
|
||||||
|
|
@ -264,7 +279,7 @@ func (indexer *txIndexer) loop(chain *BlockChain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// report returns the tx indexing progress.
|
// report returns the tx indexing progress.
|
||||||
func (indexer *txIndexer) report(head uint64) TxIndexProgress {
|
func (indexer *txIndexer) report(head uint64, tail *uint64) TxIndexProgress {
|
||||||
// Special case if the head is even below the cutoff,
|
// Special case if the head is even below the cutoff,
|
||||||
// nothing to index.
|
// nothing to index.
|
||||||
if head < indexer.cutoff {
|
if head < indexer.cutoff {
|
||||||
|
|
@ -284,7 +299,6 @@ func (indexer *txIndexer) report(head uint64) TxIndexProgress {
|
||||||
}
|
}
|
||||||
// Compute how many blocks have been indexed
|
// Compute how many blocks have been indexed
|
||||||
var indexed uint64
|
var indexed uint64
|
||||||
tail := rawdb.ReadTxIndexTail(indexer.db)
|
|
||||||
if tail != nil {
|
if tail != nil {
|
||||||
indexed = head - *tail + 1
|
indexed = head - *tail + 1
|
||||||
}
|
}
|
||||||
|
|
@ -300,16 +314,12 @@ func (indexer *txIndexer) report(head uint64) TxIndexProgress {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// txIndexProgress retrieves the tx indexing progress, or an error if the
|
// txIndexProgress retrieves the transaction indexing progress. The reported
|
||||||
// background tx indexer is already stopped.
|
// progress may slightly lag behind the actual indexing state, as the tail is
|
||||||
func (indexer *txIndexer) txIndexProgress() (TxIndexProgress, error) {
|
// only updated at the end of each indexing operation. However, this delay is
|
||||||
ch := make(chan TxIndexProgress, 1)
|
// considered acceptable.
|
||||||
select {
|
func (indexer *txIndexer) txIndexProgress() TxIndexProgress {
|
||||||
case indexer.progress <- ch:
|
return indexer.report(indexer.head.Load(), indexer.tail.Load())
|
||||||
return <-ch, nil
|
|
||||||
case <-indexer.closed:
|
|
||||||
return TxIndexProgress{}, errors.New("indexer is closed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// close shutdown the indexer. Safe to be called for multiple times.
|
// close shutdown the indexer. Safe to be called for multiple times.
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,6 @@ func TestTxIndexer(t *testing.T) {
|
||||||
indexer := &txIndexer{
|
indexer := &txIndexer{
|
||||||
limit: 0,
|
limit: 0,
|
||||||
db: db,
|
db: db,
|
||||||
progress: make(chan chan TxIndexProgress),
|
|
||||||
}
|
}
|
||||||
for i, limit := range c.limits {
|
for i, limit := range c.limits {
|
||||||
indexer.limit = limit
|
indexer.limit = limit
|
||||||
|
|
@ -243,7 +242,6 @@ func TestTxIndexerRepair(t *testing.T) {
|
||||||
indexer := &txIndexer{
|
indexer := &txIndexer{
|
||||||
limit: c.limit,
|
limit: c.limit,
|
||||||
db: db,
|
db: db,
|
||||||
progress: make(chan chan TxIndexProgress),
|
|
||||||
}
|
}
|
||||||
indexer.run(chainHead, make(chan struct{}), make(chan struct{}))
|
indexer.run(chainHead, make(chan struct{}), make(chan struct{}))
|
||||||
|
|
||||||
|
|
@ -435,12 +433,8 @@ func TestTxIndexerReport(t *testing.T) {
|
||||||
limit: c.limit,
|
limit: c.limit,
|
||||||
cutoff: c.cutoff,
|
cutoff: c.cutoff,
|
||||||
db: db,
|
db: db,
|
||||||
progress: make(chan chan TxIndexProgress),
|
|
||||||
}
|
}
|
||||||
if c.tail != nil {
|
p := indexer.report(c.head, c.tail)
|
||||||
rawdb.WriteTxIndexTail(db, *c.tail)
|
|
||||||
}
|
|
||||||
p := indexer.report(c.head)
|
|
||||||
if p.Indexed != c.expIndexed {
|
if p.Indexed != c.expIndexed {
|
||||||
t.Fatalf("Unexpected indexed: %d, expected: %d", p.Indexed, c.expIndexed)
|
t.Fatalf("Unexpected indexed: %d, expected: %d", p.Indexed, c.expIndexed)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1939,7 +1939,7 @@ func (pool *LegacyPool) Clear() {
|
||||||
pool.reserver.Release(addr)
|
pool.reserver.Release(addr)
|
||||||
}
|
}
|
||||||
pool.all.Clear()
|
pool.all.Clear()
|
||||||
pool.priced = newPricedList(pool.all)
|
pool.priced.Reheap()
|
||||||
pool.pending = make(map[common.Address]*list)
|
pool.pending = make(map[common.Address]*list)
|
||||||
pool.queue = make(map[common.Address]*list)
|
pool.queue = make(map[common.Address]*list)
|
||||||
pool.pendingNonces = newNoncer(pool.currentState)
|
pool.pendingNonces = newNoncer(pool.currentState)
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,9 @@ func validateBlobSidecarOsaka(hashes []common.Hash, sidecar *types.BlobTxSidecar
|
||||||
if len(sidecar.Blobs) != len(hashes) {
|
if len(sidecar.Blobs) != len(hashes) {
|
||||||
return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(sidecar.Blobs), len(hashes))
|
return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(sidecar.Blobs), len(hashes))
|
||||||
}
|
}
|
||||||
|
if len(sidecar.Commitments) != len(hashes) {
|
||||||
|
return fmt.Errorf("invalid number of %d commitments compared to %d blob hashes", len(sidecar.Commitments), len(hashes))
|
||||||
|
}
|
||||||
if len(sidecar.Proofs) != len(hashes)*kzg4844.CellProofsPerBlob {
|
if len(sidecar.Proofs) != len(hashes)*kzg4844.CellProofsPerBlob {
|
||||||
return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes)*kzg4844.CellProofsPerBlob)
|
return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes)*kzg4844.CellProofsPerBlob)
|
||||||
}
|
}
|
||||||
|
|
@ -210,14 +213,13 @@ func validateBlobSidecarOsaka(hashes []common.Hash, sidecar *types.BlobTxSidecar
|
||||||
}
|
}
|
||||||
// Blob commitments match with the hashes in the transaction, verify the
|
// Blob commitments match with the hashes in the transaction, verify the
|
||||||
// blobs themselves via KZG
|
// blobs themselves via KZG
|
||||||
for i := range sidecar.Blobs {
|
var blobs []*kzg4844.Blob
|
||||||
// TODO verify the cell proof here
|
for _, blob := range sidecar.Blobs {
|
||||||
_ = i
|
blobs = append(blobs, &blob)
|
||||||
/*
|
|
||||||
if err := kzg4844.VerifyBlobProof(&sidecar.Blobs[i], sidecar.Commitments[i], sidecar.Proofs[i]); err != nil {
|
|
||||||
return fmt.Errorf("invalid blob %d: %v", i, err)
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
if err := kzg4844.VerifyCellProofs(blobs, sidecar.Commitments, sidecar.Proofs); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,6 @@ type Account struct {
|
||||||
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
|
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
|
||||||
Balance *big.Int `json:"balance" gencodec:"required"`
|
Balance *big.Int `json:"balance" gencodec:"required"`
|
||||||
Nonce uint64 `json:"nonce,omitempty"`
|
Nonce uint64 `json:"nonce,omitempty"`
|
||||||
|
|
||||||
// used in tests
|
|
||||||
PrivateKey []byte `json:"secretKey,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type accountMarshaling struct {
|
type accountMarshaling struct {
|
||||||
|
|
@ -48,7 +45,6 @@ type accountMarshaling struct {
|
||||||
Balance *math.HexOrDecimal256
|
Balance *math.HexOrDecimal256
|
||||||
Nonce math.HexOrDecimal64
|
Nonce math.HexOrDecimal64
|
||||||
Storage map[storageJSON]storageJSON
|
Storage map[storageJSON]storageJSON
|
||||||
PrivateKey hexutil.Bytes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storageJSON represents a 256 bit byte array, but allows less than 256 bits when
|
// storageJSON represents a 256 bit byte array, but allows less than 256 bits when
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ func (a Account) MarshalJSON() ([]byte, error) {
|
||||||
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
|
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
|
||||||
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
|
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
|
||||||
Nonce math.HexOrDecimal64 `json:"nonce,omitempty"`
|
Nonce math.HexOrDecimal64 `json:"nonce,omitempty"`
|
||||||
PrivateKey hexutil.Bytes `json:"secretKey,omitempty"`
|
|
||||||
}
|
}
|
||||||
var enc Account
|
var enc Account
|
||||||
enc.Code = a.Code
|
enc.Code = a.Code
|
||||||
|
|
@ -33,7 +32,6 @@ func (a Account) MarshalJSON() ([]byte, error) {
|
||||||
}
|
}
|
||||||
enc.Balance = (*math.HexOrDecimal256)(a.Balance)
|
enc.Balance = (*math.HexOrDecimal256)(a.Balance)
|
||||||
enc.Nonce = math.HexOrDecimal64(a.Nonce)
|
enc.Nonce = math.HexOrDecimal64(a.Nonce)
|
||||||
enc.PrivateKey = a.PrivateKey
|
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +42,6 @@ func (a *Account) UnmarshalJSON(input []byte) error {
|
||||||
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
|
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
|
||||||
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
|
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
|
||||||
Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"`
|
Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"`
|
||||||
PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"`
|
|
||||||
}
|
}
|
||||||
var dec Account
|
var dec Account
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -66,8 +63,5 @@ func (a *Account) UnmarshalJSON(input []byte) error {
|
||||||
if dec.Nonce != nil {
|
if dec.Nonce != nil {
|
||||||
a.Nonce = uint64(*dec.Nonce)
|
a.Nonce = uint64(*dec.Nonce)
|
||||||
}
|
}
|
||||||
if dec.PrivateKey != nil {
|
|
||||||
a.PrivateKey = *dec.PrivateKey
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,11 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"golang.org/x/crypto/sha3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// hasherPool holds LegacyKeccak256 hashers for rlpHash.
|
// hasherPool holds LegacyKeccak256 hashers for rlpHash.
|
||||||
var hasherPool = sync.Pool{
|
var hasherPool = sync.Pool{
|
||||||
New: func() interface{} { return sha3.NewLegacyKeccak256() },
|
New: func() interface{} { return crypto.NewKeccakState() },
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding.
|
// encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding.
|
||||||
|
|
|
||||||
|
|
@ -555,7 +555,8 @@ func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *ui
|
||||||
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
|
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
|
||||||
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
|
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
|
||||||
func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
||||||
contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), crypto.Keccak256(code))
|
inithash := crypto.HashData(evm.interpreter.hasher, code)
|
||||||
|
contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), inithash[:])
|
||||||
return evm.create(caller, code, gas, endowment, contractAddr, CREATE2)
|
return evm.create(caller, code, gas, endowment, contractAddr, CREATE2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
@ -234,11 +233,7 @@ func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
|
||||||
offset, size := scope.Stack.pop(), scope.Stack.peek()
|
offset, size := scope.Stack.pop(), scope.Stack.peek()
|
||||||
data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64())
|
data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64())
|
||||||
|
|
||||||
if interpreter.hasher == nil {
|
|
||||||
interpreter.hasher = crypto.NewKeccakState()
|
|
||||||
} else {
|
|
||||||
interpreter.hasher.Reset()
|
interpreter.hasher.Reset()
|
||||||
}
|
|
||||||
interpreter.hasher.Write(data)
|
interpreter.hasher.Write(data)
|
||||||
interpreter.hasher.Read(interpreter.hasherBuf[:])
|
interpreter.hasher.Read(interpreter.hasherBuf[:])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
evm.Config.ExtraEips = extraEips
|
evm.Config.ExtraEips = extraEips
|
||||||
return &EVMInterpreter{evm: evm, table: table}
|
return &EVMInterpreter{evm: evm, table: table, hasher: crypto.NewKeccakState()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run loops and evaluates the contract's code with the given input data and returns
|
// Run loops and evaluates the contract's code with the given input data and returns
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
|
@ -73,6 +74,12 @@ func NewKeccakState() KeccakState {
|
||||||
return sha3.NewLegacyKeccak256().(KeccakState)
|
return sha3.NewLegacyKeccak256().(KeccakState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasherPool = sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return sha3.NewLegacyKeccak256().(KeccakState)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
|
// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
|
||||||
func HashData(kh KeccakState, data []byte) (h common.Hash) {
|
func HashData(kh KeccakState, data []byte) (h common.Hash) {
|
||||||
kh.Reset()
|
kh.Reset()
|
||||||
|
|
@ -84,22 +91,26 @@ func HashData(kh KeccakState, data []byte) (h common.Hash) {
|
||||||
// Keccak256 calculates and returns the Keccak256 hash of the input data.
|
// Keccak256 calculates and returns the Keccak256 hash of the input data.
|
||||||
func Keccak256(data ...[]byte) []byte {
|
func Keccak256(data ...[]byte) []byte {
|
||||||
b := make([]byte, 32)
|
b := make([]byte, 32)
|
||||||
d := NewKeccakState()
|
d := hasherPool.Get().(KeccakState)
|
||||||
|
d.Reset()
|
||||||
for _, b := range data {
|
for _, b := range data {
|
||||||
d.Write(b)
|
d.Write(b)
|
||||||
}
|
}
|
||||||
d.Read(b)
|
d.Read(b)
|
||||||
|
hasherPool.Put(d)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
|
// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
|
||||||
// converting it to an internal Hash data structure.
|
// converting it to an internal Hash data structure.
|
||||||
func Keccak256Hash(data ...[]byte) (h common.Hash) {
|
func Keccak256Hash(data ...[]byte) (h common.Hash) {
|
||||||
d := NewKeccakState()
|
d := hasherPool.Get().(KeccakState)
|
||||||
|
d.Reset()
|
||||||
for _, b := range data {
|
for _, b := range data {
|
||||||
d.Write(b)
|
d.Write(b)
|
||||||
}
|
}
|
||||||
d.Read(h[:])
|
d.Read(h[:])
|
||||||
|
hasherPool.Put(d)
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,16 @@ func VerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
|
||||||
return gokzgVerifyBlobProof(blob, commitment, proof)
|
return gokzgVerifyBlobProof(blob, commitment, proof)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyCellProofs verifies a batch of proofs corresponding to the blobs and commitments.
|
||||||
|
// Expects length of blobs and commitments to be equal.
|
||||||
|
// Expects length of proofs be 128 * length of blobs.
|
||||||
|
func VerifyCellProofs(blobs []*Blob, commitments []Commitment, proofs []Proof) error {
|
||||||
|
if useCKZG.Load() {
|
||||||
|
return ckzgVerifyCellProofBatch(blobs, commitments, proofs)
|
||||||
|
}
|
||||||
|
return gokzgVerifyCellProofBatch(blobs, commitments, proofs)
|
||||||
|
}
|
||||||
|
|
||||||
// ComputeCellProofs returns the KZG cell proofs that are used to verify the blob against
|
// ComputeCellProofs returns the KZG cell proofs that are used to verify the blob against
|
||||||
// the commitment.
|
// the commitment.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -149,3 +149,44 @@ func ckzgComputeCellProofs(blob *Blob) ([]Proof, error) {
|
||||||
}
|
}
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ckzgVerifyCellProofs verifies that the blob data corresponds to the provided commitment.
|
||||||
|
func ckzgVerifyCellProofBatch(blobs []*Blob, commitments []Commitment, cellProofs []Proof) error {
|
||||||
|
ckzgIniter.Do(ckzgInit)
|
||||||
|
var (
|
||||||
|
proofs = make([]ckzg4844.Bytes48, len(cellProofs))
|
||||||
|
commits = make([]ckzg4844.Bytes48, 0, len(cellProofs))
|
||||||
|
cellIndices = make([]uint64, 0, len(cellProofs))
|
||||||
|
cells = make([]ckzg4844.Cell, 0, len(cellProofs))
|
||||||
|
)
|
||||||
|
// Copy over the cell proofs
|
||||||
|
for i, proof := range cellProofs {
|
||||||
|
proofs[i] = (ckzg4844.Bytes48)(proof)
|
||||||
|
}
|
||||||
|
// Blow up the commitments to be the same length as the proofs
|
||||||
|
for _, commitment := range commitments {
|
||||||
|
for range gokzg4844.CellsPerExtBlob {
|
||||||
|
commits = append(commits, (ckzg4844.Bytes48)(commitment))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compute the cells and cell indices
|
||||||
|
for _, blob := range blobs {
|
||||||
|
cellsI, err := ckzg4844.ComputeCells((*ckzg4844.Blob)(blob))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cells = append(cells, cellsI[:]...)
|
||||||
|
for idx := range len(cellsI) {
|
||||||
|
cellIndices = append(cellIndices, uint64(idx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valid, err := ckzg4844.VerifyCellKZGProofBatch(commits, cellIndices, cells, proofs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !valid {
|
||||||
|
return errors.New("invalid proof")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,11 @@ func ckzgVerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
|
||||||
panic("unsupported platform")
|
panic("unsupported platform")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ckzgVerifyCellProofBatch verifies that the blob data corresponds to the provided commitment.
|
||||||
|
func ckzgVerifyCellProofBatch(blobs []*Blob, commitments []Commitment, proof []Proof) error {
|
||||||
|
panic("unsupported platform")
|
||||||
|
}
|
||||||
|
|
||||||
// ckzgComputeCellProofs returns the KZG cell proofs that are used to verify the blob against
|
// ckzgComputeCellProofs returns the KZG cell proofs that are used to verify the blob against
|
||||||
// the commitment.
|
// the commitment.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -114,3 +114,37 @@ func gokzgComputeCellProofs(blob *Blob) ([]Proof, error) {
|
||||||
}
|
}
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gokzgVerifyCellProofs verifies that the blob data corresponds to the provided commitment.
|
||||||
|
func gokzgVerifyCellProofBatch(blobs []*Blob, commitments []Commitment, cellProofs []Proof) error {
|
||||||
|
gokzgIniter.Do(gokzgInit)
|
||||||
|
|
||||||
|
var (
|
||||||
|
proofs = make([]gokzg4844.KZGProof, len(cellProofs))
|
||||||
|
commits = make([]gokzg4844.KZGCommitment, 0, len(cellProofs))
|
||||||
|
cellIndices = make([]uint64, 0, len(cellProofs))
|
||||||
|
cells = make([]*gokzg4844.Cell, 0, len(cellProofs))
|
||||||
|
)
|
||||||
|
// Copy over the cell proofs
|
||||||
|
for i, proof := range cellProofs {
|
||||||
|
proofs[i] = gokzg4844.KZGProof(proof)
|
||||||
|
}
|
||||||
|
// Blow up the commitments to be the same length as the proofs
|
||||||
|
for _, commitment := range commitments {
|
||||||
|
for range gokzg4844.CellsPerExtBlob {
|
||||||
|
commits = append(commits, gokzg4844.KZGCommitment(commitment))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compute the cell and cell indices
|
||||||
|
for _, blob := range blobs {
|
||||||
|
cellsI, err := context.ComputeCells((*gokzg4844.Blob)(blob), 2)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cells = append(cells, cellsI[:]...)
|
||||||
|
for idx := range len(cellsI) {
|
||||||
|
cellIndices = append(cellIndices, uint64(idx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return context.VerifyCellKZGProofBatch(commits, cellIndices, cells[:], proofs)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,3 +193,39 @@ func benchmarkVerifyBlobProof(b *testing.B, ckzg bool) {
|
||||||
VerifyBlobProof(blob, commitment, proof)
|
VerifyBlobProof(blob, commitment, proof)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCKZGCells(t *testing.T) { testKZGCells(t, true) }
|
||||||
|
func TestGoKZGCells(t *testing.T) { testKZGCells(t, false) }
|
||||||
|
func testKZGCells(t *testing.T, ckzg bool) {
|
||||||
|
if ckzg && !ckzgAvailable {
|
||||||
|
t.Skip("CKZG unavailable in this test build")
|
||||||
|
}
|
||||||
|
defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
|
||||||
|
useCKZG.Store(ckzg)
|
||||||
|
|
||||||
|
blob1 := randBlob()
|
||||||
|
blob2 := randBlob()
|
||||||
|
|
||||||
|
commitment1, err := BlobToCommitment(blob1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create KZG commitment from blob: %v", err)
|
||||||
|
}
|
||||||
|
commitment2, err := BlobToCommitment(blob2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create KZG commitment from blob: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
proofs1, err := ComputeCellProofs(blob1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create KZG proof at point: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
proofs2, err := ComputeCellProofs(blob2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create KZG proof at point: %v", err)
|
||||||
|
}
|
||||||
|
proofs := append(proofs1, proofs2...)
|
||||||
|
if err := VerifyCellProofs([]*Blob{blob1, blob2}, []Commitment{commitment1, commitment2}, proofs); err != nil {
|
||||||
|
t.Fatalf("failed to verify KZG proof at point: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -349,22 +349,20 @@ func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction
|
||||||
// GetTransaction retrieves the lookup along with the transaction itself associate
|
// GetTransaction retrieves the lookup along with the transaction itself associate
|
||||||
// with the given transaction hash.
|
// with the given transaction hash.
|
||||||
//
|
//
|
||||||
// An error will be returned if the transaction is not found, and background
|
// A null will be returned if the transaction is not found. The transaction is not
|
||||||
// indexing for transactions is still in progress. The error is used to indicate the
|
// existent from the node's perspective. This can be due to the transaction indexer
|
||||||
// scenario explicitly that the transaction might be reachable shortly.
|
// not being finished. The caller must explicitly check the indexer progress.
|
||||||
//
|
func (b *EthAPIBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
|
||||||
// A null will be returned in the transaction is not found and background transaction
|
lookup, tx := b.eth.blockchain.GetTransactionLookup(txHash)
|
||||||
// indexing is already finished. The transaction is not existent from the perspective
|
|
||||||
// of node.
|
|
||||||
func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
|
|
||||||
lookup, tx, err := b.eth.blockchain.GetTransactionLookup(txHash)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil, common.Hash{}, 0, 0, err
|
|
||||||
}
|
|
||||||
if lookup == nil || tx == nil {
|
if lookup == nil || tx == nil {
|
||||||
return false, nil, common.Hash{}, 0, 0, nil
|
return false, nil, common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index, nil
|
return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxIndexDone returns true if the transaction indexer has finished indexing.
|
||||||
|
func (b *EthAPIBackend) TxIndexDone() bool {
|
||||||
|
return b.eth.blockchain.TxIndexDone()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
|
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
|
||||||
|
|
@ -391,7 +389,7 @@ func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.S
|
||||||
return b.eth.txPool.SubscribeTransactions(ch, true)
|
return b.eth.txPool.SubscribeTransactions(ch, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress {
|
func (b *EthAPIBackend) SyncProgress(ctx context.Context) ethereum.SyncProgress {
|
||||||
prog := b.eth.Downloader().Progress()
|
prog := b.eth.Downloader().Progress()
|
||||||
if txProg, err := b.eth.blockchain.TxIndexProgress(); err == nil {
|
if txProg, err := b.eth.blockchain.TxIndexProgress(); err == nil {
|
||||||
prog.TxIndexFinishedBlocks = txProg.Indexed
|
prog.TxIndexFinishedBlocks = txProg.Indexed
|
||||||
|
|
|
||||||
|
|
@ -134,13 +134,17 @@ func TestSendTx(t *testing.T) {
|
||||||
func testSendTx(t *testing.T, withLocal bool) {
|
func testSendTx(t *testing.T, withLocal bool) {
|
||||||
b := initBackend(withLocal)
|
b := initBackend(withLocal)
|
||||||
|
|
||||||
txA := pricedSetCodeTx(0, 250000, uint256.NewInt(params.GWei), uint256.NewInt(params.GWei), key, []unsignedAuth{
|
txA := pricedSetCodeTx(0, 250000, uint256.NewInt(params.GWei), uint256.NewInt(params.GWei), key, []unsignedAuth{{nonce: 0, key: key}})
|
||||||
{
|
if err := b.SendTx(context.Background(), txA); err != nil {
|
||||||
nonce: 0,
|
t.Fatalf("Failed to submit tx: %v", err)
|
||||||
key: key,
|
}
|
||||||
},
|
for {
|
||||||
})
|
pending, _ := b.TxPool().ContentFrom(address)
|
||||||
b.SendTx(context.Background(), txA)
|
if len(pending) == 1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
txB := makeTx(1, nil, nil, key)
|
txB := makeTx(1, nil, nil, key)
|
||||||
err := b.SendTx(context.Background(), txB)
|
err := b.SendTx(context.Background(), txB)
|
||||||
|
|
|
||||||
|
|
@ -570,6 +570,7 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo
|
||||||
for i, hash := range hashes {
|
for i, hash := range hashes {
|
||||||
index[hash] = i
|
index[hash] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, sidecar := range sidecars {
|
for i, sidecar := range sidecars {
|
||||||
if res[i] != nil || sidecar == nil {
|
if res[i] != nil || sidecar == nil {
|
||||||
// already filled
|
// already filled
|
||||||
|
|
@ -610,12 +611,12 @@ func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProo
|
||||||
// pull up the blob hashes
|
// pull up the blob hashes
|
||||||
var (
|
var (
|
||||||
res = make([]*engine.BlobAndProofV2, len(hashes))
|
res = make([]*engine.BlobAndProofV2, len(hashes))
|
||||||
index = make(map[common.Hash]int)
|
index = make(map[common.Hash][]int)
|
||||||
sidecars = api.eth.TxPool().GetBlobs(hashes)
|
sidecars = api.eth.TxPool().GetBlobs(hashes)
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, hash := range hashes {
|
for i, hash := range hashes {
|
||||||
index[hash] = i
|
index[hash] = append(index[hash], i)
|
||||||
}
|
}
|
||||||
for i, sidecar := range sidecars {
|
for i, sidecar := range sidecars {
|
||||||
if res[i] != nil {
|
if res[i] != nil {
|
||||||
|
|
@ -631,12 +632,13 @@ func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProo
|
||||||
}
|
}
|
||||||
blobHashes := sidecar.BlobHashes()
|
blobHashes := sidecar.BlobHashes()
|
||||||
for bIdx, hash := range blobHashes {
|
for bIdx, hash := range blobHashes {
|
||||||
if idx, ok := index[hash]; ok {
|
if idxes, ok := index[hash]; ok {
|
||||||
proofs := sidecar.CellProofsAt(bIdx)
|
proofs := sidecar.CellProofsAt(bIdx)
|
||||||
var cellProofs []hexutil.Bytes
|
var cellProofs []hexutil.Bytes
|
||||||
for _, proof := range proofs {
|
for _, proof := range proofs {
|
||||||
cellProofs = append(cellProofs, proof[:])
|
cellProofs = append(cellProofs, proof[:])
|
||||||
}
|
}
|
||||||
|
for _, idx := range idxes {
|
||||||
res[idx] = &engine.BlobAndProofV2{
|
res[idx] = &engine.BlobAndProofV2{
|
||||||
Blob: sidecar.Blobs[bIdx][:],
|
Blob: sidecar.Blobs[bIdx][:],
|
||||||
CellProofs: cellProofs,
|
CellProofs: cellProofs,
|
||||||
|
|
@ -644,6 +646,7 @@ func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,9 @@ const (
|
||||||
// txGatherSlack is the interval used to collate almost-expired announces
|
// txGatherSlack is the interval used to collate almost-expired announces
|
||||||
// with network fetches.
|
// with network fetches.
|
||||||
txGatherSlack = 100 * time.Millisecond
|
txGatherSlack = 100 * time.Millisecond
|
||||||
|
|
||||||
|
// addTxsBatchSize it the max number of transactions to add in a single batch from a peer.
|
||||||
|
addTxsBatchSize = 128
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -329,8 +332,8 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
|
||||||
metas = make([]txMetadata, 0, len(txs))
|
metas = make([]txMetadata, 0, len(txs))
|
||||||
)
|
)
|
||||||
// proceed in batches
|
// proceed in batches
|
||||||
for i := 0; i < len(txs); i += 128 {
|
for i := 0; i < len(txs); i += addTxsBatchSize {
|
||||||
end := i + 128
|
end := i + addTxsBatchSize
|
||||||
if end > len(txs) {
|
if end > len(txs) {
|
||||||
end = len(txs)
|
end = len(txs)
|
||||||
}
|
}
|
||||||
|
|
@ -372,7 +375,7 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
|
||||||
otherRejectMeter.Mark(otherreject)
|
otherRejectMeter.Mark(otherreject)
|
||||||
|
|
||||||
// If 'other reject' is >25% of the deliveries in any batch, sleep a bit.
|
// If 'other reject' is >25% of the deliveries in any batch, sleep a bit.
|
||||||
if otherreject > 128/4 {
|
if otherreject > addTxsBatchSize/4 {
|
||||||
time.Sleep(200 * time.Millisecond)
|
time.Sleep(200 * time.Millisecond)
|
||||||
log.Debug("Peer delivering stale transactions", "peer", peer, "rejected", otherreject)
|
log.Debug("Peer delivering stale transactions", "peer", peer, "rejected", otherreject)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,13 @@ func (b *testBackend) GetReceiptsByHash(hash common.Hash) types.Receipts {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *testBackend) GetRawReceiptsByHash(hash common.Hash) types.Receipts {
|
||||||
|
if number := rawdb.ReadHeaderNumber(b.db, hash); number != nil {
|
||||||
|
return rawdb.ReadRawReceipts(b.db, hash, *number)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
|
func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
|
||||||
var (
|
var (
|
||||||
hash common.Hash
|
hash common.Hash
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
|
||||||
// There's a fairly high chance for the transaction to execute successfully
|
// There's a fairly high chance for the transaction to execute successfully
|
||||||
// with gasLimit set to the first execution's usedGas + gasRefund. Explicitly
|
// with gasLimit set to the first execution's usedGas + gasRefund. Explicitly
|
||||||
// check that gas amount and use as a limit for the binary search.
|
// check that gas amount and use as a limit for the binary search.
|
||||||
optimisticGasLimit := (result.UsedGas + result.RefundedGas + params.CallStipend) * 64 / 63
|
optimisticGasLimit := (result.MaxUsedGas + params.CallStipend) * 64 / 63
|
||||||
if optimisticGasLimit < hi {
|
if optimisticGasLimit < hi {
|
||||||
failed, _, err = execute(ctx, call, opts, optimisticGasLimit)
|
failed, _, err = execute(ctx, call, opts, optimisticGasLimit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,8 @@ type Backend interface {
|
||||||
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
||||||
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
|
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
|
||||||
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
|
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
|
||||||
GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
|
GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64)
|
||||||
|
TxIndexDone() bool
|
||||||
RPCGasCap() uint64
|
RPCGasCap() uint64
|
||||||
ChainConfig() *params.ChainConfig
|
ChainConfig() *params.ChainConfig
|
||||||
Engine() consensus.Engine
|
Engine() consensus.Engine
|
||||||
|
|
@ -777,6 +778,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
// Note: This copies the config, to not screw up the main config
|
// Note: This copies the config, to not screw up the main config
|
||||||
chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
|
chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
|
||||||
}
|
}
|
||||||
|
|
||||||
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
|
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
|
|
@ -786,42 +788,45 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
}
|
}
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
// Prepare the transaction for un-traced execution
|
// Prepare the transaction for un-traced execution
|
||||||
var (
|
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
||||||
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
|
if txHash != (common.Hash{}) && tx.Hash() != txHash {
|
||||||
vmConf vm.Config
|
// Process the tx to update state, but don't trace it.
|
||||||
dump *os.File
|
_, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
||||||
writer *bufio.Writer
|
if err != nil {
|
||||||
err error
|
return dumps, err
|
||||||
)
|
}
|
||||||
// If the transaction needs tracing, swap out the configs
|
// Finalize the state so any modifications are written to the trie
|
||||||
if tx.Hash() == txHash || txHash == (common.Hash{}) {
|
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||||
// Generate a unique temporary file to dump it into
|
statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number()))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The transaction should be traced.
|
||||||
|
// Generate a unique temporary file to dump it into.
|
||||||
prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4])
|
prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4])
|
||||||
if !canon {
|
if !canon {
|
||||||
prefix = fmt.Sprintf("%valt-", prefix)
|
prefix = fmt.Sprintf("%valt-", prefix)
|
||||||
}
|
}
|
||||||
dump, err = os.CreateTemp(os.TempDir(), prefix)
|
var dump *os.File
|
||||||
|
dump, err := os.CreateTemp(os.TempDir(), prefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dumps = append(dumps, dump.Name())
|
dumps = append(dumps, dump.Name())
|
||||||
|
// Set up the tracer and EVM for the transaction.
|
||||||
// Swap out the noop logger to the standard tracer
|
var (
|
||||||
writer = bufio.NewWriter(dump)
|
writer = bufio.NewWriter(dump)
|
||||||
vmConf = vm.Config{
|
tracer = logger.NewJSONLogger(&logConfig, writer)
|
||||||
Tracer: logger.NewJSONLogger(&logConfig, writer),
|
evm = vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{
|
||||||
EnablePreimageRecording: true,
|
Tracer: tracer,
|
||||||
}
|
NoBaseFee: true,
|
||||||
}
|
})
|
||||||
|
)
|
||||||
// Execute the transaction and flush any traces to disk
|
// Execute the transaction and flush any traces to disk
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
if vmConf.Tracer.OnTxStart != nil {
|
if tracer.OnTxStart != nil {
|
||||||
vmConf.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
}
|
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
|
||||||
if vmConf.Tracer.OnTxEnd != nil {
|
|
||||||
vmConf.Tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, err)
|
|
||||||
}
|
}
|
||||||
|
_, err = core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
||||||
if writer != nil {
|
if writer != nil {
|
||||||
writer.Flush()
|
writer.Flush()
|
||||||
}
|
}
|
||||||
|
|
@ -858,12 +863,13 @@ func containsTx(block *types.Block, hash common.Hash) bool {
|
||||||
// TraceTransaction returns the structured logs created during the execution of EVM
|
// TraceTransaction returns the structured logs created during the execution of EVM
|
||||||
// and returns them as a JSON object.
|
// and returns them as a JSON object.
|
||||||
func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
|
func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
|
||||||
found, _, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
|
found, _, blockHash, blockNumber, index := api.backend.GetTransaction(hash)
|
||||||
if err != nil {
|
if !found {
|
||||||
|
// Warn in case tx indexer is not done.
|
||||||
|
if !api.backend.TxIndexDone() {
|
||||||
return nil, ethapi.NewTxIndexingError()
|
return nil, ethapi.NewTxIndexingError()
|
||||||
}
|
}
|
||||||
// Only mined txes are supported
|
// Only mined txes are supported
|
||||||
if !found {
|
|
||||||
return nil, errTxNotFound
|
return nil, errTxNotFound
|
||||||
}
|
}
|
||||||
// It shouldn't happen in practice.
|
// It shouldn't happen in practice.
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
@ -116,9 +117,13 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
|
||||||
return b.chain.GetBlockByNumber(uint64(number)), nil
|
return b.chain.GetBlockByNumber(uint64(number)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
|
func (b *testBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
|
||||||
tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash)
|
tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash)
|
||||||
return tx != nil, tx, hash, blockNumber, index, nil
|
return tx != nil, tx, hash, blockNumber, index
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *testBackend) TxIndexDone() bool {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *testBackend) RPCGasCap() uint64 {
|
func (b *testBackend) RPCGasCap() uint64 {
|
||||||
|
|
@ -1214,3 +1219,118 @@ func TestTraceBlockWithBasefee(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStandardTraceBlockToFile(t *testing.T) {
|
||||||
|
var (
|
||||||
|
// A sender who makes transactions, has some funds
|
||||||
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
funds = big.NewInt(1000000000000000)
|
||||||
|
|
||||||
|
// first contract the sender transacts with
|
||||||
|
aa = common.HexToAddress("0x7217d81b76bdd8707601e959454e3d776aee5f43")
|
||||||
|
aaCode = []byte{byte(vm.PUSH1), 0x00, byte(vm.POP)}
|
||||||
|
|
||||||
|
// second contract the sender transacts with
|
||||||
|
bb = common.HexToAddress("0x7217d81b76bdd8707601e959454e3d776aee5f44")
|
||||||
|
bbCode = []byte{byte(vm.PUSH2), 0x00, 0x01, byte(vm.POP)}
|
||||||
|
)
|
||||||
|
|
||||||
|
genesis := &core.Genesis{
|
||||||
|
Config: params.TestChainConfig,
|
||||||
|
Alloc: types.GenesisAlloc{
|
||||||
|
address: {Balance: funds},
|
||||||
|
aa: {
|
||||||
|
Code: aaCode,
|
||||||
|
Nonce: 1,
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
},
|
||||||
|
bb: {
|
||||||
|
Code: bbCode,
|
||||||
|
Nonce: 1,
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
txHashs := make([]common.Hash, 0, 2)
|
||||||
|
backend := newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) {
|
||||||
|
b.SetCoinbase(common.Address{1})
|
||||||
|
// first tx to aa
|
||||||
|
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
|
||||||
|
Nonce: 0,
|
||||||
|
To: &aa,
|
||||||
|
Value: big.NewInt(0),
|
||||||
|
Gas: 50000,
|
||||||
|
GasPrice: b.BaseFee(),
|
||||||
|
Data: nil,
|
||||||
|
}), types.HomesteadSigner{}, key)
|
||||||
|
b.AddTx(tx)
|
||||||
|
txHashs = append(txHashs, tx.Hash())
|
||||||
|
// second tx to bb
|
||||||
|
tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{
|
||||||
|
Nonce: 1,
|
||||||
|
To: &bb,
|
||||||
|
Value: big.NewInt(1),
|
||||||
|
Gas: 100000,
|
||||||
|
GasPrice: b.BaseFee(),
|
||||||
|
Data: nil,
|
||||||
|
}), types.HomesteadSigner{}, key)
|
||||||
|
b.AddTx(tx)
|
||||||
|
txHashs = append(txHashs, tx.Hash())
|
||||||
|
})
|
||||||
|
defer backend.chain.Stop()
|
||||||
|
|
||||||
|
var testSuite = []struct {
|
||||||
|
blockNumber rpc.BlockNumber
|
||||||
|
config *StdTraceConfig
|
||||||
|
want []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// test that all traces in the block were outputted if no trace config is specified
|
||||||
|
blockNumber: rpc.LatestBlockNumber,
|
||||||
|
config: nil,
|
||||||
|
want: []string{
|
||||||
|
`{"pc":0,"op":96,"gas":"0x7148","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||||
|
{"pc":2,"op":80,"gas":"0x7145","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"POP"}
|
||||||
|
{"pc":3,"op":0,"gas":"0x7143","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"}
|
||||||
|
{"output":"","gasUsed":"0x5"}
|
||||||
|
`,
|
||||||
|
`{"pc":0,"op":97,"gas":"0x13498","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH2"}
|
||||||
|
{"pc":3,"op":80,"gas":"0x13495","gasCost":"0x2","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"POP"}
|
||||||
|
{"pc":4,"op":0,"gas":"0x13493","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"}
|
||||||
|
{"output":"","gasUsed":"0x5"}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// test that only a specific tx is traced if specified
|
||||||
|
blockNumber: rpc.LatestBlockNumber,
|
||||||
|
config: &StdTraceConfig{TxHash: txHashs[1]},
|
||||||
|
want: []string{
|
||||||
|
`{"pc":0,"op":97,"gas":"0x13498","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH2"}
|
||||||
|
{"pc":3,"op":80,"gas":"0x13495","gasCost":"0x2","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"POP"}
|
||||||
|
{"pc":4,"op":0,"gas":"0x13493","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"}
|
||||||
|
{"output":"","gasUsed":"0x5"}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
api := NewAPI(backend)
|
||||||
|
for i, tc := range testSuite {
|
||||||
|
block, _ := api.blockByNumber(context.Background(), tc.blockNumber)
|
||||||
|
txTraces, err := api.StandardTraceBlockToFile(context.Background(), block.Hash(), tc.config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("test index %d received error %v", i, err)
|
||||||
|
}
|
||||||
|
for j, traceFileName := range txTraces {
|
||||||
|
traceReceived, err := os.ReadFile(traceFileName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not read trace file: %v", err)
|
||||||
|
}
|
||||||
|
if tc.want[j] != string(traceReceived) {
|
||||||
|
t.Fatalf("unexpected trace result. expected\n'%s'\n\nreceived\n'%s'\n", tc.want[j], string(traceReceived))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumb
|
||||||
}
|
}
|
||||||
|
|
||||||
type rpcBlock struct {
|
type rpcBlock struct {
|
||||||
Hash common.Hash `json:"hash"`
|
Hash *common.Hash `json:"hash"`
|
||||||
Transactions []rpcTransaction `json:"transactions"`
|
Transactions []rpcTransaction `json:"transactions"`
|
||||||
UncleHashes []common.Hash `json:"uncles"`
|
UncleHashes []common.Hash `json:"uncles"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||||
|
|
@ -158,6 +158,12 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
|
||||||
if err := json.Unmarshal(raw, &body); err != nil {
|
if err := json.Unmarshal(raw, &body); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Pending blocks don't return a block hash, compute it for sender caching.
|
||||||
|
if body.Hash == nil {
|
||||||
|
tmp := head.Hash()
|
||||||
|
body.Hash = &tmp
|
||||||
|
}
|
||||||
|
|
||||||
// Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
|
// Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
|
||||||
if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 {
|
if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 {
|
||||||
return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles")
|
return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles")
|
||||||
|
|
@ -199,7 +205,7 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
|
||||||
txs := make([]*types.Transaction, len(body.Transactions))
|
txs := make([]*types.Transaction, len(body.Transactions))
|
||||||
for i, tx := range body.Transactions {
|
for i, tx := range body.Transactions {
|
||||||
if tx.From != nil {
|
if tx.From != nil {
|
||||||
setSenderFromServer(tx.tx, *tx.From, body.Hash)
|
setSenderFromServer(tx.tx, *tx.From, *body.Hash)
|
||||||
}
|
}
|
||||||
txs[i] = tx.tx
|
txs[i] = tx.tx
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,12 @@ func testTransactionInBlock(t *testing.T, client *rpc.Client) {
|
||||||
if tx.Hash() != testTx2.Hash() {
|
if tx.Hash() != testTx2.Hash() {
|
||||||
t.Fatalf("unexpected transaction: %v", tx)
|
t.Fatalf("unexpected transaction: %v", tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test pending block
|
||||||
|
_, err = ec.BlockByNumber(context.Background(), big.NewInt(int64(rpc.PendingBlockNumber)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testChainID(t *testing.T, client *rpc.Client) {
|
func testChainID(t *testing.T, client *rpc.Client) {
|
||||||
|
|
@ -619,6 +625,21 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
|
||||||
if gas != 21000 {
|
if gas != 21000 {
|
||||||
t.Fatalf("unexpected gas limit: %v", gas)
|
t.Fatalf("unexpected gas limit: %v", gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify that sender address of pending transaction is saved in cache.
|
||||||
|
pendingBlock, err := ec.BlockByNumber(context.Background(), big.NewInt(int64(rpc.PendingBlockNumber)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
// No additional RPC should be required, ensure the server is not asked by
|
||||||
|
// canceling the context.
|
||||||
|
sender, err := ec.TransactionSender(newCanceledContext(), pendingBlock.Transactions()[0], pendingBlock.Hash(), 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unable to recover sender:", err)
|
||||||
|
}
|
||||||
|
if sender != testAddr {
|
||||||
|
t.Fatal("wrong sender:", sender)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testTransactionSender(t *testing.T, client *rpc.Client) {
|
func testTransactionSender(t *testing.T, client *rpc.Client) {
|
||||||
|
|
@ -640,10 +661,7 @@ func testTransactionSender(t *testing.T, client *rpc.Client) {
|
||||||
|
|
||||||
// The sender address is cached in tx1, so no additional RPC should be required in
|
// The sender address is cached in tx1, so no additional RPC should be required in
|
||||||
// TransactionSender. Ensure the server is not asked by canceling the context here.
|
// TransactionSender. Ensure the server is not asked by canceling the context here.
|
||||||
canceledCtx, cancel := context.WithCancel(context.Background())
|
sender1, err := ec.TransactionSender(newCanceledContext(), tx1, block2.Hash(), 0)
|
||||||
cancel()
|
|
||||||
<-canceledCtx.Done() // Ensure the close of the Done channel
|
|
||||||
sender1, err := ec.TransactionSender(canceledCtx, tx1, block2.Hash(), 0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -662,6 +680,13 @@ func testTransactionSender(t *testing.T, client *rpc.Client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newCanceledContext() context.Context {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
<-ctx.Done() // Ensure the close of the Done channel
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
func sendTransaction(ec *ethclient.Client) error {
|
func sendTransaction(ec *ethclient.Client) error {
|
||||||
chainID, err := ec.ChainID(context.Background())
|
chainID, err := ec.ChainID(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,13 @@ type KeyValueStater interface {
|
||||||
Stat() (string, error)
|
Stat() (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeyValueSyncer wraps the SyncKeyValue method of a backing data store.
|
||||||
|
type KeyValueSyncer interface {
|
||||||
|
// SyncKeyValue ensures that all pending writes are flushed to disk,
|
||||||
|
// guaranteeing data durability up to the point.
|
||||||
|
SyncKeyValue() error
|
||||||
|
}
|
||||||
|
|
||||||
// Compacter wraps the Compact method of a backing data store.
|
// Compacter wraps the Compact method of a backing data store.
|
||||||
type Compacter interface {
|
type Compacter interface {
|
||||||
// Compact flattens the underlying data store for the given key range. In essence,
|
// Compact flattens the underlying data store for the given key range. In essence,
|
||||||
|
|
@ -75,6 +82,7 @@ type KeyValueStore interface {
|
||||||
KeyValueReader
|
KeyValueReader
|
||||||
KeyValueWriter
|
KeyValueWriter
|
||||||
KeyValueStater
|
KeyValueStater
|
||||||
|
KeyValueSyncer
|
||||||
KeyValueRangeDeleter
|
KeyValueRangeDeleter
|
||||||
Batcher
|
Batcher
|
||||||
Iteratee
|
Iteratee
|
||||||
|
|
@ -126,6 +134,9 @@ type AncientWriter interface {
|
||||||
// The integer return value is the total size of the written data.
|
// The integer return value is the total size of the written data.
|
||||||
ModifyAncients(func(AncientWriteOp) error) (int64, error)
|
ModifyAncients(func(AncientWriteOp) error) (int64, error)
|
||||||
|
|
||||||
|
// SyncAncient flushes all in-memory ancient store data to disk.
|
||||||
|
SyncAncient() error
|
||||||
|
|
||||||
// TruncateHead discards all but the first n ancient data from the ancient store.
|
// TruncateHead discards all but the first n ancient data from the ancient store.
|
||||||
// After the truncation, the latest item can be accessed it item_n-1(start from 0).
|
// After the truncation, the latest item can be accessed it item_n-1(start from 0).
|
||||||
TruncateHead(n uint64) (uint64, error)
|
TruncateHead(n uint64) (uint64, error)
|
||||||
|
|
@ -138,9 +149,6 @@ type AncientWriter interface {
|
||||||
//
|
//
|
||||||
// Note that data marked as non-prunable will still be retained and remain accessible.
|
// Note that data marked as non-prunable will still be retained and remain accessible.
|
||||||
TruncateTail(n uint64) (uint64, error)
|
TruncateTail(n uint64) (uint64, error)
|
||||||
|
|
||||||
// Sync flushes all in-memory ancient store data to disk.
|
|
||||||
Sync() error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AncientWriteOp is given to the function argument of ModifyAncients.
|
// AncientWriteOp is given to the function argument of ModifyAncients.
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,22 @@ func (db *Database) Path() string {
|
||||||
return db.fn
|
return db.fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncKeyValue flushes all pending writes in the write-ahead-log to disk,
|
||||||
|
// ensuring data durability up to that point.
|
||||||
|
func (db *Database) SyncKeyValue() error {
|
||||||
|
// In theory, the WAL (Write-Ahead Log) can be explicitly synchronized using
|
||||||
|
// a write operation with SYNC=true. However, there is no dedicated key reserved
|
||||||
|
// for this purpose, and even a nil key (key=nil) is considered a valid
|
||||||
|
// database entry.
|
||||||
|
//
|
||||||
|
// In LevelDB, writes are blocked until the data is written to the WAL, meaning
|
||||||
|
// recent writes won't be lost unless a power failure or system crash occurs.
|
||||||
|
// Additionally, LevelDB is no longer the default database engine and is likely
|
||||||
|
// only used by hash-mode archive nodes. Given this, the durability guarantees
|
||||||
|
// without explicit sync are acceptable in the context of LevelDB.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// meter periodically retrieves internal leveldb counters and reports them to
|
// meter periodically retrieves internal leveldb counters and reports them to
|
||||||
// the metrics subsystem.
|
// the metrics subsystem.
|
||||||
func (db *Database) meter(refresh time.Duration, namespace string) {
|
func (db *Database) meter(refresh time.Duration, namespace string) {
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,12 @@ func (db *Database) Compact(start []byte, limit []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncKeyValue ensures that all pending writes are flushed to disk,
|
||||||
|
// guaranteeing data durability up to the point.
|
||||||
|
func (db *Database) SyncKeyValue() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Len returns the number of entries currently present in the memory database.
|
// Len returns the number of entries currently present in the memory database.
|
||||||
//
|
//
|
||||||
// Note, this method is only used for testing (i.e. not public in general) and
|
// Note, this method is only used for testing (i.e. not public in general) and
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ func (l panicLogger) Fatalf(format string, args ...interface{}) {
|
||||||
|
|
||||||
// New returns a wrapped pebble DB object. The namespace is the prefix that the
|
// New returns a wrapped pebble DB object. The namespace is the prefix that the
|
||||||
// metrics reporting should use for surfacing internal stats.
|
// metrics reporting should use for surfacing internal stats.
|
||||||
func New(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (*Database, error) {
|
func New(file string, cache int, handles int, namespace string, readonly bool) (*Database, error) {
|
||||||
// Ensure we have some minimal caching and file guarantees
|
// Ensure we have some minimal caching and file guarantees
|
||||||
if cache < minCache {
|
if cache < minCache {
|
||||||
cache = minCache
|
cache = minCache
|
||||||
|
|
@ -185,7 +185,15 @@ func New(file string, cache int, handles int, namespace string, readonly bool, e
|
||||||
fn: file,
|
fn: file,
|
||||||
log: logger,
|
log: logger,
|
||||||
quitChan: make(chan chan error),
|
quitChan: make(chan chan error),
|
||||||
writeOptions: &pebble.WriteOptions{Sync: !ephemeral},
|
|
||||||
|
// Use asynchronous write mode by default. Otherwise, the overhead of frequent fsync
|
||||||
|
// operations can be significant, especially on platforms with slow fsync performance
|
||||||
|
// (e.g., macOS) or less capable SSDs.
|
||||||
|
//
|
||||||
|
// Note that enabling async writes means recent data may be lost in the event of an
|
||||||
|
// application-level panic (writes will also be lost on a machine-level failure,
|
||||||
|
// of course). Geth is expected to handle recovery from an unclean shutdown.
|
||||||
|
writeOptions: pebble.NoSync,
|
||||||
}
|
}
|
||||||
opt := &pebble.Options{
|
opt := &pebble.Options{
|
||||||
// Pebble has a single combined cache area and the write
|
// Pebble has a single combined cache area and the write
|
||||||
|
|
@ -228,6 +236,15 @@ func New(file string, cache int, handles int, namespace string, readonly bool, e
|
||||||
WriteStallEnd: db.onWriteStallEnd,
|
WriteStallEnd: db.onWriteStallEnd,
|
||||||
},
|
},
|
||||||
Logger: panicLogger{}, // TODO(karalabe): Delete when this is upstreamed in Pebble
|
Logger: panicLogger{}, // TODO(karalabe): Delete when this is upstreamed in Pebble
|
||||||
|
|
||||||
|
// Pebble is configured to use asynchronous write mode, meaning write operations
|
||||||
|
// return as soon as the data is cached in memory, without waiting for the WAL
|
||||||
|
// to be written. This mode offers better write performance but risks losing
|
||||||
|
// recent writes if the application crashes or a power failure/system crash occurs.
|
||||||
|
//
|
||||||
|
// By setting the WALBytesPerSync, the cached WAL writes will be periodically
|
||||||
|
// flushed at the background if the accumulated size exceeds this threshold.
|
||||||
|
WALBytesPerSync: 5 * ethdb.IdealBatchSize,
|
||||||
}
|
}
|
||||||
// Disable seek compaction explicitly. Check https://github.com/ethereum/go-ethereum/pull/20130
|
// Disable seek compaction explicitly. Check https://github.com/ethereum/go-ethereum/pull/20130
|
||||||
// for more details.
|
// for more details.
|
||||||
|
|
@ -414,6 +431,18 @@ func (d *Database) Path() string {
|
||||||
return d.fn
|
return d.fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncKeyValue flushes all pending writes in the write-ahead-log to disk,
|
||||||
|
// ensuring data durability up to that point.
|
||||||
|
func (d *Database) SyncKeyValue() error {
|
||||||
|
// The entry (value=nil) is not written to the database; it is only
|
||||||
|
// added to the WAL. Writing this special log entry in sync mode
|
||||||
|
// automatically flushes all previous writes, ensuring database
|
||||||
|
// durability up to this point.
|
||||||
|
b := d.db.NewBatch()
|
||||||
|
b.LogData(nil, nil)
|
||||||
|
return d.db.Apply(b, pebble.Sync)
|
||||||
|
}
|
||||||
|
|
||||||
// meter periodically retrieves internal pebble counters and reports them to
|
// meter periodically retrieves internal pebble counters and reports them to
|
||||||
// the metrics subsystem.
|
// the metrics subsystem.
|
||||||
func (d *Database) meter(refresh time.Duration, namespace string) {
|
func (d *Database) meter(refresh time.Duration, namespace string) {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package pebble
|
package pebble
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/cockroachdb/pebble"
|
"github.com/cockroachdb/pebble"
|
||||||
|
|
@ -54,3 +55,26 @@ func BenchmarkPebbleDB(b *testing.B) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPebbleLogData(t *testing.T) {
|
||||||
|
db, err := pebble.Open("", &pebble.Options{
|
||||||
|
FS: vfs.NewMem(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = db.Get(nil)
|
||||||
|
if !errors.Is(err, pebble.ErrNotFound) {
|
||||||
|
t.Fatal("Unknown database entry")
|
||||||
|
}
|
||||||
|
|
||||||
|
b := db.NewBatch()
|
||||||
|
b.LogData(nil, nil)
|
||||||
|
db.Apply(b, pebble.Sync)
|
||||||
|
|
||||||
|
_, _, err = db.Get(nil)
|
||||||
|
if !errors.Is(err, pebble.ErrNotFound) {
|
||||||
|
t.Fatal("Unknown database entry")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ func (db *Database) TruncateTail(n uint64) (uint64, error) {
|
||||||
panic("not supported")
|
panic("not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) Sync() error {
|
func (db *Database) SyncAncient() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,6 +138,10 @@ func (db *Database) Compact(start []byte, limit []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Database) SyncKeyValue() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (db *Database) Close() error {
|
func (db *Database) Close() error {
|
||||||
db.remote.Close()
|
db.remote.Close()
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ type backend interface {
|
||||||
CurrentHeader() *types.Header
|
CurrentHeader() *types.Header
|
||||||
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
||||||
Stats() (pending int, queued int)
|
Stats() (pending int, queued int)
|
||||||
SyncProgress() ethereum.SyncProgress
|
SyncProgress(ctx context.Context) ethereum.SyncProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
// fullNodeBackend encompasses the functionality necessary for a full node
|
// fullNodeBackend encompasses the functionality necessary for a full node
|
||||||
|
|
@ -766,7 +766,7 @@ func (s *Service) reportStats(conn *connWrapper) error {
|
||||||
)
|
)
|
||||||
// check if backend is a full node
|
// check if backend is a full node
|
||||||
if fullBackend, ok := s.backend.(fullNodeBackend); ok {
|
if fullBackend, ok := s.backend.(fullNodeBackend); ok {
|
||||||
sync := fullBackend.SyncProgress()
|
sync := fullBackend.SyncProgress(context.Background())
|
||||||
syncing = !sync.Done()
|
syncing = !sync.Done()
|
||||||
|
|
||||||
price, _ := fullBackend.SuggestGasTipCap(context.Background())
|
price, _ := fullBackend.SuggestGasTipCap(context.Background())
|
||||||
|
|
@ -775,7 +775,7 @@ func (s *Service) reportStats(conn *connWrapper) error {
|
||||||
gasprice += int(basefee.Uint64())
|
gasprice += int(basefee.Uint64())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sync := s.backend.SyncProgress()
|
sync := s.backend.SyncProgress(context.Background())
|
||||||
syncing = !sync.Done()
|
syncing = !sync.Done()
|
||||||
}
|
}
|
||||||
// Assemble the node stats and send it to the server
|
// Assemble the node stats and send it to the server
|
||||||
|
|
|
||||||
12
go.mod
12
go.mod
|
|
@ -12,7 +12,7 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2
|
||||||
github.com/cespare/cp v0.1.0
|
github.com/cespare/cp v0.1.0
|
||||||
github.com/cloudflare/cloudflare-go v0.114.0
|
github.com/cloudflare/cloudflare-go v0.114.0
|
||||||
github.com/cockroachdb/pebble v1.1.2
|
github.com/cockroachdb/pebble v1.1.5
|
||||||
github.com/consensys/gnark-crypto v0.16.0
|
github.com/consensys/gnark-crypto v0.16.0
|
||||||
github.com/crate-crypto/go-eth-kzg v1.3.0
|
github.com/crate-crypto/go-eth-kzg v1.3.0
|
||||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a
|
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a
|
||||||
|
|
@ -120,7 +120,7 @@ require (
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||||
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
||||||
|
|
@ -133,10 +133,10 @@ require (
|
||||||
github.com/pion/transport/v3 v3.0.1 // indirect
|
github.com/pion/transport/v3 v3.0.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_golang v1.12.0 // indirect
|
github.com/prometheus/client_golang v1.15.0 // indirect
|
||||||
github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
github.com/prometheus/common v0.32.1 // indirect
|
github.com/prometheus/common v0.42.0 // indirect
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
github.com/prometheus/procfs v0.9.0 // indirect
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
|
|
||||||
403
go.sum
403
go.sum
|
|
@ -1,36 +1,3 @@
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
|
||||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
|
||||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
|
||||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
|
||||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
|
||||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
|
||||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
|
||||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
|
||||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
|
||||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
|
||||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
|
||||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
|
||||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
|
||||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
|
||||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
|
||||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
|
||||||
|
|
@ -43,8 +10,6 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4=
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4=
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
|
||||||
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
||||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
|
|
@ -53,11 +18,6 @@ github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDO
|
||||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||||
github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
|
github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
|
||||||
github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
|
github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
|
||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
|
||||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
||||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA=
|
github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA=
|
||||||
|
|
@ -86,30 +46,20 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 h1:0BkLfgeDjfZnZ+MhB3ONb01u9pwF
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ=
|
||||||
github.com/aws/smithy-go v1.15.0 h1:PS/durmlzvAFpQHDs4wi4sNNP9ExsqZh6IlfdHXgKK8=
|
github.com/aws/smithy-go v1.15.0 h1:PS/durmlzvAFpQHDs4wi4sNNP9ExsqZh6IlfdHXgKK8=
|
||||||
github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
|
github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
|
||||||
github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
|
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
|
||||||
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
|
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
|
||||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
|
||||||
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
|
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
|
||||||
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
|
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
|
||||||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cloudflare/cloudflare-go v0.114.0 h1:ucoti4/7Exo0XQ+rzpn1H+IfVVe++zgiM+tyKtf0HUA=
|
github.com/cloudflare/cloudflare-go v0.114.0 h1:ucoti4/7Exo0XQ+rzpn1H+IfVVe++zgiM+tyKtf0HUA=
|
||||||
github.com/cloudflare/cloudflare-go v0.114.0/go.mod h1:O7fYfFfA6wKqKFn2QIR9lhj7FDw6VQCGOY6hd2TBtd0=
|
github.com/cloudflare/cloudflare-go v0.114.0/go.mod h1:O7fYfFfA6wKqKFn2QIR9lhj7FDw6VQCGOY6hd2TBtd0=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
|
||||||
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
|
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
|
||||||
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
|
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
|
||||||
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
|
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
|
||||||
|
|
@ -118,8 +68,8 @@ github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/e
|
||||||
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
|
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
|
||||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
|
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
|
||||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
||||||
github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA=
|
github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw=
|
||||||
github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU=
|
github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo=
|
||||||
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
|
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
|
||||||
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
||||||
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
|
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
|
||||||
|
|
@ -162,10 +112,6 @@ github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjU
|
||||||
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
|
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
|
||||||
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
||||||
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
|
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
|
||||||
github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w=
|
github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w=
|
||||||
github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E=
|
github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E=
|
||||||
github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
|
github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
|
||||||
|
|
@ -191,15 +137,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
||||||
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
|
||||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
|
||||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
|
||||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
|
|
@ -207,86 +144,44 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
|
||||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
|
||||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
|
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
|
||||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
|
||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
|
||||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
|
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
|
||||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U=
|
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U=
|
||||||
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
|
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
|
||||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
|
@ -294,8 +189,6 @@ github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY4
|
||||||
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
|
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
|
||||||
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
|
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
|
||||||
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
|
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
||||||
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4=
|
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4=
|
||||||
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
|
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
|
||||||
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
|
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
|
||||||
|
|
@ -306,7 +199,6 @@ github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
||||||
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||||
github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k=
|
github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k=
|
||||||
github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
|
github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
|
||||||
|
|
@ -322,15 +214,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
|
||||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
|
||||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
|
||||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
|
||||||
github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I=
|
github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I=
|
||||||
github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8=
|
github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8=
|
||||||
github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4=
|
github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4=
|
||||||
|
|
@ -342,9 +225,6 @@ github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs
|
||||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
|
|
@ -378,9 +258,8 @@ github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
|
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
|
||||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||||
|
|
@ -390,13 +269,6 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh
|
||||||
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
|
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
|
||||||
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
|
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
|
||||||
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
|
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
|
||||||
github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
|
github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
|
||||||
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
||||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0=
|
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0=
|
||||||
|
|
@ -431,7 +303,6 @@ github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
|
@ -439,29 +310,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
|
||||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||||
github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg=
|
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
|
||||||
github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y=
|
|
||||||
github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
|
||||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
|
||||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
|
||||||
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
|
|
||||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
|
||||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
|
||||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
|
||||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
|
||||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
|
||||||
github.com/protolambda/bls12-381-util v0.1.0 h1:05DU2wJN7DTU7z28+Q+zejXkIsA/MF8JZQGhtBZZiWk=
|
github.com/protolambda/bls12-381-util v0.1.0 h1:05DU2wJN7DTU7z28+Q+zejXkIsA/MF8JZQGhtBZZiWk=
|
||||||
github.com/protolambda/bls12-381-util v0.1.0/go.mod h1:cdkysJTRpeFeuUVx/TXGDQNMTiRAalk1vQw3TYTHcE4=
|
github.com/protolambda/bls12-381-util v0.1.0/go.mod h1:cdkysJTRpeFeuUVx/TXGDQNMTiRAalk1vQw3TYTHcE4=
|
||||||
github.com/protolambda/zrnt v0.34.1 h1:qW55rnhZJDnOb3TwFiFRJZi3yTXFrJdGOFQM7vCwYGg=
|
github.com/protolambda/zrnt v0.34.1 h1:qW55rnhZJDnOb3TwFiFRJZi3yTXFrJdGOFQM7vCwYGg=
|
||||||
|
|
@ -472,7 +328,6 @@ github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48 h
|
||||||
github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
|
github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||||
|
|
@ -483,16 +338,11 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
|
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
|
||||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
|
||||||
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
|
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
|
||||||
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
|
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
|
@ -518,24 +368,14 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
|
go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
|
||||||
go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
|
@ -545,77 +385,24 @@ golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
|
||||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
|
||||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
|
||||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
|
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
|
||||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||||
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
|
|
@ -623,78 +410,37 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
||||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
@ -716,9 +462,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
|
@ -730,54 +474,14 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
|
||||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
|
||||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
|
||||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
|
@ -788,87 +492,16 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
|
||||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
|
||||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
|
||||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
|
||||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
|
||||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
|
||||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
|
||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
|
||||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
|
||||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
|
||||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
|
||||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
|
@ -877,10 +510,8 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
|
@ -888,15 +519,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
|
||||||
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
|
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
|
||||||
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
|
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, *Block)
|
||||||
return t.tx, t.block
|
return t.tx, t.block
|
||||||
}
|
}
|
||||||
// Try to return an already finalized transaction
|
// Try to return an already finalized transaction
|
||||||
found, tx, blockHash, _, index, _ := t.r.backend.GetTransaction(ctx, t.hash)
|
found, tx, blockHash, _, index := t.r.backend.GetTransaction(t.hash)
|
||||||
if found {
|
if found {
|
||||||
t.tx = tx
|
t.tx = tx
|
||||||
blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
|
blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
|
||||||
|
|
@ -1530,8 +1530,8 @@ func (s *SyncState) TxIndexRemainingBlocks() hexutil.Uint64 {
|
||||||
// - healingBytecode: number of bytecodes pending
|
// - healingBytecode: number of bytecodes pending
|
||||||
// - txIndexFinishedBlocks: number of blocks whose transactions are indexed
|
// - txIndexFinishedBlocks: number of blocks whose transactions are indexed
|
||||||
// - txIndexRemainingBlocks: number of blocks whose transactions are not indexed yet
|
// - txIndexRemainingBlocks: number of blocks whose transactions are not indexed yet
|
||||||
func (r *Resolver) Syncing() (*SyncState, error) {
|
func (r *Resolver) Syncing(ctx context.Context) (*SyncState, error) {
|
||||||
progress := r.backend.SyncProgress()
|
progress := r.backend.SyncProgress(ctx)
|
||||||
|
|
||||||
// Return not syncing if the synchronisation already completed
|
// Return not syncing if the synchronisation already completed
|
||||||
if progress.Done() {
|
if progress.Done() {
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ func (tt *TestCmd) Kill() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tt *TestCmd) withKillTimeout(fn func()) {
|
func (tt *TestCmd) withKillTimeout(fn func()) {
|
||||||
timeout := time.AfterFunc(30*time.Second, func() {
|
timeout := time.AfterFunc(2*time.Minute, func() {
|
||||||
tt.Log("killing the child process (timeout)")
|
tt.Log("killing the child process (timeout)")
|
||||||
tt.Kill()
|
tt.Kill()
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -144,8 +144,8 @@ func (api *EthereumAPI) BlobBaseFee(ctx context.Context) *hexutil.Big {
|
||||||
// - highestBlock: block number of the highest block header this node has received from peers
|
// - highestBlock: block number of the highest block header this node has received from peers
|
||||||
// - pulledStates: number of state entries processed until now
|
// - pulledStates: number of state entries processed until now
|
||||||
// - knownStates: number of known state entries that still need to be pulled
|
// - knownStates: number of known state entries that still need to be pulled
|
||||||
func (api *EthereumAPI) Syncing() (interface{}, error) {
|
func (api *EthereumAPI) Syncing(ctx context.Context) (interface{}, error) {
|
||||||
progress := api.b.SyncProgress()
|
progress := api.b.SyncProgress(ctx)
|
||||||
|
|
||||||
// Return not syncing if the synchronisation already completed
|
// Return not syncing if the synchronisation already completed
|
||||||
if progress.Done() {
|
if progress.Done() {
|
||||||
|
|
@ -1333,17 +1333,19 @@ func (api *TransactionAPI) GetTransactionCount(ctx context.Context, address comm
|
||||||
// GetTransactionByHash returns the transaction for the given hash
|
// GetTransactionByHash returns the transaction for the given hash
|
||||||
func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
|
func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
|
||||||
// Try to return an already finalized transaction
|
// Try to return an already finalized transaction
|
||||||
found, tx, blockHash, blockNumber, index, err := api.b.GetTransaction(ctx, hash)
|
found, tx, blockHash, blockNumber, index := api.b.GetTransaction(hash)
|
||||||
if !found {
|
if !found {
|
||||||
// No finalized transaction, try to retrieve it from the pool
|
// No finalized transaction, try to retrieve it from the pool
|
||||||
if tx := api.b.GetPoolTransaction(hash); tx != nil {
|
if tx := api.b.GetPoolTransaction(hash); tx != nil {
|
||||||
return NewRPCPendingTransaction(tx, api.b.CurrentHeader(), api.b.ChainConfig()), nil
|
return NewRPCPendingTransaction(tx, api.b.CurrentHeader(), api.b.ChainConfig()), nil
|
||||||
}
|
}
|
||||||
if err == nil {
|
// If also not in the pool there is a chance the tx indexer is still in progress.
|
||||||
return nil, nil
|
if !api.b.TxIndexDone() {
|
||||||
}
|
|
||||||
return nil, NewTxIndexingError()
|
return nil, NewTxIndexingError()
|
||||||
}
|
}
|
||||||
|
// If the transaction is not found in the pool and the indexer is done, return nil
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
header, err := api.b.HeaderByHash(ctx, blockHash)
|
header, err := api.b.HeaderByHash(ctx, blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1354,27 +1356,31 @@ func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common
|
||||||
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
|
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
|
||||||
func (api *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
func (api *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
||||||
// Retrieve a finalized transaction, or a pooled otherwise
|
// Retrieve a finalized transaction, or a pooled otherwise
|
||||||
found, tx, _, _, _, err := api.b.GetTransaction(ctx, hash)
|
found, tx, _, _, _ := api.b.GetTransaction(hash)
|
||||||
if !found {
|
if !found {
|
||||||
if tx = api.b.GetPoolTransaction(hash); tx != nil {
|
if tx = api.b.GetPoolTransaction(hash); tx != nil {
|
||||||
return tx.MarshalBinary()
|
return tx.MarshalBinary()
|
||||||
}
|
}
|
||||||
if err == nil {
|
// If also not in the pool there is a chance the tx indexer is still in progress.
|
||||||
return nil, nil
|
if !api.b.TxIndexDone() {
|
||||||
}
|
|
||||||
return nil, NewTxIndexingError()
|
return nil, NewTxIndexingError()
|
||||||
}
|
}
|
||||||
|
// If the transaction is not found in the pool and the indexer is done, return nil
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return tx.MarshalBinary()
|
return tx.MarshalBinary()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
|
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
|
||||||
func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
|
func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
|
||||||
found, tx, blockHash, blockNumber, index, err := api.b.GetTransaction(ctx, hash)
|
found, tx, blockHash, blockNumber, index := api.b.GetTransaction(hash)
|
||||||
if err != nil {
|
|
||||||
return nil, NewTxIndexingError() // transaction is not fully indexed
|
|
||||||
}
|
|
||||||
if !found {
|
if !found {
|
||||||
return nil, nil // transaction is not existent or reachable
|
// Make sure indexer is done.
|
||||||
|
if !api.b.TxIndexDone() {
|
||||||
|
return nil, NewTxIndexingError()
|
||||||
|
}
|
||||||
|
// No such tx.
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
header, err := api.b.HeaderByHash(ctx, blockHash)
|
header, err := api.b.HeaderByHash(ctx, blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1774,16 +1780,18 @@ func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.Block
|
||||||
// GetRawTransaction returns the bytes of the transaction for the given hash.
|
// GetRawTransaction returns the bytes of the transaction for the given hash.
|
||||||
func (api *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
func (api *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
||||||
// Retrieve a finalized transaction, or a pooled otherwise
|
// Retrieve a finalized transaction, or a pooled otherwise
|
||||||
found, tx, _, _, _, err := api.b.GetTransaction(ctx, hash)
|
found, tx, _, _, _ := api.b.GetTransaction(hash)
|
||||||
if !found {
|
if !found {
|
||||||
if tx = api.b.GetPoolTransaction(hash); tx != nil {
|
if tx = api.b.GetPoolTransaction(hash); tx != nil {
|
||||||
return tx.MarshalBinary()
|
return tx.MarshalBinary()
|
||||||
}
|
}
|
||||||
if err == nil {
|
// If also not in the pool there is a chance the tx indexer is still in progress.
|
||||||
return nil, nil
|
if !api.b.TxIndexDone() {
|
||||||
}
|
|
||||||
return nil, NewTxIndexingError()
|
return nil, NewTxIndexingError()
|
||||||
}
|
}
|
||||||
|
// Transaction is not found in the pool and the indexer is done.
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return tx.MarshalBinary()
|
return tx.MarshalBinary()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -472,7 +472,9 @@ func (b *testBackend) setPendingBlock(block *types.Block) {
|
||||||
b.pending = block
|
b.pending = block
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b testBackend) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
|
func (b testBackend) SyncProgress(ctx context.Context) ethereum.SyncProgress {
|
||||||
|
return ethereum.SyncProgress{}
|
||||||
|
}
|
||||||
func (b testBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
|
func (b testBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
|
||||||
return big.NewInt(0), nil
|
return big.NewInt(0), nil
|
||||||
}
|
}
|
||||||
|
|
@ -589,9 +591,12 @@ func (b testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) even
|
||||||
func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
|
func (b testBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
|
||||||
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
|
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
|
||||||
return true, tx, blockHash, blockNumber, index, nil
|
return true, tx, blockHash, blockNumber, index
|
||||||
|
}
|
||||||
|
func (b testBackend) TxIndexDone() bool {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") }
|
func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") }
|
||||||
func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") }
|
func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") }
|
||||||
|
|
@ -2483,6 +2488,77 @@ func TestSimulateV1ChainLinkage(t *testing.T) {
|
||||||
require.Equal(t, block2.Hash().Bytes(), []byte(results[2].Calls[1].ReturnValue), "returned blockhash for block2 does not match")
|
require.Equal(t, block2.Hash().Bytes(), []byte(results[2].Calls[1].ReturnValue), "returned blockhash for block2 does not match")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSimulateV1TxSender(t *testing.T) {
|
||||||
|
var (
|
||||||
|
sender = common.Address{0xaa, 0xaa}
|
||||||
|
sender2 = common.Address{0xaa, 0xab}
|
||||||
|
sender3 = common.Address{0xaa, 0xac}
|
||||||
|
recipient = common.Address{0xbb, 0xbb}
|
||||||
|
gspec = &core.Genesis{
|
||||||
|
Config: params.MergedTestChainConfig,
|
||||||
|
Alloc: types.GenesisAlloc{
|
||||||
|
sender: {Balance: big.NewInt(params.Ether)},
|
||||||
|
sender2: {Balance: big.NewInt(params.Ether)},
|
||||||
|
sender3: {Balance: big.NewInt(params.Ether)},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx = context.Background()
|
||||||
|
)
|
||||||
|
backend := newTestBackend(t, 0, gspec, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {})
|
||||||
|
stateDB, baseHeader, err := backend.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to get state and header: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sim := &simulator{
|
||||||
|
b: backend,
|
||||||
|
state: stateDB,
|
||||||
|
base: baseHeader,
|
||||||
|
chainConfig: backend.ChainConfig(),
|
||||||
|
gp: new(core.GasPool).AddGas(math.MaxUint64),
|
||||||
|
traceTransfers: false,
|
||||||
|
validate: false,
|
||||||
|
fullTx: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := sim.execute(ctx, []simBlock{
|
||||||
|
{Calls: []TransactionArgs{
|
||||||
|
{From: &sender, To: &recipient, Value: (*hexutil.Big)(big.NewInt(1000))},
|
||||||
|
{From: &sender2, To: &recipient, Value: (*hexutil.Big)(big.NewInt(2000))},
|
||||||
|
{From: &sender3, To: &recipient, Value: (*hexutil.Big)(big.NewInt(3000))},
|
||||||
|
}},
|
||||||
|
{Calls: []TransactionArgs{
|
||||||
|
{From: &sender2, To: &recipient, Value: (*hexutil.Big)(big.NewInt(4000))},
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("simulation execution failed: %v", err)
|
||||||
|
}
|
||||||
|
require.Len(t, results, 2, "expected 2 simulated blocks")
|
||||||
|
require.Len(t, results[0].Block.Transactions(), 3, "expected 3 transaction in simulated block")
|
||||||
|
require.Len(t, results[1].Block.Transactions(), 1, "expected 1 transaction in 2nd simulated block")
|
||||||
|
enc, err := json.Marshal(results)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to marshal results: %v", err)
|
||||||
|
}
|
||||||
|
type resultType struct {
|
||||||
|
Transactions []struct {
|
||||||
|
From common.Address `json:"from"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var summary []resultType
|
||||||
|
if err := json.Unmarshal(enc, &summary); err != nil {
|
||||||
|
t.Fatalf("failed to unmarshal results: %v", err)
|
||||||
|
}
|
||||||
|
require.Len(t, summary, 2, "expected 2 simulated blocks")
|
||||||
|
require.Len(t, summary[0].Transactions, 3, "expected 3 transaction in simulated block")
|
||||||
|
require.Equal(t, sender, summary[0].Transactions[0].From, "sender address mismatch")
|
||||||
|
require.Equal(t, sender2, summary[0].Transactions[1].From, "sender address mismatch")
|
||||||
|
require.Equal(t, sender3, summary[0].Transactions[2].From, "sender address mismatch")
|
||||||
|
require.Len(t, summary[1].Transactions, 1, "expected 1 transaction in simulated block")
|
||||||
|
require.Equal(t, sender2, summary[1].Transactions[0].From, "sender address mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
func TestSignTransaction(t *testing.T) {
|
func TestSignTransaction(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// Initialize test accounts
|
// Initialize test accounts
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ import (
|
||||||
// both full and light clients) with access to necessary functions.
|
// both full and light clients) with access to necessary functions.
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
// General Ethereum API
|
// General Ethereum API
|
||||||
SyncProgress() ethereum.SyncProgress
|
SyncProgress(ctx context.Context) ethereum.SyncProgress
|
||||||
|
|
||||||
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
|
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
|
||||||
FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error)
|
FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error)
|
||||||
|
|
@ -74,7 +74,8 @@ type Backend interface {
|
||||||
|
|
||||||
// Transaction pool API
|
// Transaction pool API
|
||||||
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
||||||
GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
|
GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64)
|
||||||
|
TxIndexDone() bool
|
||||||
GetPoolTransactions() (types.Transactions, error)
|
GetPoolTransactions() (types.Transactions, error)
|
||||||
GetPoolTransaction(txHash common.Hash) *types.Transaction
|
GetPoolTransaction(txHash common.Hash) *types.Transaction
|
||||||
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
|
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,25 @@ type simBlockResult struct {
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
Block *types.Block
|
Block *types.Block
|
||||||
Calls []simCallResult
|
Calls []simCallResult
|
||||||
|
// senders is a map of transaction hashes to their senders.
|
||||||
|
senders map[common.Hash]common.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *simBlockResult) MarshalJSON() ([]byte, error) {
|
func (r *simBlockResult) MarshalJSON() ([]byte, error) {
|
||||||
blockData := RPCMarshalBlock(r.Block, true, r.fullTx, r.chainConfig)
|
blockData := RPCMarshalBlock(r.Block, true, r.fullTx, r.chainConfig)
|
||||||
blockData["calls"] = r.Calls
|
blockData["calls"] = r.Calls
|
||||||
|
// Set tx sender if user requested full tx objects.
|
||||||
|
if r.fullTx {
|
||||||
|
if raw, ok := blockData["transactions"].([]any); ok {
|
||||||
|
for _, tx := range raw {
|
||||||
|
if tx, ok := tx.(*RPCTransaction); ok {
|
||||||
|
tx.From = r.senders[tx.Hash]
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("simulated transaction result has invalid type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return json.Marshal(blockData)
|
return json.Marshal(blockData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,18 +195,18 @@ func (sim *simulator) execute(ctx context.Context, blocks []simBlock) ([]*simBlo
|
||||||
parent = sim.base
|
parent = sim.base
|
||||||
)
|
)
|
||||||
for bi, block := range blocks {
|
for bi, block := range blocks {
|
||||||
result, callResults, err := sim.processBlock(ctx, &block, headers[bi], parent, headers[:bi], timeout)
|
result, callResults, senders, err := sim.processBlock(ctx, &block, headers[bi], parent, headers[:bi], timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
headers[bi] = result.Header()
|
headers[bi] = result.Header()
|
||||||
results[bi] = &simBlockResult{fullTx: sim.fullTx, chainConfig: sim.chainConfig, Block: result, Calls: callResults}
|
results[bi] = &simBlockResult{fullTx: sim.fullTx, chainConfig: sim.chainConfig, Block: result, Calls: callResults, senders: senders}
|
||||||
parent = result.Header()
|
parent = result.Header()
|
||||||
}
|
}
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, parent *types.Header, headers []*types.Header, timeout time.Duration) (*types.Block, []simCallResult, error) {
|
func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, parent *types.Header, headers []*types.Header, timeout time.Duration) (*types.Block, []simCallResult, map[common.Hash]common.Address, error) {
|
||||||
// Set header fields that depend only on parent block.
|
// Set header fields that depend only on parent block.
|
||||||
// Parent hash is needed for evm.GetHashFn to work.
|
// Parent hash is needed for evm.GetHashFn to work.
|
||||||
header.ParentHash = parent.Hash()
|
header.ParentHash = parent.Hash()
|
||||||
|
|
@ -222,7 +236,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
precompiles := sim.activePrecompiles(sim.base)
|
precompiles := sim.activePrecompiles(sim.base)
|
||||||
// State overrides are applied prior to execution of a block
|
// State overrides are applied prior to execution of a block
|
||||||
if err := block.StateOverrides.Apply(sim.state, precompiles); err != nil {
|
if err := block.StateOverrides.Apply(sim.state, precompiles); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
gasUsed, blobGasUsed uint64
|
gasUsed, blobGasUsed uint64
|
||||||
|
|
@ -235,6 +249,10 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
NoBaseFee: !sim.validate,
|
NoBaseFee: !sim.validate,
|
||||||
Tracer: tracer.Hooks(),
|
Tracer: tracer.Hooks(),
|
||||||
}
|
}
|
||||||
|
// senders is a map of transaction hashes to their senders.
|
||||||
|
// Transaction objects contain only the signature, and we lose track
|
||||||
|
// of the sender when translating the arguments into a transaction object.
|
||||||
|
senders = make(map[common.Hash]common.Address)
|
||||||
)
|
)
|
||||||
tracingStateDB := vm.StateDB(sim.state)
|
tracingStateDB := vm.StateDB(sim.state)
|
||||||
if hooks := tracer.Hooks(); hooks != nil {
|
if hooks := tracer.Hooks(); hooks != nil {
|
||||||
|
|
@ -255,16 +273,17 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
var allLogs []*types.Log
|
var allLogs []*types.Log
|
||||||
for i, call := range block.Calls {
|
for i, call := range block.Calls {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
if err := sim.sanitizeCall(&call, sim.state, header, blockContext, &gasUsed); err != nil {
|
if err := sim.sanitizeCall(&call, sim.state, header, blockContext, &gasUsed); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
tx = call.ToTransaction(types.DynamicFeeTxType)
|
tx = call.ToTransaction(types.DynamicFeeTxType)
|
||||||
txHash = tx.Hash()
|
txHash = tx.Hash()
|
||||||
)
|
)
|
||||||
txes[i] = tx
|
txes[i] = tx
|
||||||
|
senders[txHash] = call.from()
|
||||||
tracer.reset(txHash, uint(i))
|
tracer.reset(txHash, uint(i))
|
||||||
sim.state.SetTxContext(txHash, i)
|
sim.state.SetTxContext(txHash, i)
|
||||||
// EoA check is always skipped, even in validation mode.
|
// EoA check is always skipped, even in validation mode.
|
||||||
|
|
@ -272,7 +291,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
|
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
txErr := txValidationError(err)
|
txErr := txValidationError(err)
|
||||||
return nil, nil, txErr
|
return nil, nil, nil, txErr
|
||||||
}
|
}
|
||||||
// Update the state with pending changes.
|
// Update the state with pending changes.
|
||||||
var root []byte
|
var root []byte
|
||||||
|
|
@ -311,15 +330,15 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
requests = [][]byte{}
|
requests = [][]byte{}
|
||||||
// EIP-6110
|
// EIP-6110
|
||||||
if err := core.ParseDepositLogs(&requests, allLogs, sim.chainConfig); err != nil {
|
if err := core.ParseDepositLogs(&requests, allLogs, sim.chainConfig); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
// EIP-7002
|
// EIP-7002
|
||||||
if err := core.ProcessWithdrawalQueue(&requests, evm); err != nil {
|
if err := core.ProcessWithdrawalQueue(&requests, evm); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
// EIP-7251
|
// EIP-7251
|
||||||
if err := core.ProcessConsolidationQueue(&requests, evm); err != nil {
|
if err := core.ProcessConsolidationQueue(&requests, evm); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if requests != nil {
|
if requests != nil {
|
||||||
|
|
@ -330,10 +349,10 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
chainHeadReader := &simChainHeadReader{ctx, sim.b}
|
chainHeadReader := &simChainHeadReader{ctx, sim.b}
|
||||||
b, err := sim.b.Engine().FinalizeAndAssemble(chainHeadReader, header, sim.state, blockBody, receipts)
|
b, err := sim.b.Engine().FinalizeAndAssemble(chainHeadReader, header, sim.state, blockBody, receipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
repairLogs(callResults, b.Hash())
|
repairLogs(callResults, b.Hash())
|
||||||
return b, callResults, nil
|
return b, callResults, senders, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// repairLogs updates the block hash in the logs present in the result of
|
// repairLogs updates the block hash in the logs present in the result of
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,9 @@ func (b *backendMock) CurrentHeader() *types.Header { return b.current }
|
||||||
func (b *backendMock) ChainConfig() *params.ChainConfig { return b.config }
|
func (b *backendMock) ChainConfig() *params.ChainConfig { return b.config }
|
||||||
|
|
||||||
// Other methods needed to implement Backend interface.
|
// Other methods needed to implement Backend interface.
|
||||||
func (b *backendMock) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
|
func (b *backendMock) SyncProgress(ctx context.Context) ethereum.SyncProgress {
|
||||||
|
return ethereum.SyncProgress{}
|
||||||
|
}
|
||||||
func (b *backendMock) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) {
|
func (b *backendMock) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) {
|
||||||
return nil, nil, nil, nil, nil, nil, nil
|
return nil, nil, nil, nil, nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -378,9 +380,10 @@ func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) eve
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
|
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
|
||||||
func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
|
func (b *backendMock) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
|
||||||
return false, nil, [32]byte{}, 0, 0, nil
|
return false, nil, [32]byte{}, 0, 0
|
||||||
}
|
}
|
||||||
|
func (b *backendMock) TxIndexDone() bool { return true }
|
||||||
func (b *backendMock) GetPoolTransactions() (types.Transactions, error) { return nil, nil }
|
func (b *backendMock) GetPoolTransactions() (types.Transactions, error) { return nil, nil }
|
||||||
func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
|
func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
|
||||||
func (b *backendMock) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
|
func (b *backendMock) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
|
||||||
|
|
|
||||||
|
|
@ -247,11 +247,6 @@ web3._extend({
|
||||||
call: 'debug_vmodule',
|
call: 'debug_vmodule',
|
||||||
params: 1
|
params: 1
|
||||||
}),
|
}),
|
||||||
new web3._extend.Method({
|
|
||||||
name: 'backtraceAt',
|
|
||||||
call: 'debug_backtraceAt',
|
|
||||||
params: 1,
|
|
||||||
}),
|
|
||||||
new web3._extend.Method({
|
new web3._extend.Method({
|
||||||
name: 'stacks',
|
name: 'stacks',
|
||||||
call: 'debug_stacks',
|
call: 'debug_stacks',
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,6 @@ type openOptions struct {
|
||||||
Cache int // the capacity(in megabytes) of the data caching
|
Cache int // the capacity(in megabytes) of the data caching
|
||||||
Handles int // number of files to be open simultaneously
|
Handles int // number of files to be open simultaneously
|
||||||
ReadOnly bool
|
ReadOnly bool
|
||||||
|
|
||||||
// Ephemeral means that filesystem sync operations should be avoided:
|
|
||||||
// data integrity in the face of a crash is not important. This option
|
|
||||||
// should typically be used in tests.
|
|
||||||
Ephemeral bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// openDatabase opens both a disk-based key-value database such as leveldb or pebble, but also
|
// openDatabase opens both a disk-based key-value database such as leveldb or pebble, but also
|
||||||
|
|
@ -83,7 +78,7 @@ func openKeyValueDatabase(o openOptions) (ethdb.Database, error) {
|
||||||
}
|
}
|
||||||
if o.Type == rawdb.DBPebble || existingDb == rawdb.DBPebble {
|
if o.Type == rawdb.DBPebble || existingDb == rawdb.DBPebble {
|
||||||
log.Info("Using pebble as the backing database")
|
log.Info("Using pebble as the backing database")
|
||||||
return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral)
|
return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||||
}
|
}
|
||||||
if o.Type == rawdb.DBLeveldb || existingDb == rawdb.DBLeveldb {
|
if o.Type == rawdb.DBLeveldb || existingDb == rawdb.DBLeveldb {
|
||||||
log.Info("Using leveldb as the backing database")
|
log.Info("Using leveldb as the backing database")
|
||||||
|
|
@ -91,7 +86,7 @@ func openKeyValueDatabase(o openOptions) (ethdb.Database, error) {
|
||||||
}
|
}
|
||||||
// No pre-existing database, no user-requested one either. Default to Pebble.
|
// No pre-existing database, no user-requested one either. Default to Pebble.
|
||||||
log.Info("Defaulting to pebble as the backing database")
|
log.Info("Defaulting to pebble as the backing database")
|
||||||
return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral)
|
return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLevelDBDatabase creates a persistent key-value database without a freezer
|
// newLevelDBDatabase creates a persistent key-value database without a freezer
|
||||||
|
|
@ -107,8 +102,8 @@ func newLevelDBDatabase(file string, cache int, handles int, namespace string, r
|
||||||
|
|
||||||
// newPebbleDBDatabase creates a persistent key-value database without a freezer
|
// newPebbleDBDatabase creates a persistent key-value database without a freezer
|
||||||
// moving immutable chain segments into cold storage.
|
// moving immutable chain segments into cold storage.
|
||||||
func newPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (ethdb.Database, error) {
|
func newPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) {
|
||||||
db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral)
|
db, err := pebble.New(file, cache, handles, namespace, readonly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -570,7 +570,6 @@ func TestHTTPWriteTimeout(t *testing.T) {
|
||||||
// Send normal request
|
// Send normal request
|
||||||
t.Run("message", func(t *testing.T) {
|
t.Run("message", func(t *testing.T) {
|
||||||
resp := rpcRequest(t, url, "test_sleep")
|
resp := rpcRequest(t, url, "test_sleep")
|
||||||
defer resp.Body.Close()
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -584,7 +583,6 @@ func TestHTTPWriteTimeout(t *testing.T) {
|
||||||
t.Run("batch", func(t *testing.T) {
|
t.Run("batch", func(t *testing.T) {
|
||||||
want := fmt.Sprintf("[%s,%s,%s]", greetRes, timeoutRes, timeoutRes)
|
want := fmt.Sprintf("[%s,%s,%s]", greetRes, timeoutRes, timeoutRes)
|
||||||
resp := batchRpcRequest(t, url, []string{"test_greet", "test_sleep", "test_greet"})
|
resp := batchRpcRequest(t, url, []string{"test_greet", "test_sleep", "test_greet"})
|
||||||
defer resp.Body.Close()
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,18 @@ var (
|
||||||
|
|
||||||
// capture the rest of errors that are not handled by the above meters
|
// capture the rest of errors that are not handled by the above meters
|
||||||
dialOtherError = metrics.NewRegisteredMeter("p2p/dials/error/other", nil)
|
dialOtherError = metrics.NewRegisteredMeter("p2p/dials/error/other", nil)
|
||||||
|
|
||||||
|
// handshake error meters for inbound connections
|
||||||
|
serveTooManyPeers = metrics.NewRegisteredMeter("p2p/serves/error/saturated", nil)
|
||||||
|
serveAlreadyConnected = metrics.NewRegisteredMeter("p2p/serves/error/known", nil)
|
||||||
|
serveSelf = metrics.NewRegisteredMeter("p2p/serves/error/self", nil)
|
||||||
|
serveUselessPeer = metrics.NewRegisteredMeter("p2p/serves/error/useless", nil)
|
||||||
|
serveUnexpectedIdentity = metrics.NewRegisteredMeter("p2p/serves/error/id/unexpected", nil)
|
||||||
|
serveEncHandshakeError = metrics.NewRegisteredMeter("p2p/serves/error/rlpx/enc", nil) //EOF; connection reset during handshake; (message too big?)
|
||||||
|
serveProtoHandshakeError = metrics.NewRegisteredMeter("p2p/serves/error/rlpx/proto", nil)
|
||||||
|
|
||||||
|
// capture the rest of errors that are not handled by the above meters
|
||||||
|
serveOtherError = metrics.NewRegisteredMeter("p2p/serves/error/other", nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
// markDialError matches errors that occur while setting up a dial connection to the
|
// markDialError matches errors that occur while setting up a dial connection to the
|
||||||
|
|
@ -99,6 +111,36 @@ func markDialError(err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// markServeError matches errors that occur while serving an inbound connection
|
||||||
|
// to the corresponding meter.
|
||||||
|
func markServeError(err error) {
|
||||||
|
if !metrics.Enabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var reason DiscReason
|
||||||
|
var handshakeErr *protoHandshakeError
|
||||||
|
d := errors.As(err, &reason)
|
||||||
|
switch {
|
||||||
|
case d && reason == DiscTooManyPeers:
|
||||||
|
serveTooManyPeers.Mark(1)
|
||||||
|
case d && reason == DiscAlreadyConnected:
|
||||||
|
serveAlreadyConnected.Mark(1)
|
||||||
|
case d && reason == DiscSelf:
|
||||||
|
serveSelf.Mark(1)
|
||||||
|
case d && reason == DiscUselessPeer:
|
||||||
|
serveUselessPeer.Mark(1)
|
||||||
|
case d && reason == DiscUnexpectedIdentity:
|
||||||
|
serveUnexpectedIdentity.Mark(1)
|
||||||
|
case errors.As(err, &handshakeErr):
|
||||||
|
serveProtoHandshakeError.Mark(1)
|
||||||
|
case errors.Is(err, errEncHandshakeError):
|
||||||
|
serveEncHandshakeError.Mark(1)
|
||||||
|
default:
|
||||||
|
serveOtherError.Mark(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// meteredConn is a wrapper around a net.Conn that meters both the
|
// meteredConn is a wrapper around a net.Conn that meters both the
|
||||||
// inbound and outbound network traffic.
|
// inbound and outbound network traffic.
|
||||||
type meteredConn struct {
|
type meteredConn struct {
|
||||||
|
|
|
||||||
|
|
@ -864,6 +864,8 @@ func (srv *Server) SetupConn(fd net.Conn, flags connFlag, dialDest *enode.Node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !c.is(inboundConn) {
|
if !c.is(inboundConn) {
|
||||||
markDialError(err)
|
markDialError(err)
|
||||||
|
} else {
|
||||||
|
markServeError(err)
|
||||||
}
|
}
|
||||||
c.close(err)
|
c.close(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ var (
|
||||||
Max: 9,
|
Max: 9,
|
||||||
UpdateFraction: 5007716,
|
UpdateFraction: 5007716,
|
||||||
}
|
}
|
||||||
// DefaultBlobSchedule is the latest configured blob schedule for test chains.
|
// DefaultBlobSchedule is the latest configured blob schedule for Ethereum mainnet.
|
||||||
DefaultBlobSchedule = &BlobScheduleConfig{
|
DefaultBlobSchedule = &BlobScheduleConfig{
|
||||||
Cancun: DefaultCancunBlobConfig,
|
Cancun: DefaultCancunBlobConfig,
|
||||||
Prague: DefaultPragueBlobConfig,
|
Prague: DefaultPragueBlobConfig,
|
||||||
|
|
|
||||||
|
|
@ -501,6 +501,10 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage
|
||||||
if msg.isUnsubscribe() {
|
if msg.isUnsubscribe() {
|
||||||
callb = h.unsubscribeCb
|
callb = h.unsubscribeCb
|
||||||
} else {
|
} else {
|
||||||
|
// Check method name length
|
||||||
|
if len(msg.Method) > maxMethodNameLength {
|
||||||
|
return msg.errorResponse(&invalidRequestError{fmt.Sprintf("method name too long: %d > %d", len(msg.Method), maxMethodNameLength)})
|
||||||
|
}
|
||||||
callb = h.reg.callback(msg.Method)
|
callb = h.reg.callback(msg.Method)
|
||||||
}
|
}
|
||||||
if callb == nil {
|
if callb == nil {
|
||||||
|
|
@ -536,6 +540,11 @@ func (h *handler) handleSubscribe(cp *callProc, msg *jsonrpcMessage) *jsonrpcMes
|
||||||
return msg.errorResponse(ErrNotificationsUnsupported)
|
return msg.errorResponse(ErrNotificationsUnsupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check method name length
|
||||||
|
if len(msg.Method) > maxMethodNameLength {
|
||||||
|
return msg.errorResponse(&invalidRequestError{fmt.Sprintf("subscription name too long: %d > %d", len(msg.Method), maxMethodNameLength)})
|
||||||
|
}
|
||||||
|
|
||||||
// Subscription method name is first argument.
|
// Subscription method name is first argument.
|
||||||
name, err := parseSubscriptionName(msg.Params)
|
name, err := parseSubscriptionName(msg.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ const (
|
||||||
subscribeMethodSuffix = "_subscribe"
|
subscribeMethodSuffix = "_subscribe"
|
||||||
unsubscribeMethodSuffix = "_unsubscribe"
|
unsubscribeMethodSuffix = "_unsubscribe"
|
||||||
notificationMethodSuffix = "_subscription"
|
notificationMethodSuffix = "_subscription"
|
||||||
|
maxMethodNameLength = 2048
|
||||||
|
|
||||||
defaultWriteTimeout = 10 * time.Second // used if context has no deadline
|
defaultWriteTimeout = 10 * time.Second // used if context has no deadline
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -391,3 +391,77 @@ func wsPingTestHandler(t *testing.T, conn *websocket.Conn, shutdown, sendPing <-
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWebsocketMethodNameLengthLimit(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var (
|
||||||
|
srv = newTestServer()
|
||||||
|
httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"}))
|
||||||
|
wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
|
||||||
|
)
|
||||||
|
defer srv.Stop()
|
||||||
|
defer httpsrv.Close()
|
||||||
|
|
||||||
|
client, err := DialWebsocket(context.Background(), wsURL, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't dial: %v", err)
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
// Test cases
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
method string
|
||||||
|
params []interface{}
|
||||||
|
expectedError string
|
||||||
|
isSubscription bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid method name",
|
||||||
|
method: "test_echo",
|
||||||
|
params: []interface{}{"test", 1},
|
||||||
|
expectedError: "",
|
||||||
|
isSubscription: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "method name too long",
|
||||||
|
method: "test_" + string(make([]byte, maxMethodNameLength+1)),
|
||||||
|
params: []interface{}{"test", 1},
|
||||||
|
expectedError: "method name too long",
|
||||||
|
isSubscription: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid subscription",
|
||||||
|
method: "nftest_subscribe",
|
||||||
|
params: []interface{}{"someSubscription", 1, 2},
|
||||||
|
expectedError: "",
|
||||||
|
isSubscription: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "subscription name too long",
|
||||||
|
method: string(make([]byte, maxMethodNameLength+1)) + "_subscribe",
|
||||||
|
params: []interface{}{"newHeads"},
|
||||||
|
expectedError: "subscription name too long",
|
||||||
|
isSubscription: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var result interface{}
|
||||||
|
err := client.Call(&result, tt.method, tt.params...)
|
||||||
|
if tt.expectedError == "" {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error, got nil")
|
||||||
|
} else if !strings.Contains(err.Error(), tt.expectedError) {
|
||||||
|
t.Errorf("expected error containing %q, got %q", tt.expectedError, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ type hasher struct {
|
||||||
|
|
||||||
// hasherPool holds pureHashers
|
// hasherPool holds pureHashers
|
||||||
var hasherPool = sync.Pool{
|
var hasherPool = sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() any {
|
||||||
return &hasher{
|
return &hasher{
|
||||||
tmp: make([]byte, 0, 550), // cap is as large as a full fullNode.
|
tmp: make([]byte, 0, 550), // cap is as large as a full fullNode.
|
||||||
sha: crypto.NewKeccakState(),
|
sha: crypto.NewKeccakState(),
|
||||||
|
|
|
||||||
24
trie/sync.go
24
trie/sync.go
|
|
@ -729,9 +729,7 @@ func (s *Sync) hasNode(owner common.Hash, path []byte, hash common.Hash) (exists
|
||||||
} else {
|
} else {
|
||||||
blob = rawdb.ReadStorageTrieNode(s.database, owner, path)
|
blob = rawdb.ReadStorageTrieNode(s.database, owner, path)
|
||||||
}
|
}
|
||||||
h := newBlobHasher()
|
exists = hash == crypto.Keccak256Hash(blob)
|
||||||
defer h.release()
|
|
||||||
exists = hash == h.hash(blob)
|
|
||||||
inconsistent = !exists && len(blob) != 0
|
inconsistent = !exists && len(blob) != 0
|
||||||
return exists, inconsistent
|
return exists, inconsistent
|
||||||
}
|
}
|
||||||
|
|
@ -746,23 +744,3 @@ func ResolvePath(path []byte) (common.Hash, []byte) {
|
||||||
}
|
}
|
||||||
return owner, path
|
return owner, path
|
||||||
}
|
}
|
||||||
|
|
||||||
// blobHasher is used to compute the sha256 hash of the provided data.
|
|
||||||
type blobHasher struct{ state crypto.KeccakState }
|
|
||||||
|
|
||||||
// blobHasherPool is the pool for reusing pre-allocated hash state.
|
|
||||||
var blobHasherPool = sync.Pool{
|
|
||||||
New: func() interface{} { return &blobHasher{state: crypto.NewKeccakState()} },
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBlobHasher() *blobHasher {
|
|
||||||
return blobHasherPool.Get().(*blobHasher)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *blobHasher) hash(data []byte) common.Hash {
|
|
||||||
return crypto.HashData(h.state, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *blobHasher) release() {
|
|
||||||
blobHasherPool.Put(h)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -830,6 +830,7 @@ func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBat
|
||||||
func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} }
|
func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} }
|
||||||
func (s *spongeDb) Stat() (string, error) { panic("implement me") }
|
func (s *spongeDb) Stat() (string, error) { panic("implement me") }
|
||||||
func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
|
func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
|
||||||
|
func (s *spongeDb) SyncKeyValue() error { return nil }
|
||||||
func (s *spongeDb) Close() error { return nil }
|
func (s *spongeDb) Close() error { return nil }
|
||||||
func (s *spongeDb) Put(key []byte, value []byte) error {
|
func (s *spongeDb) Put(key []byte, value []byte) error {
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -135,10 +135,13 @@ func (b *buffer) flush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, node
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
batch = db.NewBatchWithSize(b.nodes.dbsize() * 11 / 10) // extra 10% for potential pebble internal stuff
|
batch = db.NewBatchWithSize(b.nodes.dbsize() * 11 / 10) // extra 10% for potential pebble internal stuff
|
||||||
)
|
)
|
||||||
// Explicitly sync the state freezer, ensuring that all written
|
// Explicitly sync the state freezer to ensure all written data is persisted to disk
|
||||||
// data is transferred to disk before updating the key-value store.
|
// before updating the key-value store.
|
||||||
|
//
|
||||||
|
// This step is crucial to guarantee that the corresponding state history remains
|
||||||
|
// available for state rollback.
|
||||||
if freezer != nil {
|
if freezer != nil {
|
||||||
if err := freezer.Sync(); err != nil {
|
if err := freezer.SyncAncient(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -454,6 +454,15 @@ func (db *Database) Recover(root common.Hash) error {
|
||||||
db.tree.reset(dl)
|
db.tree.reset(dl)
|
||||||
}
|
}
|
||||||
rawdb.DeleteTrieJournal(db.diskdb)
|
rawdb.DeleteTrieJournal(db.diskdb)
|
||||||
|
|
||||||
|
// Explicitly sync the key-value store to ensure all recent writes are
|
||||||
|
// flushed to disk. This step is crucial to prevent a scenario where
|
||||||
|
// recent key-value writes are lost due to an application panic, while
|
||||||
|
// the associated state histories have already been removed, resulting
|
||||||
|
// in the inability to perform a state rollback.
|
||||||
|
if err := db.diskdb.SyncKeyValue(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
_, err := truncateFromHead(db.diskdb, db.freezer, dl.stateID())
|
_, err := truncateFromHead(db.diskdb, db.freezer, dl.stateID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -115,15 +115,12 @@ func (dl *diskLayer) node(owner common.Hash, path []byte, depth int) ([]byte, co
|
||||||
dirtyNodeMissMeter.Mark(1)
|
dirtyNodeMissMeter.Mark(1)
|
||||||
|
|
||||||
// Try to retrieve the trie node from the clean memory cache
|
// Try to retrieve the trie node from the clean memory cache
|
||||||
h := newHasher()
|
|
||||||
defer h.release()
|
|
||||||
|
|
||||||
key := nodeCacheKey(owner, path)
|
key := nodeCacheKey(owner, path)
|
||||||
if dl.nodes != nil {
|
if dl.nodes != nil {
|
||||||
if blob := dl.nodes.Get(nil, key); len(blob) > 0 {
|
if blob := dl.nodes.Get(nil, key); len(blob) > 0 {
|
||||||
cleanNodeHitMeter.Mark(1)
|
cleanNodeHitMeter.Mark(1)
|
||||||
cleanNodeReadMeter.Mark(int64(len(blob)))
|
cleanNodeReadMeter.Mark(int64(len(blob)))
|
||||||
return blob, h.hash(blob), &nodeLoc{loc: locCleanCache, depth: depth}, nil
|
return blob, crypto.Keccak256Hash(blob), &nodeLoc{loc: locCleanCache, depth: depth}, nil
|
||||||
}
|
}
|
||||||
cleanNodeMissMeter.Mark(1)
|
cleanNodeMissMeter.Mark(1)
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +135,7 @@ func (dl *diskLayer) node(owner common.Hash, path []byte, depth int) ([]byte, co
|
||||||
dl.nodes.Set(key, blob)
|
dl.nodes.Set(key, blob)
|
||||||
cleanNodeWriteMeter.Mark(int64(len(blob)))
|
cleanNodeWriteMeter.Mark(int64(len(blob)))
|
||||||
}
|
}
|
||||||
return blob, h.hash(blob), &nodeLoc{loc: locDiskLayer, depth: depth}, nil
|
return blob, crypto.Keccak256Hash(blob), &nodeLoc{loc: locDiskLayer, depth: depth}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// account directly retrieves the account RLP associated with a particular
|
// account directly retrieves the account RLP associated with a particular
|
||||||
|
|
@ -231,6 +228,8 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
|
||||||
oldest uint64
|
oldest uint64
|
||||||
)
|
)
|
||||||
if dl.db.freezer != nil {
|
if dl.db.freezer != nil {
|
||||||
|
// Bail out with an error if writing the state history fails.
|
||||||
|
// This can happen, for example, if the device is full.
|
||||||
err := writeHistory(dl.db.freezer, bottom)
|
err := writeHistory(dl.db.freezer, bottom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -357,22 +356,3 @@ func (dl *diskLayer) resetCache() {
|
||||||
dl.nodes.Reset()
|
dl.nodes.Reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasher is used to compute the sha256 hash of the provided data.
|
|
||||||
type hasher struct{ sha crypto.KeccakState }
|
|
||||||
|
|
||||||
var hasherPool = sync.Pool{
|
|
||||||
New: func() interface{} { return &hasher{sha: crypto.NewKeccakState()} },
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHasher() *hasher {
|
|
||||||
return hasherPool.Get().(*hasher)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *hasher) hash(data []byte) common.Hash {
|
|
||||||
return crypto.HashData(h.sha, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *hasher) release() {
|
|
||||||
hasherPool.Put(h)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
|
|
||||||
"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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
|
|
@ -85,10 +86,9 @@ func apply(db database.NodeDatabase, prevRoot common.Hash, postRoot common.Hash,
|
||||||
func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) error {
|
func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) error {
|
||||||
// The account was present in prev-state, decode it from the
|
// The account was present in prev-state, decode it from the
|
||||||
// 'slim-rlp' format bytes.
|
// 'slim-rlp' format bytes.
|
||||||
h := newHasher()
|
h := crypto.NewKeccakState()
|
||||||
defer h.release()
|
|
||||||
|
|
||||||
addrHash := h.hash(addr.Bytes())
|
addrHash := crypto.HashData(h, addr.Bytes())
|
||||||
prev, err := types.FullAccount(ctx.accounts[addr])
|
prev, err := types.FullAccount(ctx.accounts[addr])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -113,7 +113,7 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address)
|
||||||
for key, val := range ctx.storages[addr] {
|
for key, val := range ctx.storages[addr] {
|
||||||
tkey := key
|
tkey := key
|
||||||
if ctx.rawStorageKey {
|
if ctx.rawStorageKey {
|
||||||
tkey = h.hash(key.Bytes())
|
tkey = crypto.HashData(h, key.Bytes())
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
if len(val) == 0 {
|
if len(val) == 0 {
|
||||||
|
|
@ -149,10 +149,9 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address)
|
||||||
// account and storage is wiped out correctly.
|
// account and storage is wiped out correctly.
|
||||||
func deleteAccount(ctx *context, db database.NodeDatabase, addr common.Address) error {
|
func deleteAccount(ctx *context, db database.NodeDatabase, addr common.Address) error {
|
||||||
// The account must be existent in post-state, load the account.
|
// The account must be existent in post-state, load the account.
|
||||||
h := newHasher()
|
h := crypto.NewKeccakState()
|
||||||
defer h.release()
|
|
||||||
|
|
||||||
addrHash := h.hash(addr.Bytes())
|
addrHash := crypto.HashData(h, addr.Bytes())
|
||||||
blob, err := ctx.accountTrie.Get(addrHash.Bytes())
|
blob, err := ctx.accountTrie.Get(addrHash.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -174,7 +173,7 @@ func deleteAccount(ctx *context, db database.NodeDatabase, addr common.Address)
|
||||||
}
|
}
|
||||||
tkey := key
|
tkey := key
|
||||||
if ctx.rawStorageKey {
|
if ctx.rawStorageKey {
|
||||||
tkey = h.hash(key.Bytes())
|
tkey = crypto.HashData(h, key.Bytes())
|
||||||
}
|
}
|
||||||
if err := st.Delete(tkey.Bytes()); err != nil {
|
if err := st.Delete(tkey.Bytes()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -542,8 +542,9 @@ func writeHistory(writer ethdb.AncientWriter, dl *diffLayer) error {
|
||||||
indexSize := common.StorageSize(len(accountIndex) + len(storageIndex))
|
indexSize := common.StorageSize(len(accountIndex) + len(storageIndex))
|
||||||
|
|
||||||
// Write history data into five freezer table respectively.
|
// Write history data into five freezer table respectively.
|
||||||
rawdb.WriteStateHistory(writer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData)
|
if err := rawdb.WriteStateHistory(writer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
historyDataBytesMeter.Mark(int64(dataSize))
|
historyDataBytesMeter.Mark(int64(dataSize))
|
||||||
historyIndexBytesMeter.Mark(int64(indexSize))
|
historyIndexBytesMeter.Mark(int64(indexSize))
|
||||||
historyBuildTimeMeter.UpdateSince(start)
|
historyBuildTimeMeter.UpdateSince(start)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ var (
|
||||||
nodeDiskFalseMeter = metrics.NewRegisteredMeter("pathdb/disk/false", nil)
|
nodeDiskFalseMeter = metrics.NewRegisteredMeter("pathdb/disk/false", nil)
|
||||||
nodeDiffFalseMeter = metrics.NewRegisteredMeter("pathdb/diff/false", nil)
|
nodeDiffFalseMeter = metrics.NewRegisteredMeter("pathdb/diff/false", nil)
|
||||||
|
|
||||||
commitTimeTimer = metrics.NewRegisteredTimer("pathdb/commit/time", nil)
|
commitTimeTimer = metrics.NewRegisteredResettingTimer("pathdb/commit/time", nil)
|
||||||
commitNodesMeter = metrics.NewRegisteredMeter("pathdb/commit/nodes", nil)
|
commitNodesMeter = metrics.NewRegisteredMeter("pathdb/commit/nodes", nil)
|
||||||
commitBytesMeter = metrics.NewRegisteredMeter("pathdb/commit/bytes", nil)
|
commitBytesMeter = metrics.NewRegisteredMeter("pathdb/commit/bytes", nil)
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ var (
|
||||||
gcStorageMeter = metrics.NewRegisteredMeter("pathdb/gc/storage/count", nil)
|
gcStorageMeter = metrics.NewRegisteredMeter("pathdb/gc/storage/count", nil)
|
||||||
gcStorageBytesMeter = metrics.NewRegisteredMeter("pathdb/gc/storage/bytes", nil)
|
gcStorageBytesMeter = metrics.NewRegisteredMeter("pathdb/gc/storage/bytes", nil)
|
||||||
|
|
||||||
historyBuildTimeMeter = metrics.NewRegisteredTimer("pathdb/history/time", nil)
|
historyBuildTimeMeter = metrics.NewRegisteredResettingTimer("pathdb/history/time", nil)
|
||||||
historyDataBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/data", nil)
|
historyDataBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/data", nil)
|
||||||
historyIndexBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/index", nil)
|
historyIndexBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/index", nil)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
78
triedb/preimages_test.go
Normal file
78
triedb/preimages_test.go
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright 2023 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package triedb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestDatabasePreimages tests the preimage functionality of the trie database.
|
||||||
|
func TestDatabasePreimages(t *testing.T) {
|
||||||
|
// Create a database with preimages enabled
|
||||||
|
memDB := rawdb.NewMemoryDatabase()
|
||||||
|
config := &Config{
|
||||||
|
Preimages: true,
|
||||||
|
HashDB: hashdb.Defaults,
|
||||||
|
}
|
||||||
|
db := NewDatabase(memDB, config)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
// Test inserting and retrieving preimages
|
||||||
|
preimages := make(map[common.Hash][]byte)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
data := []byte{byte(i), byte(i + 1), byte(i + 2)}
|
||||||
|
hash := common.BytesToHash(data)
|
||||||
|
preimages[hash] = data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert preimages into the database
|
||||||
|
db.InsertPreimage(preimages)
|
||||||
|
|
||||||
|
// Verify all preimages are retrievable
|
||||||
|
for hash, data := range preimages {
|
||||||
|
retrieved := db.Preimage(hash)
|
||||||
|
if retrieved == nil {
|
||||||
|
t.Errorf("Preimage for %x not found", hash)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(retrieved, data) {
|
||||||
|
t.Errorf("Preimage data mismatch: got %x want %x", retrieved, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test non-existent preimage
|
||||||
|
nonExistentHash := common.HexToHash("deadbeef")
|
||||||
|
if data := db.Preimage(nonExistentHash); data != nil {
|
||||||
|
t.Errorf("Unexpected preimage data for non-existent hash: %x", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force preimage commit and verify again
|
||||||
|
db.WritePreimages()
|
||||||
|
for hash, data := range preimages {
|
||||||
|
retrieved := db.Preimage(hash)
|
||||||
|
if retrieved == nil {
|
||||||
|
t.Errorf("Preimage for %x not found after forced commit", hash)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(retrieved, data) {
|
||||||
|
t.Errorf("Preimage data mismatch after forced commit: got %x want %x", retrieved, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,6 @@ package version
|
||||||
const (
|
const (
|
||||||
Major = 1 // Major version component of the current release
|
Major = 1 // Major version component of the current release
|
||||||
Minor = 15 // Minor version component of the current release
|
Minor = 15 // Minor version component of the current release
|
||||||
Patch = 11 // Patch version component of the current release
|
Patch = 12 // Patch version component of the current release
|
||||||
Meta = "unstable" // Version metadata to append to the version string
|
Meta = "unstable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue