Skip to content

Commit

Permalink
Merge qa to master (#750)
Browse files Browse the repository at this point in the history
* Added checks to RPC requests and introduced new flags to customise the parameters (#657)

* added a check to reject rpc requests with batch size > the one set using a newly added flag (rpcbatchlimit)

* added a check to reject rpc requests whose result size > the one set using a newly added flag (rpcreturndatalimit)

* updated the config files and docs

* chg : trieTimeout from 60 to 10 mins (#692)

* chg : trieTimeout from 60 to 10 mins

* chg : cache.timout to 10m from 1h in configs

* internal/cli/server : fix : added triesInMemory in config (#691)

* changed version from 0.3.0 to 0.3.4-beta (#693)

* fix nil state-sync issue, increase grpc limit (#695)

* Increase grpc message size limit in pprof

* consensus/bor/bor.go : stateSyncs init fixed [Fix #686]

* eth/filters: handle nil state-sync before notify

* eth/filters: update check

Co-authored-by: Jerry <jerrycgh@gmail.com>
Co-authored-by: Daniil <daniil.melnik@chainstack.com>

* core, tests/bor: add more tests for state-sync validation (#710)

* core: add get state sync function for tests

* tests/bor: add validation for state sync events post consensus

* Arpit/temp bor sync (#701)

* Increase grpc message size limit in pprof

* ReadBorReceipts improvements

* use internal function

* fix tests

* fetch geth upstread for ReadBorReceiptRLP

* Only query bor receipt when the query index is equal to # tx in block body

This change reduces the frequency of calling ReadBorReceipt and
ReadBorTransaction, which are CPU and db intensive.

* Revert "fetch geth upstread for ReadBorReceiptRLP"

This reverts commit 2e838a6.

* Restore ReadBorReceiptRLP

* fix bor receipts

* remove unused

* fix lints

---------

Co-authored-by: Jerry <jerrycgh@gmail.com>
Co-authored-by: Manav Darji <manavdarji.india@gmail.com>
Co-authored-by: Evgeny Danienko <6655321@bk.ru>

* Revert "chg : trieTimeout from 60 to 10 mins (#692)" (#720)

This reverts commit 241843c.

* Arpit/add execution pool 2 (#719)

* initial

* linters

* linters

* remove timeout

* update pool

* change pool size function

* check nil

* check nil

* fix tests

* Use execution pool from server in all handlers

* simplify things

* test fix

* add support for cli, config

* add to cli and config

* merge base branch

* debug statements

* fix bug

* atomic pointer timeout

* add apis

* update workerpool

* fix issues

* change params

* fix issues

* fix ipc issue

* remove execution pool from IPC

* revert

* fix tests

* mutex

* refactor flag and value names

* ordering fix

* refactor flag and value names

* update default ep size to 40

* fix bor start issues

* revert file changes

* debug statements

* fix bug

* update workerpool

* atomic pointer timeout

* add apis

* Merge branch 'add-execution-pool' of github.com:maticnetwork/bor into arpit/add-execution-pool

* fix issues

* change params

* fix issues

* fix ipc issue

* remove execution pool from IPC

* revert

* merge base branch

* Merge branch 'add-execution-pool' of github.com:maticnetwork/bor into arpit/add-execution-pool

* mutex

* fix tests

* Merge branch 'arpit/add-execution-pool' of github.com:maticnetwork/bor into arpit/add-execution-pool

* Change default size of execution pool to 40

* refactor flag and value names

* fix merge conflicts

* ordering fix

* refactor flag and value names

* update default ep size to 40

* fix bor start issues

* revert file changes

* fix linters

* fix go.mod

* change sec to ms

* change default value for ep timeout

* fix node api calls

* comment setter for ep timeout

---------

Co-authored-by: Evgeny Danienko <6655321@bk.ru>
Co-authored-by: Jerry <jerrycgh@gmail.com>
Co-authored-by: Manav Darji <manavdarji.india@gmail.com>

* version change (#721)

* Event based pprof (#732)

* feature

* Save pprof to /tmp

---------

Co-authored-by: Jerry <jerrycgh@gmail.com>

* Cherry-pick changes from develop (#738)

* Check if block is nil to prevent panic (#736)

* miner: use env for tracing instead of block object (#728)

---------

Co-authored-by: Dmitry <46797839+dkeysil@users.noreply.github.com>

* add max code init size check in txpool (#739)

* Revert "Event based pprof" and update version (#742)

* Revert "Event based pprof (#732)"

This reverts commit 22fa403.

* params: update version to 0.3.4-beta3

* packaging/templates: update bor version

* params, packaging/templates: update bor version

---------

Co-authored-by: SHIVAM SHARMA <shivam691999@gmail.com>
Co-authored-by: Pratik Patil <pratikspatil024@gmail.com>
Co-authored-by: Jerry <jerrycgh@gmail.com>
Co-authored-by: Daniil <daniil.melnik@chainstack.com>
Co-authored-by: Arpit Temani <temaniarpit27@gmail.com>
Co-authored-by: Evgeny Danienko <6655321@bk.ru>
Co-authored-by: Dmitry <46797839+dkeysil@users.noreply.github.com>
  • Loading branch information
8 people authored Feb 20, 2023
1 parent 56d3058 commit c3d2c26
Show file tree
Hide file tree
Showing 65 changed files with 671 additions and 154 deletions.
6 changes: 6 additions & 0 deletions builder/files/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ chain = "mainnet"
datadir = "/var/lib/bor/data"
# ancient = ""
# keystore = "/var/lib/bor/keystore"
# "rpc.batchlimit" = 100
# "rpc.returndatalimit" = 100000
syncmode = "full"
# gcmode = "full"
# snapshot = true
Expand Down Expand Up @@ -73,13 +75,17 @@ syncmode = "full"
# api = ["eth", "net", "web3", "txpool", "bor"]
# vhosts = ["*"]
# corsdomain = ["*"]
# ep-size = 40
# ep-requesttimeout = "0s"
# [jsonrpc.ws]
# enabled = false
# port = 8546
# prefix = ""
# host = "localhost"
# api = ["web3", "net"]
# origins = ["*"]
# ep-size = 40
# ep-requesttimeout = "0s"
# [jsonrpc.graphql]
# enabled = false
# port = 0
Expand Down
2 changes: 1 addition & 1 deletion cmd/clef/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ func signer(c *cli.Context) error {
vhosts := utils.SplitAndTrim(c.GlobalString(utils.HTTPVirtualHostsFlag.Name))
cors := utils.SplitAndTrim(c.GlobalString(utils.HTTPCORSDomainFlag.Name))

srv := rpc.NewServer()
srv := rpc.NewServer(0, 0)
err := node.RegisterApis(rpcAPI, []string{"account"}, srv, false)
if err != nil {
utils.Fatalf("Could not register API: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion consensus/bor/bor.go
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,7 @@ func (c *Bor) CommitStates(
processStart := time.Now()
totalGas := 0 /// limit on gas for state sync per block
chainID := c.chainConfig.ChainID.String()
stateSyncs := make([]*types.StateSyncData, len(eventRecords))
stateSyncs := make([]*types.StateSyncData, 0, len(eventRecords))

var gasUsed uint64

Expand Down
2 changes: 1 addition & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2059,7 +2059,7 @@ func (bc *BlockChain) collectLogs(hash common.Hash, removed bool) []*types.Log {
receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig)

// Append bor receipt
borReceipt := rawdb.ReadBorReceipt(bc.db, hash, *number)
borReceipt := rawdb.ReadBorReceipt(bc.db, hash, *number, bc.chainConfig)
if borReceipt != nil {
receipts = append(receipts, borReceipt)
}
Expand Down
4 changes: 4 additions & 0 deletions core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ func (bc *BlockChain) SetStateSync(stateData []*types.StateSyncData) {
bc.stateSyncData = stateData
}

func (bc *BlockChain) GetStateSync() []*types.StateSyncData {
return bc.stateSyncData
}

// SubscribeStateSyncEvent registers a subscription of StateSyncEvent.
func (bc *BlockChain) SubscribeStateSyncEvent(ch chan<- StateSyncEvent) event.Subscription {
return bc.scope.Track(bc.stateSyncFeed.Subscribe(ch))
Expand Down
2 changes: 1 addition & 1 deletion core/bor_blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func (bc *BlockChain) GetBorReceiptByHash(hash common.Hash) *types.Receipt {
}

// read bor reciept by hash and number
receipt := rawdb.ReadBorReceipt(bc.db, hash, *number)
receipt := rawdb.ReadBorReceipt(bc.db, hash, *number, bc.chainConfig)
if receipt == nil {
return nil
}
Expand Down
4 changes: 4 additions & 0 deletions core/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ var (
// have enough funds for transfer(topmost call only).
ErrInsufficientFundsForTransfer = errors.New("insufficient funds for transfer")

// ErrMaxInitCodeSizeExceeded is returned if creation transaction provides the init code bigger
// than init code size limit.
ErrMaxInitCodeSizeExceeded = errors.New("max initcode size exceeded")

// ErrInsufficientFunds is returned if the total cost of executing a transaction
// is higher than the balance of the user's account.
ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value")
Expand Down
64 changes: 24 additions & 40 deletions core/rawdb/bor_receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)

Expand All @@ -33,49 +34,28 @@ func borTxLookupKey(hash common.Hash) []byte {
return append(borTxLookupPrefix, hash.Bytes()...)
}

// HasBorReceipt verifies the existence of all block receipt belonging
// to a block.
func HasBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) bool {
if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash {
return true
}

if has, err := db.Has(borReceiptKey(number, hash)); !has || err != nil {
return false
}
func ReadBorReceiptRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte

return true
}
err := db.ReadAncients(func(reader ethdb.AncientReader) error {
// Check if the data is in ancients
if isCanon(reader, number, hash) {
data, _ = reader.Ancient(freezerBorReceiptTable, number)

// ReadBorReceiptRLP retrieves the block receipt belonging to a block in RLP encoding.
func ReadBorReceiptRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
// First try to look up the data in ancient database. Extra hash
// comparison is necessary since ancient database only maintains
// the canonical data.
data, _ := db.Ancient(freezerBorReceiptTable, number)
if len(data) > 0 {
h, _ := db.Ancient(freezerHashTable, number)
if common.BytesToHash(h) == hash {
return data
}
}
// Then try to look up the data in leveldb.
data, _ = db.Get(borReceiptKey(number, hash))
if len(data) > 0 {
return data
}
// In the background freezer is moving data from leveldb to flatten files.
// So during the first check for ancient db, the data is not yet in there,
// but when we reach into leveldb, the data was already moved. That would
// result in a not found error.
data, _ = db.Ancient(freezerBorReceiptTable, number)
if len(data) > 0 {
h, _ := db.Ancient(freezerHashTable, number)
if common.BytesToHash(h) == hash {
return data
return nil
}

// If not, try reading from leveldb
data, _ = db.Get(borReceiptKey(number, hash))

return nil
})

if err != nil {
log.Warn("during ReadBorReceiptRLP", "number", number, "hash", hash, "err", err)
}
return nil // Can't find the data anywhere.

return data
}

// ReadRawBorReceipt retrieves the block receipt belonging to a block.
Expand All @@ -101,7 +81,11 @@ func ReadRawBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.
// ReadBorReceipt retrieves all the bor block receipts belonging to a block, including
// its correspoinding metadata fields. If it is unable to populate these metadata
// fields then nil is returned.
func ReadBorReceipt(db ethdb.Reader, hash common.Hash, number uint64) *types.Receipt {
func ReadBorReceipt(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) *types.Receipt {
if config != nil && config.Bor != nil && config.Bor.Sprint != nil && !config.Bor.IsSprintStart(number) {
return nil
}

// We're deriving many fields from the block body, retrieve beside the receipt
borReceipt := ReadRawBorReceipt(db, hash, number)
if borReceipt == nil {
Expand Down
6 changes: 6 additions & 0 deletions core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package core

import (
"errors"
"fmt"
"math"
"math/big"
"sort"
Expand Down Expand Up @@ -604,6 +605,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if uint64(tx.Size()) > txMaxSize {
return ErrOversizedData
}
// Check whether the init code size has been exceeded.
// (TODO): Add a hardfork check here while pulling upstream changes.
if tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize {
return fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize)
}
// Transactions can't be negative. This may never happen using RLP decoded
// transactions but may occur if you create a transaction using the RPC.
if tx.Value().Sign() < 0 {
Expand Down
25 changes: 16 additions & 9 deletions docs/cli/example_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ log-level = "INFO" # Set log level for the server
datadir = "var/lib/bor" # Path of the data directory to store information
ancient = "" # Data directory for ancient chain segments (default = inside chaindata)
keystore = "" # Path of the directory where keystores are located
"rpc.batchlimit" = 100 # Maximum number of messages in a batch (default=100, use 0 for no limits)
"rpc.returndatalimit" = 100000 # Maximum size (in bytes) a result of an rpc request could have (default=100000, use 0 for no limits)
syncmode = "full" # Blockchain sync mode (only "full" sync supported)
gcmode = "full" # Blockchain garbage collection mode ("full", "archive")
snapshot = true # Enables the snapshot-database mode
Expand Down Expand Up @@ -72,25 +74,30 @@ ethstats = "" # Reporting URL of a ethstats service (nodename:sec
api = ["eth", "net", "web3", "txpool", "bor"] # API's offered over the HTTP-RPC interface
vhosts = ["localhost"] # Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
corsdomain = ["localhost"] # Comma separated list of domains from which to accept cross origin requests (browser enforced)
ep-size = 40 # Maximum size of workers to run in rpc execution pool for HTTP requests (default: 40)
ep-requesttimeout = "0s" # Request Timeout for rpc execution pool for HTTP requests (default: 0s, 0s = disabled)
[jsonrpc.ws]
enabled = false # Enable the WS-RPC server
port = 8546 # WS-RPC server listening port
prefix = "" # HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
host = "localhost" # ws.addr
api = ["net", "web3"] # API's offered over the WS-RPC interface
origins = ["localhost"] # Origins from which to accept websockets requests
enabled = false # Enable the WS-RPC server
port = 8546 # WS-RPC server listening port
prefix = "" # HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
host = "localhost" # ws.addr
api = ["net", "web3"] # API's offered over the WS-RPC interface
origins = ["localhost"] # Origins from which to accept websockets requests
ep-size = 40 # Maximum size of workers to run in rpc execution pool for WS requests (default: 40)
ep-requesttimeout = "0s" # Request Timeout for rpc execution pool for WS requests (default: 0s, 0s = disabled)
[jsonrpc.graphql]
enabled = false # Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.
port = 0 #
prefix = "" #
host = "" #
port = 0 #
prefix = "" #
host = "" #
vhosts = ["localhost"] # Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
corsdomain = ["localhost"] # Comma separated list of domains from which to accept cross origin requests (browser enforced)
[jsonrpc.timeouts]
read = "30s"
write = "30s"
idle = "2m0s"


[gpo]
blocks = 20 # Number of recent blocks to check for gas prices
percentile = 60 # Suggested gas price is the given percentile of a set of recent transaction gas prices
Expand Down
12 changes: 12 additions & 0 deletions docs/cli/server.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ The ```bor server``` command runs the Bor client.

- ```keystore```: Path of the directory where keystores are located

- ```rpc.batchlimit```: Maximum number of messages in a batch (default=100, use 0 for no limits) (default: 100)

- ```rpc.returndatalimit```: Maximum size (in bytes) a result of an rpc request could have (default=100000, use 0 for no limits) (default: 100000)

- ```config```: File for the config file

- ```syncmode```: Blockchain sync mode (only "full" sync supported) (default: full)
Expand Down Expand Up @@ -116,6 +120,10 @@ The ```bor server``` command runs the Bor client.

- ```http.api```: API's offered over the HTTP-RPC interface (default: eth,net,web3,txpool,bor)

- ```http.ep-size```: Maximum size of workers to run in rpc execution pool for HTTP requests (default: 40)

- ```http.ep-requesttimeout```: Request Timeout for rpc execution pool for HTTP requests (default: 0s)

- ```ws```: Enable the WS-RPC server (default: false)

- ```ws.addr```: WS-RPC server listening interface (default: localhost)
Expand All @@ -126,6 +134,10 @@ The ```bor server``` command runs the Bor client.

- ```ws.api```: API's offered over the WS-RPC interface (default: net,web3)

- ```ws.ep-size```: Maximum size of workers to run in rpc execution pool for WS requests (default: 40)

- ```ws.ep-requesttimeout```: Request Timeout for rpc execution pool for WS requests (default: 0s)

- ```graphql```: Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well. (default: false)

### P2P Options
Expand Down
4 changes: 4 additions & 0 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ func (b *EthAPIBackend) RPCGasCap() uint64 {
return b.eth.config.RPCGasCap
}

func (b *EthAPIBackend) RPCRpcReturnDataLimit() uint64 {
return b.eth.config.RPCReturnDataLimit
}

func (b *EthAPIBackend) RPCEVMTimeout() time.Duration {
return b.eth.config.RPCEVMTimeout
}
Expand Down
14 changes: 9 additions & 5 deletions eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,12 @@ var Defaults = Config{
GasPrice: big.NewInt(params.GWei),
Recommit: 125 * time.Second,
},
TxPool: core.DefaultTxPoolConfig,
RPCGasCap: 50000000,
RPCEVMTimeout: 5 * time.Second,
GPO: FullNodeGPO,
RPCTxFeeCap: 5, // 5 matic
TxPool: core.DefaultTxPoolConfig,
RPCGasCap: 50000000,
RPCReturnDataLimit: 100000,
RPCEVMTimeout: 5 * time.Second,
GPO: FullNodeGPO,
RPCTxFeeCap: 5, // 5 matic
}

func init() {
Expand Down Expand Up @@ -199,6 +200,9 @@ type Config struct {
// RPCGasCap is the global gas cap for eth-call variants.
RPCGasCap uint64

// Maximum size (in bytes) a result of an rpc request could have
RPCReturnDataLimit uint64

// RPCEVMTimeout is the global timeout for eth-call.
RPCEVMTimeout time.Duration

Expand Down
7 changes: 3 additions & 4 deletions eth/filters/bor_api.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package filters

import (
"bytes"
"context"
"errors"

Expand All @@ -19,7 +18,7 @@ func (api *PublicFilterAPI) SetChainConfig(chainConfig *params.ChainConfig) {

func (api *PublicFilterAPI) GetBorBlockLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
if api.chainConfig == nil {
return nil, errors.New("No chain config found. Proper PublicFilterAPI initialization required")
return nil, errors.New("no chain config found. Proper PublicFilterAPI initialization required")
}

// get sprint from bor config
Expand Down Expand Up @@ -67,8 +66,8 @@ func (api *PublicFilterAPI) NewDeposits(ctx context.Context, crit ethereum.State
for {
select {
case h := <-stateSyncData:
if crit.ID == h.ID || bytes.Compare(crit.Contract.Bytes(), h.Contract.Bytes()) == 0 ||
(crit.ID == 0 && crit.Contract == common.Address{}) {
if h != nil && (crit.ID == h.ID || crit.Contract == h.Contract ||
(crit.ID == 0 && crit.Contract == common.Address{})) {
notifier.Notify(rpcSub.ID, h)
}
case <-rpcSub.Err():
Expand Down
2 changes: 1 addition & 1 deletion eth/filters/test_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (b *TestBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash)
return &types.Receipt{}, nil
}

receipt := rawdb.ReadBorReceipt(b.DB, hash, *number)
receipt := rawdb.ReadBorReceipt(b.DB, hash, *number, nil)
if receipt == nil {
return &types.Receipt{}, nil
}
Expand Down
2 changes: 1 addition & 1 deletion eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func (api *API) getAllBlockTransactions(ctx context.Context, block *types.Block)

stateSyncPresent := false

borReceipt := rawdb.ReadBorReceipt(api.backend.ChainDb(), block.Hash(), block.NumberU64())
borReceipt := rawdb.ReadBorReceipt(api.backend.ChainDb(), block.Hash(), block.NumberU64(), api.backend.ChainConfig())
if borReceipt != nil {
txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash()))
if txHash != (common.Hash{}) {
Expand Down
4 changes: 4 additions & 0 deletions eth/tracers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ func (b *testBackend) RPCGasCap() uint64 {
return 25000000
}

func (b *testBackend) RPCRpcReturnDataLimit() uint64 {
return 100000
}

func (b *testBackend) ChainConfig() *params.ChainConfig {
return b.chainConfig
}
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0
github.com/BurntSushi/toml v1.1.0
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d
github.com/JekaMas/workerpool v1.1.5
github.com/VictoriaMetrics/fastcache v1.6.0
github.com/aws/aws-sdk-go-v2 v1.2.0
github.com/aws/aws-sdk-go-v2/config v1.1.1
Expand Down Expand Up @@ -84,6 +85,8 @@ require (
pgregory.net/rapid v0.4.8
)

require github.com/gammazero/deque v0.2.1 // indirect

require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect
Expand Down
Loading

0 comments on commit c3d2c26

Please sign in to comment.