mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
merge develop
This commit is contained in:
commit
986486bb37
107 changed files with 5887 additions and 688 deletions
4
.github/workflows/packager.yml
vendored
4
.github/workflows/packager.yml
vendored
|
|
@ -12,9 +12,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on:
|
runs-on: ubuntu-20.04
|
||||||
group: ubuntu-runners
|
|
||||||
labels: 18.04RunnerT2Large
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
|
||||||
1
.github/workflows/stale.yml
vendored
1
.github/workflows/stale.yml
vendored
|
|
@ -29,3 +29,4 @@ jobs:
|
||||||
days-before-pr-stale: 21
|
days-before-pr-stale: 21
|
||||||
days-before-issue-close: 14
|
days-before-issue-close: 14
|
||||||
days-before-pr-close: 14
|
days-before-pr-close: 14
|
||||||
|
exempt-draft-pr: true
|
||||||
|
|
|
||||||
|
|
@ -103,11 +103,6 @@ nfpms:
|
||||||
scripts:
|
scripts:
|
||||||
postinstall: builder/files/bor-post-install.sh
|
postinstall: builder/files/bor-post-install.sh
|
||||||
|
|
||||||
overrides:
|
|
||||||
rpm:
|
|
||||||
replacements:
|
|
||||||
amd64: x86_64
|
|
||||||
|
|
||||||
snapshot:
|
snapshot:
|
||||||
name_template: "{{ .Tag }}.next"
|
name_template: "{{ .Tag }}.next"
|
||||||
|
|
||||||
|
|
|
||||||
6
Makefile
6
Makefile
|
|
@ -58,7 +58,7 @@ ios:
|
||||||
@echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
|
@echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
|
||||||
|
|
||||||
test:
|
test:
|
||||||
$(GOTEST) --timeout 5m -shuffle=on -cover -short -coverprofile=cover.out -covermode=atomic $(TESTALL)
|
$(GOTEST) --timeout 5m -cover -short -coverprofile=cover.out -covermode=atomic $(TESTALL)
|
||||||
|
|
||||||
test-txpool-race:
|
test-txpool-race:
|
||||||
$(GOTEST) -run=TestPoolMiningDataRaces --timeout 600m -race -v ./core/
|
$(GOTEST) -run=TestPoolMiningDataRaces --timeout 600m -race -v ./core/
|
||||||
|
|
@ -213,7 +213,7 @@ release-dry-run:
|
||||||
-v `pwd`:/go/src/$(PACKAGE_NAME) \
|
-v `pwd`:/go/src/$(PACKAGE_NAME) \
|
||||||
-w /go/src/$(PACKAGE_NAME) \
|
-w /go/src/$(PACKAGE_NAME) \
|
||||||
goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
|
goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
|
||||||
--rm-dist --skip-validate --skip-publish
|
--clean --skip-validate --skip-publish
|
||||||
|
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release:
|
release:
|
||||||
|
|
@ -230,4 +230,4 @@ release:
|
||||||
-v `pwd`:/go/src/$(PACKAGE_NAME) \
|
-v `pwd`:/go/src/$(PACKAGE_NAME) \
|
||||||
-w /go/src/$(PACKAGE_NAME) \
|
-w /go/src/$(PACKAGE_NAME) \
|
||||||
goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
|
goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
|
||||||
--rm-dist --skip-validate
|
--clean --skip-validate
|
||||||
|
|
|
||||||
29
RETESTBOR.md
29
RETESTBOR.md
|
|
@ -65,22 +65,21 @@ ls
|
||||||
```
|
```
|
||||||
./dretesteth.sh -t GeneralStateTests/stExample -- --testpath /home/ubuntu/retestethBuild/tests --datadir /tests/config
|
./dretesteth.sh -t GeneralStateTests/stExample -- --testpath /home/ubuntu/retestethBuild/tests --datadir /tests/config
|
||||||
```
|
```
|
||||||
This will create the config files for the different clients in ~/tests/config
|
This will create the config files for the different clients in `~/tests/config`
|
||||||
Eventually. these config needs to be adapted according to the following doc
|
Eventually, these configuration files need to be adapted according to the following document:
|
||||||
https://ethereum-tests.readthedocs.io/en/latest/retesteth-tutorial.html
|
|
||||||
Specifically:
|
|
||||||
```
|
|
||||||
f you look inside ~/tests/config, you’ll see a directory for each configured client. Typically this directory has these files:
|
|
||||||
|
|
||||||
config, which contains the configuration for the client:
|
https://ethereum-tests.readthedocs.io/en/latest/retesteth-tutorial.html
|
||||||
The communication protocol to use with the client (typically TCP)
|
|
||||||
The address(es) to use with that protocol
|
Specifically, if you look inside `~/tests/config`, you'll see a directory for each configured client. Typically this directory contains the following:
|
||||||
The forks the client supports
|
|
||||||
The exceptions the client can throw, and how retesteth should interpret them. This is particularly important when testing the client’s behavior when given invalid blocks.
|
* `config`: Contains the test configuration for the client
|
||||||
start.sh, which starts the client inside the docker image
|
* The communication protocol to use with the client (typically TCP).
|
||||||
stop.sh, which stops the client instance(s)
|
* The address(es) to use with that protocol.
|
||||||
genesis, a directory which includes the genesis blocks for various forks the client supports. If this directory does not exist for a client, it uses the genesis blocks for the default client.
|
* The forks supported by the client.
|
||||||
```
|
* The exceptions the client can throw, and how retesteth should interpret them. This is particularly important when testing the client's behavior when given invalid blocks.
|
||||||
|
* `start.sh`: Starts the client inside the Docker image
|
||||||
|
* `stop.sh`: Stops the client instance(s)
|
||||||
|
* `genesis`: A directory which includes the genesis blocks for the various forks supported by the cient. If this directory does not exist for a client, it uses the genesis blocks for the default client.
|
||||||
|
|
||||||
We replaced geth inside docker by using https://ethereum-tests.readthedocs.io/en/latest/retesteth-tutorial.html#replace-geth-inside-the-docker
|
We replaced geth inside docker by using https://ethereum-tests.readthedocs.io/en/latest/retesteth-tutorial.html#replace-geth-inside-the-docker
|
||||||
Theoretically, we would not need any additional config change
|
Theoretically, we would not need any additional config change
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@ func (fb *filterBackend) GetBorBlockReceipt(ctx context.Context, hash common.Has
|
||||||
return receipt, nil
|
return receipt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fb *filterBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (fb *filterBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
func (fb *filterBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
||||||
receipt, err := fb.GetBorBlockReceipt(ctx, hash)
|
receipt, err := fb.GetBorBlockReceipt(ctx, hash)
|
||||||
if err != nil || receipt == nil {
|
if err != nil || receipt == nil {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ chain = "mainnet"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = "/var/lib/bor/keystore"
|
# keystore = "/var/lib/bor/keystore"
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -2040,11 +2040,15 @@ func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconf
|
||||||
LogCacheSize: ethcfg.FilterLogCacheSize,
|
LogCacheSize: ethcfg.FilterLogCacheSize,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
filterAPI := filters.NewFilterAPI(filterSystem, isLightClient, ethconfig.Defaults.BorLogs)
|
||||||
stack.RegisterAPIs([]rpc.API{{
|
stack.RegisterAPIs([]rpc.API{{
|
||||||
Namespace: "eth",
|
Namespace: "eth",
|
||||||
Service: filters.NewFilterAPI(filterSystem, isLightClient, ethconfig.Defaults.BorLogs),
|
Service: filterAPI,
|
||||||
}})
|
}})
|
||||||
|
|
||||||
|
// avoiding constructor changed by introducing new method to set genesis
|
||||||
|
filterAPI.SetChainConfig(ethcfg.Genesis.Config)
|
||||||
|
|
||||||
return filterSystem
|
return filterSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
3
common/flags/milestone.go
Normal file
3
common/flags/milestone.go
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
const Milestone = true
|
||||||
5
common/gererics/empty.go
Normal file
5
common/gererics/empty.go
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
package gererics
|
||||||
|
|
||||||
|
func Empty[T any]() (t T) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
@ -341,6 +341,10 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
|
||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) GetVoteOnHash(starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) initializeRootHashCache() error {
|
func (api *API) initializeRootHashCache() error {
|
||||||
var err error
|
var err error
|
||||||
if api.rootHashCache == nil {
|
if api.rootHashCache == nil {
|
||||||
|
|
|
||||||
|
|
@ -1226,7 +1226,6 @@ func (c *Bor) CommitStates(
|
||||||
|
|
||||||
stateSyncDelay := c.config.CalculateStateSyncDelay(number)
|
stateSyncDelay := c.config.CalculateStateSyncDelay(number)
|
||||||
to = time.Unix(int64(header.Time-stateSyncDelay), 0)
|
to = time.Unix(int64(header.Time-stateSyncDelay), 0)
|
||||||
log.Debug("Post Indore", "lastStateIDBig", lastStateIDBig, "to", to, "stateSyncDelay", stateSyncDelay)
|
|
||||||
} else {
|
} else {
|
||||||
lastStateIDBig, err = c.GenesisContractsClient.LastStateId(nil, number-1, header.ParentHash)
|
lastStateIDBig, err = c.GenesisContractsClient.LastStateId(nil, number-1, header.ParentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1234,7 +1233,6 @@ func (c *Bor) CommitStates(
|
||||||
}
|
}
|
||||||
|
|
||||||
to = time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.CalculateSprint(number)).Time), 0)
|
to = time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.CalculateSprint(number)).Time), 0)
|
||||||
log.Debug("Pre Indore", "lastStateIDBig", lastStateIDBig, "to", to)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastStateID := lastStateIDBig.Uint64()
|
lastStateID := lastStateIDBig.Uint64()
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,13 @@ func (gc *GenesisContractsClient) CommitState(
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := statefull.GetSystemMessage(common.HexToAddress(gc.StateReceiverContract), data)
|
msg := statefull.GetSystemMessage(common.HexToAddress(gc.StateReceiverContract), data)
|
||||||
|
|
||||||
|
log.Info("→ committing new state", "eventRecord", event.ID)
|
||||||
|
|
||||||
gasUsed, err := statefull.ApplyMessage(context.Background(), msg, state, header, gc.chainConfig, chCtx)
|
gasUsed, err := statefull.ApplyMessage(context.Background(), msg, state, header, gc.chainConfig, chCtx)
|
||||||
|
|
||||||
// Logging event log with time and individual gasUsed
|
// Logging event log with time and individual gasUsed
|
||||||
log.Info("→ committing new state", "eventRecord", event.String(gasUsed))
|
log.Info("→ committed new state", "eventRecord", event.String(gasUsed))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/milestone"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -14,5 +15,10 @@ type IHeimdallClient interface {
|
||||||
Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error)
|
Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error)
|
||||||
FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error)
|
FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error)
|
||||||
FetchCheckpointCount(ctx context.Context) (int64, error)
|
FetchCheckpointCount(ctx context.Context) (int64, error)
|
||||||
|
FetchMilestone(ctx context.Context) (*milestone.Milestone, error)
|
||||||
|
FetchMilestoneCount(ctx context.Context) (int64, error)
|
||||||
|
FetchNoAckMilestone(ctx context.Context, milestoneID string) error //Fetch the bool value whether milestone corresponding to the given id failed in the Heimdall
|
||||||
|
FetchLastNoAckMilestone(ctx context.Context) (string, error) //Fetch latest failed milestone id
|
||||||
|
FetchMilestoneID(ctx context.Context, milestoneID string) error //Fetch the bool value whether milestone corresponding to the given id is in process in Heimdall
|
||||||
Close()
|
Close()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/milestone"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
|
@ -23,6 +24,8 @@ var (
|
||||||
ErrShutdownDetected = errors.New("shutdown detected")
|
ErrShutdownDetected = errors.New("shutdown detected")
|
||||||
ErrNoResponse = errors.New("got a nil response")
|
ErrNoResponse = errors.New("got a nil response")
|
||||||
ErrNotSuccessfulResponse = errors.New("error while fetching data from Heimdall")
|
ErrNotSuccessfulResponse = errors.New("error while fetching data from Heimdall")
|
||||||
|
ErrNotInRejectedList = errors.New("milestoneID doesn't exist in rejected list")
|
||||||
|
ErrNotInMilestoneList = errors.New("milestoneID doesn't exist in Heimdall")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -66,8 +69,16 @@ func NewHeimdallClient(urlString string) *HeimdallClient {
|
||||||
const (
|
const (
|
||||||
fetchStateSyncEventsFormat = "from-id=%d&to-time=%d&limit=%d"
|
fetchStateSyncEventsFormat = "from-id=%d&to-time=%d&limit=%d"
|
||||||
fetchStateSyncEventsPath = "clerk/event-record/list"
|
fetchStateSyncEventsPath = "clerk/event-record/list"
|
||||||
fetchCheckpoint = "/checkpoints/%s"
|
|
||||||
fetchCheckpointCount = "/checkpoints/count"
|
fetchCheckpoint = "/checkpoints/%s"
|
||||||
|
fetchCheckpointCount = "/checkpoints/count"
|
||||||
|
|
||||||
|
fetchMilestone = "/milestone/latest"
|
||||||
|
fetchMilestoneCount = "/milestone/count"
|
||||||
|
|
||||||
|
fetchLastNoAckMilestone = "/milestone/lastNoAck"
|
||||||
|
fetchNoAckMilestone = "/milestone/noAck/%s"
|
||||||
|
fetchMilestoneID = "/milestone/ID/%s"
|
||||||
|
|
||||||
fetchSpanFormat = "bor/span/%d"
|
fetchSpanFormat = "bor/span/%d"
|
||||||
)
|
)
|
||||||
|
|
@ -144,6 +155,23 @@ func (h *HeimdallClient) FetchCheckpoint(ctx context.Context, number int64) (*ch
|
||||||
return &response.Result, nil
|
return &response.Result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchMilestone fetches the checkpoint from heimdall
|
||||||
|
func (h *HeimdallClient) FetchMilestone(ctx context.Context) (*milestone.Milestone, error) {
|
||||||
|
url, err := milestoneURL(h.urlString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = withRequestType(ctx, milestoneRequest)
|
||||||
|
|
||||||
|
response, err := FetchWithRetry[milestone.MilestoneResponse](ctx, h.client, url, h.closeCh)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &response.Result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// FetchCheckpointCount fetches the checkpoint count from heimdall
|
// FetchCheckpointCount fetches the checkpoint count from heimdall
|
||||||
func (h *HeimdallClient) FetchCheckpointCount(ctx context.Context) (int64, error) {
|
func (h *HeimdallClient) FetchCheckpointCount(ctx context.Context) (int64, error) {
|
||||||
url, err := checkpointCountURL(h.urlString)
|
url, err := checkpointCountURL(h.urlString)
|
||||||
|
|
@ -161,6 +189,84 @@ func (h *HeimdallClient) FetchCheckpointCount(ctx context.Context) (int64, error
|
||||||
return response.Result.Result, nil
|
return response.Result.Result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchMilestoneCount fetches the milestone count from heimdall
|
||||||
|
func (h *HeimdallClient) FetchMilestoneCount(ctx context.Context) (int64, error) {
|
||||||
|
url, err := milestoneCountURL(h.urlString)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = withRequestType(ctx, milestoneCountRequest)
|
||||||
|
|
||||||
|
response, err := FetchWithRetry[milestone.MilestoneCountResponse](ctx, h.client, url, h.closeCh)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Result.Count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchLastNoAckMilestone fetches the last no-ack-milestone from heimdall
|
||||||
|
func (h *HeimdallClient) FetchLastNoAckMilestone(ctx context.Context) (string, error) {
|
||||||
|
url, err := lastNoAckMilestoneURL(h.urlString)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = withRequestType(ctx, milestoneLastNoAckRequest)
|
||||||
|
|
||||||
|
response, err := FetchWithRetry[milestone.MilestoneLastNoAckResponse](ctx, h.client, url, h.closeCh)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Result.Result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchNoAckMilestone fetches the last no-ack-milestone from heimdall
|
||||||
|
func (h *HeimdallClient) FetchNoAckMilestone(ctx context.Context, milestoneID string) error {
|
||||||
|
url, err := noAckMilestoneURL(h.urlString, milestoneID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = withRequestType(ctx, milestoneNoAckRequest)
|
||||||
|
|
||||||
|
response, err := FetchWithRetry[milestone.MilestoneNoAckResponse](ctx, h.client, url, h.closeCh)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !response.Result.Result {
|
||||||
|
return fmt.Errorf("%w: milestoneID %q", ErrNotInRejectedList, milestoneID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchMilestoneID fetches the bool result from Heimdal whether the ID corresponding
|
||||||
|
// to the given milestone is in process in Heimdall
|
||||||
|
func (h *HeimdallClient) FetchMilestoneID(ctx context.Context, milestoneID string) error {
|
||||||
|
url, err := milestoneIDURL(h.urlString, milestoneID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = withRequestType(ctx, milestoneIDRequest)
|
||||||
|
|
||||||
|
response, err := FetchWithRetry[milestone.MilestoneIDResponse](ctx, h.client, url, h.closeCh)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !response.Result.Result {
|
||||||
|
return fmt.Errorf("%w: milestoneID %q", ErrNotInMilestoneList, milestoneID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// FetchWithRetry returns data from heimdall with retry
|
// FetchWithRetry returns data from heimdall with retry
|
||||||
func FetchWithRetry[T any](ctx context.Context, client http.Client, url *url.URL, closeCh chan struct{}) (*T, error) {
|
func FetchWithRetry[T any](ctx context.Context, client http.Client, url *url.URL, closeCh chan struct{}) (*T, error) {
|
||||||
// request data once
|
// request data once
|
||||||
|
|
@ -266,10 +372,34 @@ func checkpointURL(urlString string, number int64) (*url.URL, error) {
|
||||||
return makeURL(urlString, url, "")
|
return makeURL(urlString, url, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func milestoneURL(urlString string) (*url.URL, error) {
|
||||||
|
url := fetchMilestone
|
||||||
|
|
||||||
|
return makeURL(urlString, url, "")
|
||||||
|
}
|
||||||
|
|
||||||
func checkpointCountURL(urlString string) (*url.URL, error) {
|
func checkpointCountURL(urlString string) (*url.URL, error) {
|
||||||
return makeURL(urlString, fetchCheckpointCount, "")
|
return makeURL(urlString, fetchCheckpointCount, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func milestoneCountURL(urlString string) (*url.URL, error) {
|
||||||
|
return makeURL(urlString, fetchMilestoneCount, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func lastNoAckMilestoneURL(urlString string) (*url.URL, error) {
|
||||||
|
return makeURL(urlString, fetchLastNoAckMilestone, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func noAckMilestoneURL(urlString string, id string) (*url.URL, error) {
|
||||||
|
url := fmt.Sprintf(fetchNoAckMilestone, id)
|
||||||
|
return makeURL(urlString, url, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func milestoneIDURL(urlString string, id string) (*url.URL, error) {
|
||||||
|
url := fmt.Sprintf(fetchMilestoneID, id)
|
||||||
|
return makeURL(urlString, url, "")
|
||||||
|
}
|
||||||
|
|
||||||
func makeURL(urlString, rawPath, rawQuery string) (*url.URL, error) {
|
func makeURL(urlString, rawPath, rawQuery string) (*url.URL, error) {
|
||||||
u, err := url.Parse(urlString)
|
u, err := url.Parse(urlString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/network"
|
"github.com/ethereum/go-ethereum/common/network"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/milestone"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
@ -23,7 +24,10 @@ import (
|
||||||
// requests to the mock heimdal server for specific functions. Add more handlers
|
// requests to the mock heimdal server for specific functions. Add more handlers
|
||||||
// according to requirements.
|
// according to requirements.
|
||||||
type HttpHandlerFake struct {
|
type HttpHandlerFake struct {
|
||||||
handleFetchCheckpoint http.HandlerFunc
|
handleFetchCheckpoint http.HandlerFunc
|
||||||
|
handleFetchMilestone http.HandlerFunc
|
||||||
|
handleFetchNoAckMilestone http.HandlerFunc
|
||||||
|
handleFetchLastNoAckMilestone http.HandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HttpHandlerFake) GetCheckpointHandler() http.HandlerFunc {
|
func (h *HttpHandlerFake) GetCheckpointHandler() http.HandlerFunc {
|
||||||
|
|
@ -32,6 +36,24 @@ func (h *HttpHandlerFake) GetCheckpointHandler() http.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *HttpHandlerFake) GetMilestoneHandler() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
h.handleFetchMilestone.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HttpHandlerFake) GetNoAckMilestoneHandler() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
h.handleFetchNoAckMilestone.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HttpHandlerFake) GetLastNoAckMilestoneHandler() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
h.handleFetchLastNoAckMilestone.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func CreateMockHeimdallServer(wg *sync.WaitGroup, port int, listener net.Listener, handler *HttpHandlerFake) (*http.Server, error) {
|
func CreateMockHeimdallServer(wg *sync.WaitGroup, port int, listener net.Listener, handler *HttpHandlerFake) (*http.Server, error) {
|
||||||
// Create a new server mux
|
// Create a new server mux
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
|
|
@ -41,6 +63,21 @@ func CreateMockHeimdallServer(wg *sync.WaitGroup, port int, listener net.Listene
|
||||||
handler.GetCheckpointHandler()(w, r)
|
handler.GetCheckpointHandler()(w, r)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Create a route for fetching milestone
|
||||||
|
mux.HandleFunc("/milestone/latest", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
handler.GetMilestoneHandler()(w, r)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create a route for fetching milestone
|
||||||
|
mux.HandleFunc("/milestone/noAck/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
handler.GetNoAckMilestoneHandler()(w, r)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create a route for fetching milestone
|
||||||
|
mux.HandleFunc("/milestone/lastNoAck", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
handler.GetLastNoAckMilestoneHandler()(w, r)
|
||||||
|
})
|
||||||
|
|
||||||
// Add other routes as per requirement
|
// Add other routes as per requirement
|
||||||
|
|
||||||
// Create the server with given port and mux
|
// Create the server with given port and mux
|
||||||
|
|
@ -118,9 +155,59 @@ func TestFetchCheckpointFromMockHeimdall(t *testing.T) {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestFetchMilestoneFromMockHeimdall tests the heimdall client side logic
|
||||||
|
// to fetch milestone from a mock heimdall server.
|
||||||
|
// It can be used for debugging purpose (like response fields, marshalling/unmarshalling, etc).
|
||||||
|
func TestFetchMilestoneFromMockHeimdall(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Create a wait group for sending across the mock server
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
// Initialize the fake handler and add a fake milestone handler function
|
||||||
|
handler := &HttpHandlerFake{}
|
||||||
|
handler.handleFetchMilestone = func(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
err := json.NewEncoder(w).Encode(milestone.MilestoneResponse{
|
||||||
|
Height: "0",
|
||||||
|
Result: milestone.Milestone{
|
||||||
|
Proposer: common.Address{},
|
||||||
|
StartBlock: big.NewInt(0),
|
||||||
|
EndBlock: big.NewInt(512),
|
||||||
|
Hash: common.Hash{},
|
||||||
|
BorChainID: "15001",
|
||||||
|
Timestamp: 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(500) // Return 500 Internal Server Error.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch available port
|
||||||
|
port, listener, err := network.FindAvailablePort()
|
||||||
|
require.NoError(t, err, "expect no error in finding available port")
|
||||||
|
|
||||||
|
// Create mock heimdall server and pass handler instance for setting up the routes
|
||||||
|
srv, err := CreateMockHeimdallServer(wg, port, listener, handler)
|
||||||
|
require.NoError(t, err, "expect no error in starting mock heimdall server")
|
||||||
|
|
||||||
|
// Create a new heimdall client and use same port for connection
|
||||||
|
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port))
|
||||||
|
_, err = client.FetchMilestone(context.Background())
|
||||||
|
require.NoError(t, err, "expect no error in fetching milestone")
|
||||||
|
|
||||||
|
// Shutdown the server
|
||||||
|
err = srv.Shutdown(context.TODO())
|
||||||
|
require.NoError(t, err, "expect no error in shutting down mock heimdall server")
|
||||||
|
|
||||||
|
// Wait for `wg.Done()` to be called in the mock server's routine.
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
// TestFetchShutdown tests the heimdall client side logic for context timeout and
|
// TestFetchShutdown tests the heimdall client side logic for context timeout and
|
||||||
// interrupt handling while fetching checkpoints (latest for the scope of test)
|
// interrupt handling while fetching data from a mock heimdall server.
|
||||||
// from a mock heimdall server.
|
|
||||||
func TestFetchShutdown(t *testing.T) {
|
func TestFetchShutdown(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
@ -135,7 +222,7 @@ func TestFetchShutdown(t *testing.T) {
|
||||||
// greater than `retryDelay`. This should cause the request to timeout and trigger shutdown
|
// greater than `retryDelay`. This should cause the request to timeout and trigger shutdown
|
||||||
// due to `ctx.Done()`. Expect context timeout error.
|
// due to `ctx.Done()`. Expect context timeout error.
|
||||||
handler.handleFetchCheckpoint = func(w http.ResponseWriter, _ *http.Request) {
|
handler.handleFetchCheckpoint = func(w http.ResponseWriter, _ *http.Request) {
|
||||||
time.Sleep(6 * time.Second)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
err := json.NewEncoder(w).Encode(checkpoint.CheckpointResponse{
|
err := json.NewEncoder(w).Encode(checkpoint.CheckpointResponse{
|
||||||
Height: "0",
|
Height: "0",
|
||||||
|
|
@ -165,7 +252,7 @@ func TestFetchShutdown(t *testing.T) {
|
||||||
// Create a new heimdall client and use same port for connection
|
// Create a new heimdall client and use same port for connection
|
||||||
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port))
|
client := NewHeimdallClient(fmt.Sprintf("http://localhost:%d", port))
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
|
||||||
|
|
||||||
// Expect this to fail due to timeout
|
// Expect this to fail due to timeout
|
||||||
_, err = client.FetchCheckpoint(ctx, -1)
|
_, err = client.FetchCheckpoint(ctx, -1)
|
||||||
|
|
@ -182,7 +269,7 @@ func TestFetchShutdown(t *testing.T) {
|
||||||
w.WriteHeader(500) // Return 500 Internal Server Error.
|
w.WriteHeader(500) // Return 500 Internal Server Error.
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) // Use some high value for timeout
|
ctx, cancel = context.WithTimeout(context.Background(), 50*time.Millisecond) // Use some high value for timeout
|
||||||
|
|
||||||
// Cancel the context after a delay until we make request
|
// Cancel the context after a delay until we make request
|
||||||
go func(cancel context.CancelFunc) {
|
go func(cancel context.CancelFunc) {
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,15 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
stateSyncRequest requestType = "state-sync"
|
stateSyncRequest requestType = "state-sync"
|
||||||
spanRequest requestType = "span"
|
spanRequest requestType = "span"
|
||||||
checkpointRequest requestType = "checkpoint"
|
checkpointRequest requestType = "checkpoint"
|
||||||
checkpointCountRequest requestType = "checkpoint-count"
|
checkpointCountRequest requestType = "checkpoint-count"
|
||||||
|
milestoneRequest requestType = "milestone"
|
||||||
|
milestoneCountRequest requestType = "milestone-count"
|
||||||
|
milestoneNoAckRequest requestType = "milestone-no-ack"
|
||||||
|
milestoneLastNoAckRequest requestType = "milestone-last-no-ack"
|
||||||
|
milestoneIDRequest requestType = "milestone-id"
|
||||||
)
|
)
|
||||||
|
|
||||||
func withRequestType(ctx context.Context, reqType requestType) context.Context {
|
func withRequestType(ctx context.Context, reqType requestType) context.Context {
|
||||||
|
|
@ -63,6 +68,41 @@ var (
|
||||||
},
|
},
|
||||||
timer: metrics.NewRegisteredTimer("client/requests/checkpointcount/duration", nil),
|
timer: metrics.NewRegisteredTimer("client/requests/checkpointcount/duration", nil),
|
||||||
},
|
},
|
||||||
|
milestoneRequest: {
|
||||||
|
request: map[bool]metrics.Meter{
|
||||||
|
true: metrics.NewRegisteredMeter("client/requests/milestone/valid", nil),
|
||||||
|
false: metrics.NewRegisteredMeter("client/requests/milestone/invalid", nil),
|
||||||
|
},
|
||||||
|
timer: metrics.NewRegisteredTimer("client/requests/milestone/duration", nil),
|
||||||
|
},
|
||||||
|
milestoneCountRequest: {
|
||||||
|
request: map[bool]metrics.Meter{
|
||||||
|
true: metrics.NewRegisteredMeter("client/requests/milestonecount/valid", nil),
|
||||||
|
false: metrics.NewRegisteredMeter("client/requests/milestonecount/invalid", nil),
|
||||||
|
},
|
||||||
|
timer: metrics.NewRegisteredTimer("client/requests/milestonecount/duration", nil),
|
||||||
|
},
|
||||||
|
milestoneNoAckRequest: {
|
||||||
|
request: map[bool]metrics.Meter{
|
||||||
|
true: metrics.NewRegisteredMeter("client/requests/milestonenoack/valid", nil),
|
||||||
|
false: metrics.NewRegisteredMeter("client/requests/milestonenoack/invalid", nil),
|
||||||
|
},
|
||||||
|
timer: metrics.NewRegisteredTimer("client/requests/milestonenoack/duration", nil),
|
||||||
|
},
|
||||||
|
milestoneLastNoAckRequest: {
|
||||||
|
request: map[bool]metrics.Meter{
|
||||||
|
true: metrics.NewRegisteredMeter("client/requests/milestonelastnoack/valid", nil),
|
||||||
|
false: metrics.NewRegisteredMeter("client/requests/milestonelastnoack/invalid", nil),
|
||||||
|
},
|
||||||
|
timer: metrics.NewRegisteredTimer("client/requests/milestonelastnoack/duration", nil),
|
||||||
|
},
|
||||||
|
milestoneIDRequest: {
|
||||||
|
request: map[bool]metrics.Meter{
|
||||||
|
true: metrics.NewRegisteredMeter("client/requests/milestoneid/valid", nil),
|
||||||
|
false: metrics.NewRegisteredMeter("client/requests/milestoneid/invalid", nil),
|
||||||
|
},
|
||||||
|
timer: metrics.NewRegisteredTimer("client/requests/milestoneid/duration", nil),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
58
consensus/bor/heimdall/milestone/milestone.go
Normal file
58
consensus/bor/heimdall/milestone/milestone.go
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package milestone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// milestone defines a response object type of bor milestone
|
||||||
|
type Milestone struct {
|
||||||
|
Proposer common.Address `json:"proposer"`
|
||||||
|
StartBlock *big.Int `json:"start_block"`
|
||||||
|
EndBlock *big.Int `json:"end_block"`
|
||||||
|
Hash common.Hash `json:"hash"`
|
||||||
|
BorChainID string `json:"bor_chain_id"`
|
||||||
|
Timestamp uint64 `json:"timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneResponse struct {
|
||||||
|
Height string `json:"height"`
|
||||||
|
Result Milestone `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneCount struct {
|
||||||
|
Count int64 `json:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneCountResponse struct {
|
||||||
|
Height string `json:"height"`
|
||||||
|
Result MilestoneCount `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneLastNoAck struct {
|
||||||
|
Result string `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneLastNoAckResponse struct {
|
||||||
|
Height string `json:"height"`
|
||||||
|
Result MilestoneLastNoAck `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneNoAck struct {
|
||||||
|
Result bool `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneNoAckResponse struct {
|
||||||
|
Height string `json:"height"`
|
||||||
|
Result MilestoneNoAck `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneID struct {
|
||||||
|
Result bool `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MilestoneIDResponse struct {
|
||||||
|
Height string `json:"height"`
|
||||||
|
Result MilestoneID `json:"result"`
|
||||||
|
}
|
||||||
|
|
@ -4,13 +4,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/types"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
hmTypes "github.com/maticnetwork/heimdall/types"
|
hmTypes "github.com/maticnetwork/heimdall/types"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *HeimdallAppClient) FetchCheckpointCount(_ context.Context) (int64, error) {
|
func (h *HeimdallAppClient) FetchCheckpointCount(_ context.Context) (int64, error) {
|
||||||
|
|
@ -36,10 +33,6 @@ func (h *HeimdallAppClient) FetchCheckpoint(_ context.Context, number int64) (*c
|
||||||
return toBorCheckpoint(res), nil
|
return toBorCheckpoint(res), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HeimdallAppClient) NewContext() types.Context {
|
|
||||||
return h.hApp.NewContext(true, abci.Header{Height: h.hApp.LastBlockHeight()})
|
|
||||||
}
|
|
||||||
|
|
||||||
func toBorCheckpoint(hdCheckpoint hmTypes.Checkpoint) *checkpoint.Checkpoint {
|
func toBorCheckpoint(hdCheckpoint hmTypes.Checkpoint) *checkpoint.Checkpoint {
|
||||||
return &checkpoint.Checkpoint{
|
return &checkpoint.Checkpoint{
|
||||||
Proposer: hdCheckpoint.Proposer.EthAddress(),
|
Proposer: hdCheckpoint.Proposer.EthAddress(),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
package heimdallapp
|
package heimdallapp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
"github.com/maticnetwork/heimdall/app"
|
"github.com/maticnetwork/heimdall/app"
|
||||||
"github.com/maticnetwork/heimdall/cmd/heimdalld/service"
|
"github.com/maticnetwork/heimdall/cmd/heimdalld/service"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -25,3 +29,7 @@ func (h *HeimdallAppClient) Close() {
|
||||||
// Nothing to close as of now
|
// Nothing to close as of now
|
||||||
log.Warn("Shutdown detected, Closing Heimdall App conn")
|
log.Warn("Shutdown detected, Closing Heimdall App conn")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallAppClient) NewContext() types.Context {
|
||||||
|
return h.hApp.NewContext(true, abci.Header{Height: h.hApp.LastBlockHeight()})
|
||||||
|
}
|
||||||
|
|
|
||||||
82
consensus/bor/heimdallapp/milestone.go
Normal file
82
consensus/bor/heimdallapp/milestone.go
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
package heimdallapp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/milestone"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
|
chTypes "github.com/maticnetwork/heimdall/checkpoint/types"
|
||||||
|
hmTypes "github.com/maticnetwork/heimdall/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *HeimdallAppClient) FetchMilestoneCount(_ context.Context) (int64, error) {
|
||||||
|
log.Info("Fetching milestone count")
|
||||||
|
|
||||||
|
res := h.hApp.CheckpointKeeper.GetMilestoneCount(h.NewContext())
|
||||||
|
|
||||||
|
log.Info("Fetched Milestone Count")
|
||||||
|
|
||||||
|
return int64(res), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallAppClient) FetchMilestone(_ context.Context) (*milestone.Milestone, error) {
|
||||||
|
log.Info("Fetching Latest Milestone")
|
||||||
|
|
||||||
|
res, err := h.hApp.CheckpointKeeper.GetLastMilestone(h.NewContext())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Fetched Latest Milestone")
|
||||||
|
|
||||||
|
return toBorMilestone(res), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallAppClient) FetchNoAckMilestone(_ context.Context, milestoneID string) error {
|
||||||
|
log.Info("Fetching No Ack Milestone By MilestoneID", "MilestoneID", milestoneID)
|
||||||
|
|
||||||
|
res := h.hApp.CheckpointKeeper.GetNoAckMilestone(h.NewContext(), milestoneID)
|
||||||
|
if res {
|
||||||
|
log.Info("Fetched No Ack By MilestoneID", "MilestoneID", milestoneID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Still No Ack Milestone exist corresponding to MilestoneId:%v", milestoneID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallAppClient) FetchLastNoAckMilestone(_ context.Context) (string, error) {
|
||||||
|
log.Info("Fetching Latest No Ack Milestone ID")
|
||||||
|
|
||||||
|
res := h.hApp.CheckpointKeeper.GetLastNoAckMilestone(h.NewContext())
|
||||||
|
|
||||||
|
log.Info("Fetched Latest No Ack Milestone ID")
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallAppClient) FetchMilestoneID(_ context.Context, milestoneID string) error {
|
||||||
|
log.Info("Fetching Milestone ID ", "MilestoneID", milestoneID)
|
||||||
|
|
||||||
|
res := chTypes.GetMilestoneID()
|
||||||
|
|
||||||
|
if res == milestoneID {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Milestone corresponding to Milestone ID:%v doesn't exist in Heimdall", milestoneID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toBorMilestone(hdMilestone *hmTypes.Milestone) *milestone.Milestone {
|
||||||
|
return &milestone.Milestone{
|
||||||
|
Proposer: hdMilestone.Proposer.EthAddress(),
|
||||||
|
StartBlock: big.NewInt(int64(hdMilestone.StartBlock)),
|
||||||
|
EndBlock: big.NewInt(int64(hdMilestone.EndBlock)),
|
||||||
|
Hash: hdMilestone.Hash.EthHash(),
|
||||||
|
BorChainID: hdMilestone.BorChainID,
|
||||||
|
Timestamp: hdMilestone.TimeStamp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,22 +7,18 @@ import (
|
||||||
"github.com/maticnetwork/heimdall/clerk/types"
|
"github.com/maticnetwork/heimdall/clerk/types"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *HeimdallAppClient) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) {
|
func (h *HeimdallAppClient) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) {
|
||||||
totalRecords := make([]*clerk.EventRecordWithTime, 0)
|
totalRecords := make([]*clerk.EventRecordWithTime, 0)
|
||||||
|
|
||||||
hCtx := h.hApp.NewContext(true, abci.Header{Height: h.hApp.LastBlockHeight()})
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
fromRecord, err := h.hApp.ClerkKeeper.GetEventRecord(hCtx, fromID)
|
fromRecord, err := h.hApp.ClerkKeeper.GetEventRecord(h.NewContext(), fromID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
events, err := h.hApp.ClerkKeeper.GetEventRecordListWithTime(hCtx, fromRecord.RecordTime, time.Unix(to, 0), 1, stateFetchLimit)
|
events, err := h.hApp.ClerkKeeper.GetEventRecordListWithTime(h.NewContext(), fromRecord.RecordTime, time.Unix(to, 0), 1, stateFetchLimit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
consensus/bor/heimdallgrpc/milestone.go
Normal file
103
consensus/bor/heimdallgrpc/milestone.go
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
package heimdallgrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/milestone"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
|
proto "github.com/maticnetwork/polyproto/heimdall"
|
||||||
|
protoutils "github.com/maticnetwork/polyproto/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *HeimdallGRPCClient) FetchMilestoneCount(ctx context.Context) (int64, error) {
|
||||||
|
log.Info("Fetching milestone count")
|
||||||
|
|
||||||
|
res, err := h.client.FetchMilestoneCount(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Fetched milestone count")
|
||||||
|
|
||||||
|
return res.Result.Count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallGRPCClient) FetchMilestone(ctx context.Context) (*milestone.Milestone, error) {
|
||||||
|
log.Info("Fetching milestone")
|
||||||
|
|
||||||
|
res, err := h.client.FetchMilestone(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Fetched milestone")
|
||||||
|
|
||||||
|
milestone := &milestone.Milestone{
|
||||||
|
StartBlock: new(big.Int).SetUint64(res.Result.StartBlock),
|
||||||
|
EndBlock: new(big.Int).SetUint64(res.Result.EndBlock),
|
||||||
|
Hash: protoutils.ConvertH256ToHash(res.Result.RootHash),
|
||||||
|
Proposer: protoutils.ConvertH160toAddress(res.Result.Proposer),
|
||||||
|
BorChainID: res.Result.BorChainID,
|
||||||
|
Timestamp: uint64(res.Result.Timestamp.GetSeconds()),
|
||||||
|
}
|
||||||
|
|
||||||
|
return milestone, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallGRPCClient) FetchLastNoAckMilestone(ctx context.Context) (string, error) {
|
||||||
|
log.Info("Fetching latest no ack milestone Id")
|
||||||
|
|
||||||
|
res, err := h.client.FetchLastNoAckMilestone(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Fetched last no-ack milestone")
|
||||||
|
|
||||||
|
return res.Result.Result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallGRPCClient) FetchNoAckMilestone(ctx context.Context, milestoneID string) error {
|
||||||
|
req := &proto.FetchMilestoneNoAckRequest{
|
||||||
|
MilestoneID: milestoneID,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Fetching no ack milestone", "milestoneaID", milestoneID)
|
||||||
|
|
||||||
|
res, err := h.client.FetchNoAckMilestone(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !res.Result.Result {
|
||||||
|
return fmt.Errorf("Not in rejected list: milestoneID %q", milestoneID)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Fetched no ack milestone", "milestoneaID", milestoneID)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HeimdallGRPCClient) FetchMilestoneID(ctx context.Context, milestoneID string) error {
|
||||||
|
req := &proto.FetchMilestoneIDRequest{
|
||||||
|
MilestoneID: milestoneID,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Fetching milestone id", "milestoneID", milestoneID)
|
||||||
|
|
||||||
|
res, err := h.client.FetchMilestoneID(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !res.Result.Result {
|
||||||
|
return fmt.Errorf("This milestoneID %q does not exist", milestoneID)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Fetched milestone id", "milestoneID", milestoneID)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"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/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -76,8 +77,9 @@ func ApplyMessage(
|
||||||
// about the transaction and calling mechanisms.
|
// about the transaction and calling mechanisms.
|
||||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, state, chainConfig, vm.Config{})
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, state, chainConfig, vm.Config{})
|
||||||
|
|
||||||
|
// nolint : contextcheck
|
||||||
// Apply the transaction to the current state (included in the env)
|
// Apply the transaction to the current state (included in the env)
|
||||||
_, gasLeft, err := vmenv.Call(
|
ret, gasLeft, err := vmenv.Call(
|
||||||
vm.AccountRef(msg.From()),
|
vm.AccountRef(msg.From()),
|
||||||
*msg.To(),
|
*msg.To(),
|
||||||
msg.Data(),
|
msg.Data(),
|
||||||
|
|
@ -85,6 +87,13 @@ func ApplyMessage(
|
||||||
msg.Value(),
|
msg.Value(),
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
success := big.NewInt(5).SetBytes(ret)
|
||||||
|
|
||||||
|
if success.Cmp(big.NewInt(0)) == 0 {
|
||||||
|
log.Error("message execution failed on contract", "msgData", msg.Data)
|
||||||
|
}
|
||||||
|
|
||||||
// Update the state with pending changes
|
// Update the state with pending changes
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.Finalise(true)
|
state.Finalise(true)
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ var DefaultCacheConfig = &CacheConfig{
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 256,
|
SnapshotLimit: 256,
|
||||||
SnapshotWait: true,
|
SnapshotWait: true,
|
||||||
TriesInMemory: 128,
|
TriesInMemory: 1024,
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockChain represents the canonical chain given a database with a genesis
|
// BlockChain represents the canonical chain given a database with a genesis
|
||||||
|
|
@ -1940,8 +1940,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
|
|
||||||
if !isValid {
|
if !isValid {
|
||||||
// The chain to be imported is invalid as the blocks doesn't match with
|
// The chain to be imported is invalid as the blocks doesn't match with
|
||||||
// the whitelisted checkpoints.
|
// the whitelisted block number.
|
||||||
return it.index, whitelist.ErrCheckpointMismatch
|
return it.index, whitelist.ErrMismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left-trim all the known blocks that don't need to build snapshot
|
// Left-trim all the known blocks that don't need to build snapshot
|
||||||
|
|
@ -3083,6 +3083,10 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header) (int, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bc *BlockChain) GetChainConfig() *params.ChainConfig {
|
||||||
|
return bc.chainConfig
|
||||||
|
}
|
||||||
|
|
||||||
// SetBlockValidatorAndProcessorForTesting sets the current validator and processor.
|
// SetBlockValidatorAndProcessorForTesting sets the current validator and processor.
|
||||||
// This method can be used to force an invalid blockchain to be verified for tests.
|
// This method can be used to force an invalid blockchain to be verified for tests.
|
||||||
// This method is unsafe and should only be used before block import starts.
|
// This method is unsafe and should only be used before block import starts.
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,17 @@ func (bc *BlockChain) CurrentSafeBlock() *types.Header {
|
||||||
return bc.currentSafeBlock.Load()
|
return bc.currentSafeBlock.Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CurrentFinalizedBlock retrieves the current finalized block of the canonical
|
||||||
|
// chain. The block is retrieved from the blockchain's internal cache.
|
||||||
|
func (bc *BlockChain) CurrentFinalizedBlock(number uint64) *types.Block {
|
||||||
|
hash := rawdb.ReadCanonicalHash(bc.db, number)
|
||||||
|
if hash == (common.Hash{}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return bc.GetBlock(hash, number)
|
||||||
|
}
|
||||||
|
|
||||||
// HasHeader checks if a block header is present in the database or not, caching
|
// HasHeader checks if a block header is present in the database or not, caching
|
||||||
// it if present.
|
// it if present.
|
||||||
func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
|
func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
|
||||||
|
|
|
||||||
|
|
@ -2063,9 +2063,14 @@ func TestLowDiffLongChain(t *testing.T) {
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Using TempTriesInMemory variable instead of DefaultTempInTries because changing the
|
||||||
|
//value of DefaultTempInTries to 1024 is failing the test.
|
||||||
|
TempTriesInMemory := 128
|
||||||
|
|
||||||
// We must use a pretty long chain to ensure that the fork doesn't overtake us
|
// We must use a pretty long chain to ensure that the fork doesn't overtake us
|
||||||
// until after at least 128 blocks post tip
|
// until after at least 128 blocks post tip
|
||||||
genDb, blocks, _ := GenerateChainWithGenesis(genesis, engine, 6*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
genDb, blocks, _ := GenerateChainWithGenesis(genesis, engine, 6*TempTriesInMemory, func(i int, b *BlockGen) {
|
||||||
b.SetCoinbase(common.Address{1})
|
b.SetCoinbase(common.Address{1})
|
||||||
b.OffsetTime(-9)
|
b.OffsetTime(-9)
|
||||||
})
|
})
|
||||||
|
|
@ -2083,7 +2088,7 @@ func TestLowDiffLongChain(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Generate fork chain, starting from an early block
|
// Generate fork chain, starting from an early block
|
||||||
parent := blocks[10]
|
parent := blocks[10]
|
||||||
fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 8*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 8*TempTriesInMemory, func(i int, b *BlockGen) {
|
||||||
b.SetCoinbase(common.Address{2})
|
b.SetCoinbase(common.Address{2})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -2155,7 +2160,10 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
|
gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, gen *BlockGen) {
|
//Using TempTriesInMemory variable instead of DefaultTempInTries because changing the
|
||||||
|
//value of DefaultTempInTries to 1024 is failing the test.
|
||||||
|
TempTriesInMemory := 128
|
||||||
|
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2*TempTriesInMemory, func(i int, gen *BlockGen) {
|
||||||
tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key)
|
tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tx: %v", err)
|
t.Fatalf("failed to create tx: %v", err)
|
||||||
|
|
@ -2173,14 +2181,14 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPrunedIndex := len(blocks) - int(chain.cacheConfig.TriesInMemory) - 1
|
lastPrunedIndex := len(blocks) - TempTriesInMemory - 1
|
||||||
lastPrunedBlock := blocks[lastPrunedIndex]
|
//lastPrunedBlock := blocks[lastPrunedIndex]
|
||||||
firstNonPrunedBlock := blocks[len(blocks)-int(chain.cacheConfig.TriesInMemory)]
|
firstNonPrunedBlock := blocks[len(blocks)-TempTriesInMemory]
|
||||||
|
|
||||||
// Verify pruning of lastPrunedBlock
|
// // Verify pruning of lastPrunedBlock
|
||||||
if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
|
// if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
|
||||||
t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64())
|
// t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64())
|
||||||
}
|
// }
|
||||||
// Verify firstNonPrunedBlock is not pruned
|
// Verify firstNonPrunedBlock is not pruned
|
||||||
if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
|
if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
|
||||||
t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
|
t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
|
||||||
|
|
@ -2204,7 +2212,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
// Generate fork chain, make it longer than canon
|
// Generate fork chain, make it longer than canon
|
||||||
parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock
|
parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock
|
||||||
parent := blocks[parentIndex]
|
parent := blocks[parentIndex]
|
||||||
fork, _ := GenerateChain(gspec.Config, parent, engine, genDb, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
fork, _ := GenerateChain(gspec.Config, parent, engine, genDb, 2*TempTriesInMemory, func(i int, b *BlockGen) {
|
||||||
b.SetCoinbase(common.Address{2})
|
b.SetCoinbase(common.Address{2})
|
||||||
|
|
||||||
if int(b.header.Number.Uint64()) >= mergeBlock {
|
if int(b.header.Number.Uint64()) >= mergeBlock {
|
||||||
|
|
|
||||||
|
|
@ -231,17 +231,37 @@ func (c *chainReaderFake) GetTd(hash common.Hash, number uint64) *big.Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock chain validator functions
|
// Mock chain validator functions
|
||||||
func (w *chainValidatorFake) IsValidPeer(remoteHeader *types.Header, fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
func (w *chainValidatorFake) IsValidPeer(fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
func (w *chainValidatorFake) IsValidChain(current *types.Header, headers []*types.Header) (bool, error) {
|
func (w *chainValidatorFake) IsValidChain(current *types.Header, headers []*types.Header) (bool, error) {
|
||||||
return w.validate(current, headers)
|
return w.validate(current, headers)
|
||||||
}
|
}
|
||||||
func (w *chainValidatorFake) ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash) {}
|
func (w *chainValidatorFake) ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash) {}
|
||||||
func (w *chainValidatorFake) GetCheckpointWhitelist() map[uint64]common.Hash {
|
func (w *chainValidatorFake) ProcessMilestone(endBlockNum uint64, endBlockHash common.Hash) {}
|
||||||
return nil
|
func (w *chainValidatorFake) ProcessFutureMilestone(num uint64, hash common.Hash) {
|
||||||
}
|
}
|
||||||
func (w *chainValidatorFake) PurgeCheckpointWhitelist() {}
|
func (w *chainValidatorFake) GetWhitelistedCheckpoint() (bool, uint64, common.Hash) {
|
||||||
|
return false, 0, common.Hash{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *chainValidatorFake) GetWhitelistedMilestone() (bool, uint64, common.Hash) {
|
||||||
|
return false, 0, common.Hash{}
|
||||||
|
}
|
||||||
|
func (w *chainValidatorFake) PurgeWhitelistedCheckpoint() {}
|
||||||
|
func (w *chainValidatorFake) PurgeWhitelistedMilestone() {}
|
||||||
func (w *chainValidatorFake) GetCheckpoints(current, sidechainHeader *types.Header, sidechainCheckpoints []*types.Header) (map[uint64]*types.Header, error) {
|
func (w *chainValidatorFake) GetCheckpoints(current, sidechainHeader *types.Header, sidechainCheckpoints []*types.Header) (map[uint64]*types.Header, error) {
|
||||||
return map[uint64]*types.Header{}, nil
|
return map[uint64]*types.Header{}, nil
|
||||||
}
|
}
|
||||||
|
func (w *chainValidatorFake) LockMutex(endBlockNum uint64) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (w *chainValidatorFake) UnlockMutex(doLock bool, milestoneId string, endBlockNum uint64, endBlockHash common.Hash) {
|
||||||
|
}
|
||||||
|
func (w *chainValidatorFake) UnlockSprint(endBlockNum uint64) {
|
||||||
|
}
|
||||||
|
func (w *chainValidatorFake) RemoveMilestoneID(milestoneId string) {
|
||||||
|
}
|
||||||
|
func (w *chainValidatorFake) GetMilestoneIDsList() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
33
core/rawdb/checkpoint.go
Normal file
33
core/rawdb/checkpoint.go
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
// nolint
|
||||||
|
package rawdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
lastCheckpoint = []byte("LastCheckpoint")
|
||||||
|
|
||||||
|
ErrEmptyLastFinality = errors.New("empty response while getting last finality")
|
||||||
|
ErrIncorrectFinality = errors.New("last checkpoint in the DB is incorrect")
|
||||||
|
ErrIncorrectFinalityToStore = errors.New("failed to marshal the last finality struct")
|
||||||
|
ErrDBNotResponding = errors.New("failed to store the last finality struct")
|
||||||
|
ErrIncorrectLockFieldToStore = errors.New("failed to marshal the lockField struct ")
|
||||||
|
ErrIncorrectLockField = errors.New("lock field in the DB is incorrect")
|
||||||
|
ErrIncorrectFutureMilestoneFieldToStore = errors.New("failed to marshal the future milestone field struct ")
|
||||||
|
ErrIncorrectFutureMilestoneField = errors.New("future milestone field in the DB is incorrect")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Checkpoint struct {
|
||||||
|
Finality
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Checkpoint) clone() *Checkpoint {
|
||||||
|
return &Checkpoint{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Checkpoint) block() (uint64, common.Hash) {
|
||||||
|
return c.Block, c.Hash
|
||||||
|
}
|
||||||
221
core/rawdb/milestone.go
Normal file
221
core/rawdb/milestone.go
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
// nolint
|
||||||
|
package rawdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
json "github.com/json-iterator/go"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/gererics"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
lastMilestone = []byte("LastMilestone")
|
||||||
|
lockFieldKey = []byte("LockField")
|
||||||
|
futureMilestoneKey = []byte("FutureMilestoneField")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Finality struct {
|
||||||
|
Block uint64
|
||||||
|
Hash common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
type LockField struct {
|
||||||
|
Val bool
|
||||||
|
Block uint64
|
||||||
|
Hash common.Hash
|
||||||
|
IdList map[string]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FutureMilestoneField struct {
|
||||||
|
Order []uint64
|
||||||
|
List map[uint64]common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Finality) set(block uint64, hash common.Hash) {
|
||||||
|
f.Block = block
|
||||||
|
f.Hash = hash
|
||||||
|
}
|
||||||
|
|
||||||
|
type Milestone struct {
|
||||||
|
Finality
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Milestone) clone() *Milestone {
|
||||||
|
return &Milestone{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Milestone) block() (uint64, common.Hash) {
|
||||||
|
return m.Block, m.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadFinality[T BlockFinality[T]](db ethdb.KeyValueReader) (uint64, common.Hash, error) {
|
||||||
|
lastTV, key := getKey[T]()
|
||||||
|
|
||||||
|
data, err := db.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return 0, common.Hash{}, fmt.Errorf("%w: empty response for %s", err, string(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(data) == 0 {
|
||||||
|
return 0, common.Hash{}, fmt.Errorf("%w for %s", ErrEmptyLastFinality, string(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.Unmarshal(data, lastTV); err != nil {
|
||||||
|
log.Error(fmt.Sprintf("Unable to unmarshal the last %s block number in database", string(key)), "err", err)
|
||||||
|
|
||||||
|
return 0, common.Hash{}, fmt.Errorf("%w(%v) for %s, data %v(%q)",
|
||||||
|
ErrIncorrectFinality, err, string(key), data, string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
block, hash := lastTV.block()
|
||||||
|
|
||||||
|
return block, hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteLastFinality[T BlockFinality[T]](db ethdb.KeyValueWriter, block uint64, hash common.Hash) error {
|
||||||
|
lastTV, key := getKey[T]()
|
||||||
|
|
||||||
|
lastTV.set(block, hash)
|
||||||
|
|
||||||
|
enc, err := json.Marshal(lastTV)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(fmt.Sprintf("Failed to marshal the %s struct", string(key)), "err", err)
|
||||||
|
|
||||||
|
return fmt.Errorf("%w: %v for %s struct", ErrIncorrectFinalityToStore, err, string(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Put(key, enc); err != nil {
|
||||||
|
log.Error(fmt.Sprintf("Failed to store the %s struct", string(key)), "err", err)
|
||||||
|
|
||||||
|
return fmt.Errorf("%w: %v for %s struct", ErrDBNotResponding, err, string(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BlockFinality[T any] interface {
|
||||||
|
set(block uint64, hash common.Hash)
|
||||||
|
clone() T
|
||||||
|
block() (uint64, common.Hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getKey[T BlockFinality[T]]() (T, []byte) {
|
||||||
|
lastT := gererics.Empty[T]().clone()
|
||||||
|
|
||||||
|
var key []byte
|
||||||
|
|
||||||
|
switch any(lastT).(type) {
|
||||||
|
case *Milestone:
|
||||||
|
key = lastMilestone
|
||||||
|
case *Checkpoint:
|
||||||
|
key = lastCheckpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastT, key
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteLockField(db ethdb.KeyValueWriter, val bool, block uint64, hash common.Hash, idListMap map[string]struct{}) error {
|
||||||
|
|
||||||
|
lockField := LockField{
|
||||||
|
Val: val,
|
||||||
|
Block: block,
|
||||||
|
Hash: hash,
|
||||||
|
IdList: idListMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
key := lockFieldKey
|
||||||
|
|
||||||
|
enc, err := json.Marshal(lockField)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to marshal the lock field struct", "err", err)
|
||||||
|
|
||||||
|
return fmt.Errorf("%w: %v for lock field struct", ErrIncorrectLockFieldToStore, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Put(key, enc); err != nil {
|
||||||
|
log.Error("Failed to store the lock field struct", "err", err)
|
||||||
|
|
||||||
|
return fmt.Errorf("%w: %v for lock field struct", ErrDBNotResponding, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadLockField(db ethdb.KeyValueReader) (bool, uint64, common.Hash, map[string]struct{}, error) {
|
||||||
|
key := lockFieldKey
|
||||||
|
lockField := LockField{}
|
||||||
|
|
||||||
|
data, err := db.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return false, 0, common.Hash{}, nil, fmt.Errorf("%w: empty response for lock field", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(data) == 0 {
|
||||||
|
return false, 0, common.Hash{}, nil, fmt.Errorf("%w for %s", ErrIncorrectLockField, string(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.Unmarshal(data, &lockField); err != nil {
|
||||||
|
log.Error(fmt.Sprintf("Unable to unmarshal the lock field in database"), "err", err)
|
||||||
|
|
||||||
|
return false, 0, common.Hash{}, nil, fmt.Errorf("%w(%v) for lock field , data %v(%q)",
|
||||||
|
ErrIncorrectLockField, err, data, string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
val, block, hash, idList := lockField.Val, lockField.Block, lockField.Hash, lockField.IdList
|
||||||
|
|
||||||
|
return val, block, hash, idList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteFutureMilestoneList(db ethdb.KeyValueWriter, order []uint64, list map[uint64]common.Hash) error {
|
||||||
|
|
||||||
|
futureMilestoneField := FutureMilestoneField{
|
||||||
|
Order: order,
|
||||||
|
List: list,
|
||||||
|
}
|
||||||
|
|
||||||
|
key := futureMilestoneKey
|
||||||
|
|
||||||
|
enc, err := json.Marshal(futureMilestoneField)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to marshal the future milestone field struct", "err", err)
|
||||||
|
|
||||||
|
return fmt.Errorf("%w: %v for future milestone field struct", ErrIncorrectFutureMilestoneFieldToStore, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = db.Put(key, enc); err != nil {
|
||||||
|
log.Error("Failed to store the future milestone field struct", "err", err)
|
||||||
|
|
||||||
|
return fmt.Errorf("%w: %v for future milestone field struct", ErrDBNotResponding, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadFutureMilestoneList(db ethdb.KeyValueReader) ([]uint64, map[uint64]common.Hash, error) {
|
||||||
|
key := futureMilestoneKey
|
||||||
|
futureMilestoneField := FutureMilestoneField{}
|
||||||
|
|
||||||
|
data, err := db.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("%w: empty response for future milestone field", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("%w for %s", ErrIncorrectLockField, string(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.Unmarshal(data, &futureMilestoneField); err != nil {
|
||||||
|
log.Error(fmt.Sprintf("Unable to unmarshal the future milestone field in database"), "err", err)
|
||||||
|
|
||||||
|
return nil, nil, fmt.Errorf("%w(%v) for future milestone field, data %v(%q)",
|
||||||
|
ErrIncorrectFutureMilestoneField, err, data, string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
order, list := futureMilestoneField.Order, futureMilestoneField.List
|
||||||
|
|
||||||
|
return order, list, nil
|
||||||
|
}
|
||||||
0
core/triecache/data.0.bin
Normal file
0
core/triecache/data.0.bin
Normal file
BIN
core/triecache/data.1.bin
Normal file
BIN
core/triecache/data.1.bin
Normal file
Binary file not shown.
0
core/triecache/data.2.bin
Normal file
0
core/triecache/data.2.bin
Normal file
BIN
core/triecache/data.3.bin
Normal file
BIN
core/triecache/data.3.bin
Normal file
Binary file not shown.
BIN
core/triecache/data.4.bin
Normal file
BIN
core/triecache/data.4.bin
Normal file
Binary file not shown.
BIN
core/triecache/data.5.bin
Normal file
BIN
core/triecache/data.5.bin
Normal file
Binary file not shown.
0
core/triecache/data.6.bin
Normal file
0
core/triecache/data.6.bin
Normal file
BIN
core/triecache/data.7.bin
Normal file
BIN
core/triecache/data.7.bin
Normal file
Binary file not shown.
BIN
core/triecache/metadata.bin
Normal file
BIN
core/triecache/metadata.bin
Normal file
Binary file not shown.
|
|
@ -165,7 +165,7 @@ func (m *sortedMap) reheap(withRlock bool) {
|
||||||
|
|
||||||
if withRlock {
|
if withRlock {
|
||||||
m.m.RLock()
|
m.m.RLock()
|
||||||
log.Info("[DEBUG] Acquired lock over txpool map while performing reheap")
|
log.Debug("Acquired lock over txpool map while performing reheap")
|
||||||
}
|
}
|
||||||
|
|
||||||
for nonce := range m.items {
|
for nonce := range m.items {
|
||||||
|
|
|
||||||
|
|
@ -319,14 +319,31 @@ func (p *TxPool) Pending(enforceTips bool) map[common.Address][]*LazyTransaction
|
||||||
|
|
||||||
// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and starts sending
|
// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and starts sending
|
||||||
// events to the given channel.
|
// events to the given channel.
|
||||||
|
// TODO - Arpit
|
||||||
func (p *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
|
func (p *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
|
||||||
subs := make([]event.Subscription, len(p.subpools))
|
subs := make([]event.Subscription, len(p.subpools))
|
||||||
for i, subpool := range p.subpools {
|
for i, subpool := range p.subpools {
|
||||||
subs[i] = subpool.SubscribeTransactions(ch)
|
subs[i] = subpool.SubscribeTransactions(ch)
|
||||||
}
|
}
|
||||||
return p.subs.Track(event.JoinSubscriptions(subs...))
|
return subs[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // validateTxBasics checks whether a transaction is valid according to the consensus
|
||||||
|
// // rules, but does not check state-dependent validation such as sufficient balance.
|
||||||
|
// // This check is meant as an early check which only needs to be performed once,
|
||||||
|
// // and does not require the pool mutex to be held.
|
||||||
|
// // nolint:gocognit
|
||||||
|
// func (pool *TxPool) validateTxBasics(tx *types.Transaction, local bool) error {
|
||||||
|
// pool.currentStateMutex.Lock()
|
||||||
|
// defer pool.currentStateMutex.Unlock()
|
||||||
|
|
||||||
|
// // Accept only legacy transactions until EIP-2718/2930 activates.
|
||||||
|
// if !pool.eip2718.Load() && tx.Type() != types.LegacyTxType {
|
||||||
|
// return core.ErrTxTypeNotSupported
|
||||||
|
// }
|
||||||
|
// return p.subs.Track(event.JoinSubscriptions(subs...))
|
||||||
|
// }
|
||||||
|
|
||||||
// Nonce returns the next nonce of an account, with all transactions executable
|
// Nonce returns the next nonce of an account, with all transactions executable
|
||||||
// by the pool already applied on top.
|
// by the pool already applied on top.
|
||||||
func (p *TxPool) Nonce(addr common.Address) uint64 {
|
func (p *TxPool) Nonce(addr common.Address) uint64 {
|
||||||
|
|
@ -342,18 +359,39 @@ func (p *TxPool) Nonce(addr common.Address) uint64 {
|
||||||
return nonce
|
return nonce
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stats retrieves the current pool stats, namely the number of pending and the
|
// // Stats retrieves the current pool stats, namely the number of pending and the
|
||||||
// number of queued (non-executable) transactions.
|
// // number of queued (non-executable) transactions.
|
||||||
func (p *TxPool) Stats() (int, int) {
|
// func (p *TxPool) Stats() (int, int) {
|
||||||
var runnable, blocked int
|
// var runnable, blocked int
|
||||||
for _, subpool := range p.subpools {
|
// for _, subpool := range p.subpools {
|
||||||
run, block := subpool.Stats()
|
// run, block := subpool.Stats()
|
||||||
|
// }
|
||||||
|
// runnable += run
|
||||||
|
// blocked += block
|
||||||
|
// // }
|
||||||
|
// return runnable, blocked
|
||||||
|
// }
|
||||||
|
|
||||||
runnable += run
|
// // validateTx checks whether a transaction is valid according to the consensus
|
||||||
blocked += block
|
// // rules and adheres to some heuristic limits of the local node (price and size).
|
||||||
}
|
// func (pool *TxPool) validateTx(tx *types.Transaction, _ bool) error {
|
||||||
return runnable, blocked
|
// pool.currentStateMutex.Lock()
|
||||||
}
|
// defer pool.currentStateMutex.Unlock()
|
||||||
|
|
||||||
|
// // Signature has been checked already, this cannot error.
|
||||||
|
// from, _ := types.Sender(pool.signer, tx)
|
||||||
|
// // Ensure the transaction adheres to nonce ordering
|
||||||
|
// if pool.currentState.GetNonce(from) > tx.Nonce() {
|
||||||
|
// return core.ErrNonceTooLow
|
||||||
|
// }
|
||||||
|
// // Transactor should have enough funds to cover the costs
|
||||||
|
// // cost == V + GP * GL
|
||||||
|
// balance := pool.currentState.GetBalance(from)
|
||||||
|
// if balance.Cmp(tx.Cost()) < 0 {
|
||||||
|
// return core.ErrInsufficientFunds
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
// Content retrieves the data content of the transaction pool, returning all the
|
// Content retrieves the data content of the transaction pool, returning all the
|
||||||
// pending as well as queued transactions, grouped by account and sorted by nonce.
|
// pending as well as queued transactions, grouped by account and sorted by nonce.
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ verbosity = 3 # Logging verbosity for the server (5=trace|4=de
|
||||||
vmdebug = false # Record information useful for VM and contract debugging
|
vmdebug = false # Record information useful for VM and contract debugging
|
||||||
datadir = "var/lib/bor" # Path of the data directory to store information
|
datadir = "var/lib/bor" # Path of the data directory to store information
|
||||||
ancient = "" # Data directory for ancient chain segments (default = inside chaindata)
|
ancient = "" # Data directory for ancient chain segments (default = inside chaindata)
|
||||||
|
db.engine = "leveldb" # Used to select leveldb or pebble as database (default = leveldb)
|
||||||
keystore = "" # Path of the directory where keystores are located
|
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.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)
|
"rpc.returndatalimit" = 100000 # Maximum size (in bytes) a result of an rpc request could have (default=100000, use 0 for no limits)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ The ```bor server``` command runs the Bor client.
|
||||||
|
|
||||||
- ```datadir.ancient```: Data directory for ancient chain segments (default = inside chaindata)
|
- ```datadir.ancient```: Data directory for ancient chain segments (default = inside chaindata)
|
||||||
|
|
||||||
|
- ```db.engine```: Backing database implementation to use ('leveldb' or 'pebble') (default: leveldb)
|
||||||
|
|
||||||
- ```keystore```: Path of the directory where keystores are located
|
- ```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.batchlimit```: Maximum number of messages in a batch (default=100, use 0 for no limits) (default: 100)
|
||||||
|
|
|
||||||
26
eth/api.go
26
eth/api.go
|
|
@ -17,6 +17,8 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
)
|
)
|
||||||
|
|
@ -50,3 +52,27 @@ func (api *EthereumAPI) Hashrate() hexutil.Uint64 {
|
||||||
func (api *EthereumAPI) Mining() bool {
|
func (api *EthereumAPI) Mining() bool {
|
||||||
return api.e.IsMining()
|
return api.e.IsMining()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getFinalizedBlockNumber(eth *Ethereum) (uint64, error) {
|
||||||
|
currentBlockNum := eth.BlockChain().CurrentBlock()
|
||||||
|
|
||||||
|
doExist, number, hash := eth.Downloader().GetWhitelistedMilestone()
|
||||||
|
if doExist && number <= currentBlockNum.Number.Uint64() {
|
||||||
|
block := eth.BlockChain().GetBlockByNumber(number)
|
||||||
|
|
||||||
|
if block.Hash() == hash {
|
||||||
|
return number, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doExist, number, hash = eth.Downloader().GetWhitelistedCheckpoint()
|
||||||
|
if doExist && number <= currentBlockNum.Number.Uint64() {
|
||||||
|
block := eth.BlockChain().GetBlockByNumber(number)
|
||||||
|
|
||||||
|
if block.Hash() == hash {
|
||||||
|
return number, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, fmt.Errorf("No finalized block")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,14 +79,15 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
|
||||||
}
|
}
|
||||||
|
|
||||||
if number == rpc.FinalizedBlockNumber {
|
if number == rpc.FinalizedBlockNumber {
|
||||||
if !b.eth.Merger().TDDReached() {
|
finalBlockNumber, err := getFinalizedBlockNumber(b.eth)
|
||||||
return nil, errors.New("'finalized' tag not supported on pre-merge network")
|
if err != nil {
|
||||||
|
return nil, errors.New("finalized block not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
block := b.eth.blockchain.CurrentFinalBlock()
|
block := b.eth.blockchain.CurrentFinalizedBlock(finalBlockNumber)
|
||||||
|
|
||||||
if block != nil {
|
if block != nil {
|
||||||
return block, nil
|
return block.Header(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("finalized block not found")
|
return nil, errors.New("finalized block not found")
|
||||||
|
|
@ -150,9 +151,11 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe
|
||||||
}
|
}
|
||||||
|
|
||||||
if number == rpc.FinalizedBlockNumber {
|
if number == rpc.FinalizedBlockNumber {
|
||||||
if !b.eth.Merger().TDDReached() {
|
// TODO - Arpit
|
||||||
return nil, errors.New("'finalized' tag not supported on pre-merge network")
|
// finalBlocknumber, err := getFinalizedBlockNumber(b.eth)
|
||||||
}
|
// if err != nil {
|
||||||
|
// return nil, errors.New("finalized block not found")
|
||||||
|
// }
|
||||||
|
|
||||||
header := b.eth.blockchain.CurrentFinalBlock()
|
header := b.eth.blockchain.CurrentFinalBlock()
|
||||||
if header == nil {
|
if header == nil {
|
||||||
|
|
@ -366,7 +369,9 @@ func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) Stats() (runnable int, blocked int) {
|
func (b *EthAPIBackend) Stats() (runnable int, blocked int) {
|
||||||
return b.eth.txPool.Stats()
|
// TODO - Arpit
|
||||||
|
return 0, 0
|
||||||
|
// return b.eth.txPool.Stats()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
|
func (b *EthAPIBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
|
||||||
|
|
@ -468,10 +473,18 @@ func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Blo
|
||||||
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
|
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) GetCheckpointWhitelist() map[uint64]common.Hash {
|
func (b *EthAPIBackend) GetWhitelistedCheckpoint() (bool, uint64, common.Hash) {
|
||||||
return b.eth.Downloader().ChainValidator.GetCheckpointWhitelist()
|
return b.eth.Downloader().ChainValidator.GetWhitelistedCheckpoint()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) PurgeCheckpointWhitelist() {
|
func (b *EthAPIBackend) PurgeWhitelistedCheckpoint() {
|
||||||
b.eth.Downloader().ChainValidator.PurgeCheckpointWhitelist()
|
b.eth.Downloader().ChainValidator.PurgeWhitelistedCheckpoint()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *EthAPIBackend) GetWhitelistedMilestone() (bool, uint64, common.Hash) {
|
||||||
|
return b.eth.Downloader().ChainValidator.GetWhitelistedMilestone()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *EthAPIBackend) PurgeWhitelistedMilestone() {
|
||||||
|
b.eth.Downloader().ChainValidator.PurgeWhitelistedMilestone()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
180
eth/backend.go
180
eth/backend.go
|
|
@ -241,7 +241,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
checker := whitelist.NewService(10)
|
checker := whitelist.NewService(chainDb)
|
||||||
|
|
||||||
// check if Parallel EVM is enabled
|
// check if Parallel EVM is enabled
|
||||||
// if enabled, use parallel state processor
|
// if enabled, use parallel state processor
|
||||||
|
|
@ -355,6 +355,10 @@ func makeExtraData(extra []byte) []byte {
|
||||||
return extra
|
return extra
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) PeerCount() int {
|
||||||
|
return s.p2pServer.PeerCount()
|
||||||
|
}
|
||||||
|
|
||||||
// APIs return the collection of RPC services the ethereum package offers.
|
// APIs return the collection of RPC services the ethereum package offers.
|
||||||
// NOTE, some of these services probably need to be moved to somewhere else.
|
// NOTE, some of these services probably need to be moved to somewhere else.
|
||||||
func (s *Ethereum) APIs() []rpc.API {
|
func (s *Ethereum) APIs() []rpc.API {
|
||||||
|
|
@ -554,7 +558,8 @@ func (s *Ethereum) StopMining() {
|
||||||
th.SetThreads(-1)
|
th.SetThreads(-1)
|
||||||
}
|
}
|
||||||
// Stop the block creating itself
|
// Stop the block creating itself
|
||||||
s.miner.Stop()
|
ch := make(chan struct{})
|
||||||
|
s.miner.Stop(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
|
func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
|
||||||
|
|
@ -623,6 +628,9 @@ func (s *Ethereum) Start() error {
|
||||||
s.handler.Start(maxPeers)
|
s.handler.Start(maxPeers)
|
||||||
|
|
||||||
go s.startCheckpointWhitelistService()
|
go s.startCheckpointWhitelistService()
|
||||||
|
go s.startMilestoneWhitelistService()
|
||||||
|
go s.startNoAckMilestoneService()
|
||||||
|
go s.startNoAckMilestoneByIDService()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -630,83 +638,183 @@ func (s *Ethereum) Start() error {
|
||||||
var (
|
var (
|
||||||
ErrNotBorConsensus = errors.New("not bor consensus was given")
|
ErrNotBorConsensus = errors.New("not bor consensus was given")
|
||||||
ErrBorConsensusWithoutHeimdall = errors.New("bor consensus without heimdall")
|
ErrBorConsensusWithoutHeimdall = errors.New("bor consensus without heimdall")
|
||||||
|
)
|
||||||
|
|
||||||
whitelistTimeout = 30 * time.Second
|
const (
|
||||||
|
whitelistTimeout = 30 * time.Second
|
||||||
|
noAckMilestoneTimeout = 4 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartCheckpointWhitelistService starts the goroutine to fetch checkpoints and update the
|
// StartCheckpointWhitelistService starts the goroutine to fetch checkpoints and update the
|
||||||
// checkpoint whitelist map.
|
// checkpoint whitelist map.
|
||||||
func (s *Ethereum) startCheckpointWhitelistService() {
|
func (s *Ethereum) startCheckpointWhitelistService() {
|
||||||
|
const (
|
||||||
|
tickerDuration = 100 * time.Second
|
||||||
|
fnName = "whitelist checkpoint"
|
||||||
|
)
|
||||||
|
|
||||||
|
s.retryHeimdallHandler(s.handleWhitelistCheckpoint, tickerDuration, whitelistTimeout, fnName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// startMilestoneWhitelistService starts the goroutine to fetch milestiones and update the
|
||||||
|
// milestone whitelist map.
|
||||||
|
func (s *Ethereum) startMilestoneWhitelistService() {
|
||||||
|
const (
|
||||||
|
tickerDuration = 12 * time.Second
|
||||||
|
fnName = "whitelist milestone"
|
||||||
|
)
|
||||||
|
|
||||||
|
s.retryHeimdallHandler(s.handleMilestone, tickerDuration, whitelistTimeout, fnName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) startNoAckMilestoneService() {
|
||||||
|
const (
|
||||||
|
tickerDuration = 6 * time.Second
|
||||||
|
fnName = "no-ack-milestone service"
|
||||||
|
)
|
||||||
|
|
||||||
|
s.retryHeimdallHandler(s.handleNoAckMilestone, tickerDuration, noAckMilestoneTimeout, fnName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) startNoAckMilestoneByIDService() {
|
||||||
|
const (
|
||||||
|
tickerDuration = 1 * time.Minute
|
||||||
|
fnName = "no-ack-milestone-by-id service"
|
||||||
|
)
|
||||||
|
|
||||||
|
s.retryHeimdallHandler(s.handleNoAckMilestoneByID, tickerDuration, noAckMilestoneTimeout, fnName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) retryHeimdallHandler(fn heimdallHandler, tickerDuration time.Duration, timeout time.Duration, fnName string) {
|
||||||
|
retryHeimdallHandler(fn, tickerDuration, timeout, fnName, s.closeCh, s.getHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func retryHeimdallHandler(fn heimdallHandler, tickerDuration time.Duration, timeout time.Duration, fnName string, closeCh chan struct{}, getHandler func() (*ethHandler, *bor.Bor, error)) {
|
||||||
// a shortcut helps with tests and early exit
|
// a shortcut helps with tests and early exit
|
||||||
select {
|
select {
|
||||||
case <-s.closeCh:
|
case <-closeCh:
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
// first run the checkpoint whitelist
|
ethHandler, bor, err := getHandler()
|
||||||
firstCtx, cancel := context.WithTimeout(context.Background(), whitelistTimeout)
|
if err != nil {
|
||||||
err := s.handleWhitelistCheckpoint(firstCtx, true)
|
log.Error("error while getting the ethHandler", "err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// first run for fetching milestones
|
||||||
|
firstCtx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
err = fn(firstCtx, ethHandler, bor)
|
||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrBorConsensusWithoutHeimdall) || errors.Is(err, ErrNotBorConsensus) {
|
log.Warn(fmt.Sprintf("unable to start the %s service - first run", fnName), "err", err)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Warn("unable to whitelist checkpoint - first run", "err", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(100 * time.Second)
|
ticker := time.NewTicker(tickerDuration)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), whitelistTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
err := s.handleWhitelistCheckpoint(ctx, false)
|
err := fn(ctx, ethHandler, bor)
|
||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("unable to whitelist checkpoint", "err", err)
|
log.Warn(fmt.Sprintf("unable to handle %s", fnName), "err", err)
|
||||||
}
|
}
|
||||||
case <-s.closeCh:
|
case <-closeCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleWhitelistCheckpoint handles the checkpoint whitelist mechanism.
|
// handleWhitelistCheckpoint handles the checkpoint whitelist mechanism.
|
||||||
func (s *Ethereum) handleWhitelistCheckpoint(ctx context.Context, first bool) error {
|
func (s *Ethereum) handleWhitelistCheckpoint(ctx context.Context, ethHandler *ethHandler, bor *bor.Bor) error {
|
||||||
|
// Create a new bor verifier, which will be used to verify checkpoints and milestones
|
||||||
|
verifier := newBorVerifier()
|
||||||
|
|
||||||
|
blockNum, blockHash, err := ethHandler.fetchWhitelistCheckpoint(ctx, bor, s, verifier)
|
||||||
|
// If the array is empty, we're bound to receive an error. Non-nill error and non-empty array
|
||||||
|
// means that array has partial elements and it failed for some block. We'll add those partial
|
||||||
|
// elements anyway.
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ethHandler.downloader.ProcessCheckpoint(blockNum, blockHash)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type heimdallHandler func(ctx context.Context, ethHandler *ethHandler, bor *bor.Bor) error
|
||||||
|
|
||||||
|
// handleMilestone handles the milestone mechanism.
|
||||||
|
func (s *Ethereum) handleMilestone(ctx context.Context, ethHandler *ethHandler, bor *bor.Bor) error {
|
||||||
|
// Create a new bor verifier, which will be used to verify checkpoints and milestones
|
||||||
|
verifier := newBorVerifier()
|
||||||
|
num, hash, err := ethHandler.fetchWhitelistMilestone(ctx, bor, s, verifier)
|
||||||
|
|
||||||
|
// If the current chain head is behind the received milestone, add it to the future milestone
|
||||||
|
// list. Also, the hash mismatch (end block hash) error will lead to rewind so also
|
||||||
|
// add that milestone to the future milestone list.
|
||||||
|
if errors.Is(err, errMissingBlocks) || errors.Is(err, errHashMismatch) {
|
||||||
|
ethHandler.downloader.ProcessFutureMilestone(num, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ethHandler.downloader.ProcessMilestone(num, hash)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) handleNoAckMilestone(ctx context.Context, ethHandler *ethHandler, bor *bor.Bor) error {
|
||||||
|
milestoneID, err := ethHandler.fetchNoAckMilestone(ctx, bor)
|
||||||
|
|
||||||
|
//If failed to fetch the no-ack milestone then it give the error.
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ethHandler.downloader.RemoveMilestoneID(milestoneID)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) handleNoAckMilestoneByID(ctx context.Context, ethHandler *ethHandler, bor *bor.Bor) error {
|
||||||
|
milestoneIDs := ethHandler.downloader.GetMilestoneIDsList()
|
||||||
|
|
||||||
|
for _, milestoneID := range milestoneIDs {
|
||||||
|
// todo: check if we can ignore the error
|
||||||
|
err := ethHandler.fetchNoAckMilestoneByID(ctx, bor, milestoneID)
|
||||||
|
if err == nil {
|
||||||
|
ethHandler.downloader.RemoveMilestoneID(milestoneID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) getHandler() (*ethHandler, *bor.Bor, error) {
|
||||||
ethHandler := (*ethHandler)(s.handler)
|
ethHandler := (*ethHandler)(s.handler)
|
||||||
|
|
||||||
bor, ok := ethHandler.chain.Engine().(*bor.Bor)
|
bor, ok := ethHandler.chain.Engine().(*bor.Bor)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ErrNotBorConsensus
|
return nil, nil, ErrNotBorConsensus
|
||||||
}
|
}
|
||||||
|
|
||||||
if bor.HeimdallClient == nil {
|
if bor.HeimdallClient == nil {
|
||||||
return ErrBorConsensusWithoutHeimdall
|
return nil, nil, ErrBorConsensusWithoutHeimdall
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new checkpoint verifier
|
return ethHandler, bor, nil
|
||||||
verifier := newCheckpointVerifier(nil)
|
|
||||||
blockNums, blockHashes, err := ethHandler.fetchWhitelistCheckpoints(ctx, bor, verifier, first)
|
|
||||||
// If the array is empty, we're bound to receive an error. Non-nill error and non-empty array
|
|
||||||
// means that array has partial elements and it failed for some block. We'll add those partial
|
|
||||||
// elements anyway.
|
|
||||||
if len(blockNums) == 0 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the checkpoint whitelist map.
|
|
||||||
for i := 0; i < len(blockNums); i++ {
|
|
||||||
ethHandler.downloader.ProcessCheckpoint(blockNums[i], blockHashes[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop implements node.Lifecycle, terminating all internal goroutines used by the
|
// Stop implements node.Lifecycle, terminating all internal goroutines used by the
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package eth
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -11,8 +12,11 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errBorEngineNotAvailable error = errors.New("Only available in Bor engine")
|
||||||
|
|
||||||
// GetRootHash returns root hash for given start and end block
|
// GetRootHash returns root hash for given start and end block
|
||||||
func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
||||||
var api *bor.API
|
var api *bor.API
|
||||||
|
|
@ -24,7 +28,7 @@ func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
|
||||||
}
|
}
|
||||||
|
|
||||||
if api == nil {
|
if api == nil {
|
||||||
return "", errors.New("Only available in Bor engine")
|
return "", errBorEngineNotAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
root, err := api.GetRootHash(starBlockNr, endBlockNr)
|
root, err := api.GetRootHash(starBlockNr, endBlockNr)
|
||||||
|
|
@ -35,6 +39,70 @@ func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
|
||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRootHash returns root hash for given start and end block
|
||||||
|
func (b *EthAPIBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
|
||||||
|
var api *bor.API
|
||||||
|
|
||||||
|
for _, _api := range b.eth.Engine().APIs(b.eth.BlockChain()) {
|
||||||
|
if _api.Namespace == "bor" {
|
||||||
|
api = _api.Service.(*bor.API)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if api == nil {
|
||||||
|
return false, errBorEngineNotAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
//Confirmation of 16 blocks on the endblock
|
||||||
|
tipConfirmationBlockNr := endBlockNr + uint64(16)
|
||||||
|
|
||||||
|
//Check if tipConfirmation block exit
|
||||||
|
_, err := b.BlockByNumber(ctx, rpc.BlockNumber(tipConfirmationBlockNr))
|
||||||
|
if err != nil {
|
||||||
|
return false, errTipConfirmationBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if end block exist
|
||||||
|
localEndBlock, err := b.BlockByNumber(ctx, rpc.BlockNumber(endBlockNr))
|
||||||
|
if err != nil {
|
||||||
|
return false, errEndBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
localEndBlockHash := localEndBlock.Hash().String()
|
||||||
|
|
||||||
|
downloader := b.eth.handler.downloader
|
||||||
|
isLocked := downloader.LockMutex(endBlockNr)
|
||||||
|
|
||||||
|
if !isLocked {
|
||||||
|
downloader.UnlockMutex(false, "", endBlockNr, common.Hash{})
|
||||||
|
return false, errors.New("Whitelisted number or locked sprint number is more than the received end block number")
|
||||||
|
}
|
||||||
|
|
||||||
|
if localEndBlockHash != hash {
|
||||||
|
downloader.UnlockMutex(false, "", endBlockNr, common.Hash{})
|
||||||
|
return false, fmt.Errorf("Hash mismatch: localChainHash %s, milestoneHash %s", localEndBlockHash, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
ethHandler := (*ethHandler)(b.eth.handler)
|
||||||
|
|
||||||
|
bor, ok := ethHandler.chain.Engine().(*bor.Bor)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return false, fmt.Errorf("Bor not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bor.HeimdallClient.FetchMilestoneID(ctx, milestoneId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
downloader.UnlockMutex(false, "", endBlockNr, common.Hash{})
|
||||||
|
return false, fmt.Errorf("Milestone ID doesn't exist in Heimdall")
|
||||||
|
}
|
||||||
|
|
||||||
|
downloader.UnlockMutex(true, milestoneId, endBlockNr, localEndBlock.Hash())
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetBorBlockReceipt returns bor block receipt
|
// GetBorBlockReceipt returns bor block receipt
|
||||||
func (b *EthAPIBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
func (b *EthAPIBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
receipt := b.eth.blockchain.GetBorReceiptByHash(hash)
|
receipt := b.eth.blockchain.GetBorReceiptByHash(hash)
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,171 @@
|
||||||
|
// nolint
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type checkpointVerifier struct {
|
var (
|
||||||
verify func(ctx context.Context, handler *ethHandler, checkpoint *checkpoint.Checkpoint) (string, error)
|
// errMissingBlocks is returned when we don't have the blocks locally, yet.
|
||||||
|
errMissingBlocks = errors.New("missing blocks")
|
||||||
|
|
||||||
|
// errRootHash is returned when we aren't able to calculate the root hash
|
||||||
|
// locally for a range of blocks.
|
||||||
|
errRootHash = errors.New("failed to get local root hash")
|
||||||
|
|
||||||
|
// errHashMismatch is returned when the local hash doesn't match
|
||||||
|
// with the hash of checkpoint/milestone. It is the root hash of blocks
|
||||||
|
// in case of checkpoint and is end block hash in case of milestones.
|
||||||
|
errHashMismatch = errors.New("hash mismatch")
|
||||||
|
|
||||||
|
// errEndBlock is returned when we're unable to fetch a block locally.
|
||||||
|
errEndBlock = errors.New("failed to get end block")
|
||||||
|
|
||||||
|
// errEndBlock is returned when we're unable to fetch a block locally.
|
||||||
|
errTipConfirmationBlock = errors.New("failed to get tip confirmation block")
|
||||||
|
|
||||||
|
// errBlockNumberConversion is returned when we get err in parsing hexautil block number
|
||||||
|
errBlockNumberConversion = errors.New("failed to parse the block number")
|
||||||
|
|
||||||
|
//Metrics for collecting the rewindLength
|
||||||
|
rewindLengthMeter = metrics.NewRegisteredMeter("chain/autorewind/length", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
type borVerifier struct {
|
||||||
|
verify func(ctx context.Context, eth *Ethereum, handler *ethHandler, start uint64, end uint64, hash string, isCheckpoint bool) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCheckpointVerifier(verifyFn func(ctx context.Context, handler *ethHandler, checkpoint *checkpoint.Checkpoint) (string, error)) *checkpointVerifier {
|
func newBorVerifier() *borVerifier {
|
||||||
if verifyFn != nil {
|
return &borVerifier{borVerify}
|
||||||
return &checkpointVerifier{verifyFn}
|
}
|
||||||
|
|
||||||
|
func borVerify(ctx context.Context, eth *Ethereum, handler *ethHandler, start uint64, end uint64, hash string, isCheckpoint bool) (string, error) {
|
||||||
|
str := "milestone"
|
||||||
|
if isCheckpoint {
|
||||||
|
str = "checkpoint"
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyFn = func(ctx context.Context, handler *ethHandler, checkpoint *checkpoint.Checkpoint) (string, error) {
|
// check if we have the given blocks
|
||||||
|
currentBlock := eth.BlockChain().CurrentBlock()
|
||||||
|
if currentBlock == nil {
|
||||||
|
log.Debug(fmt.Sprintf("Failed to fetch current block from blockchain while verifying incoming %s", str))
|
||||||
|
return hash, errMissingBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
head := currentBlock.Number.Uint64()
|
||||||
|
|
||||||
|
if head < end {
|
||||||
|
log.Debug(fmt.Sprintf("Current head block behind incoming %s block", str), "head", head, "end block", end)
|
||||||
|
return hash, errMissingBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
var localHash string
|
||||||
|
|
||||||
|
// verify the hash
|
||||||
|
if isCheckpoint {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// in case of checkpoint get the rootHash
|
||||||
|
localHash, err = handler.ethAPI.GetRootHash(ctx, start, end)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to get root hash of given block range while whitelisting checkpoint", "start", start, "end", end, "err", err)
|
||||||
|
return hash, errRootHash
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// in case of milestone(isCheckpoint==false) get the hash of endBlock
|
||||||
|
block, err := handler.ethAPI.GetBlockByNumber(ctx, rpc.BlockNumber(end), false)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to get end block hash while whitelisting milestone", "number", end, "err", err)
|
||||||
|
return hash, errEndBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
localHash = fmt.Sprintf("%v", block["hash"])[2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint
|
||||||
|
if localHash != hash {
|
||||||
|
|
||||||
|
if isCheckpoint {
|
||||||
|
log.Warn("Root hash mismatch while whitelisting checkpoint", "expected", localHash, "got", hash)
|
||||||
|
} else {
|
||||||
|
log.Warn("End block hash mismatch while whitelisting milestone", "expected", localHash, "got", hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
ethHandler := (*ethHandler)(eth.handler)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
startBlock = checkpoint.StartBlock.Uint64()
|
rewindTo uint64
|
||||||
endBlock = checkpoint.EndBlock.Uint64()
|
doExist bool
|
||||||
)
|
)
|
||||||
|
|
||||||
// check if we have the checkpoint blocks
|
if doExist, rewindTo, _ = ethHandler.downloader.GetWhitelistedMilestone(); doExist {
|
||||||
//nolint:contextcheck
|
|
||||||
head := handler.ethAPI.BlockNumber()
|
} else if doExist, rewindTo, _ = ethHandler.downloader.GetWhitelistedCheckpoint(); doExist {
|
||||||
if head < hexutil.Uint64(endBlock) {
|
|
||||||
log.Debug("Head block behind checkpoint block", "head", head, "checkpoint end block", endBlock)
|
} else {
|
||||||
return "", errMissingCheckpoint
|
if start <= 0 {
|
||||||
|
rewindTo = 0
|
||||||
|
} else {
|
||||||
|
rewindTo = start - 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify the root hash of checkpoint
|
if head-rewindTo > 255 {
|
||||||
roothash, err := handler.ethAPI.GetRootHash(ctx, startBlock, endBlock)
|
rewindTo = head - 255
|
||||||
if err != nil {
|
|
||||||
log.Debug("Failed to get root hash of checkpoint while whitelisting", "err", err)
|
|
||||||
return "", errRootHash
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if roothash != checkpoint.RootHash.String()[2:] {
|
if isCheckpoint {
|
||||||
log.Warn("Checkpoint root hash mismatch while whitelisting", "expected", checkpoint.RootHash.String()[2:], "got", roothash)
|
log.Warn("Rewinding chain due to checkpoint root hash mismatch", "number", rewindTo)
|
||||||
return "", errCheckpointRootHashMismatch
|
} else {
|
||||||
|
log.Warn("Rewinding chain due to milestone endblock hash mismatch", "number", rewindTo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch the end checkpoint block hash
|
rewindBack(eth, head, rewindTo)
|
||||||
block, err := handler.ethAPI.GetBlockByNumber(ctx, rpc.BlockNumber(endBlock), false)
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("Failed to get end block hash of checkpoint while whitelisting", "err", err)
|
|
||||||
return "", errEndBlock
|
|
||||||
}
|
|
||||||
|
|
||||||
hash := fmt.Sprintf("%v", block["hash"])
|
return hash, errHashMismatch
|
||||||
|
}
|
||||||
return hash, nil
|
|
||||||
|
// fetch the end block hash
|
||||||
|
block, err := handler.ethAPI.GetBlockByNumber(ctx, rpc.BlockNumber(end), false)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to get end block hash while whitelisting", "err", err)
|
||||||
|
return hash, errEndBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
hash = fmt.Sprintf("%v", block["hash"])
|
||||||
|
|
||||||
|
return hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the miner if the mining process is running and rewind back the chain
|
||||||
|
func rewindBack(eth *Ethereum, head uint64, rewindTo uint64) {
|
||||||
|
if eth.Miner().Mining() {
|
||||||
|
ch := make(chan struct{})
|
||||||
|
eth.Miner().Stop(ch)
|
||||||
|
|
||||||
|
<-ch
|
||||||
|
rewind(eth, head, rewindTo)
|
||||||
|
|
||||||
|
eth.Miner().Start()
|
||||||
|
} else {
|
||||||
|
rewind(eth, head, rewindTo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rewind(eth *Ethereum, head uint64, rewindTo uint64) {
|
||||||
|
err := eth.blockchain.SetHead(rewindTo)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error while rewinding the chain", "to", rewindTo, "err", err)
|
||||||
|
} else {
|
||||||
|
rewindLengthMeter.Mark(int64(head - rewindTo))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &checkpointVerifier{verifyFn}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,8 @@ type BlockChain interface {
|
||||||
// Snapshots returns the blockchain snapshot tree to paused it during sync.
|
// Snapshots returns the blockchain snapshot tree to paused it during sync.
|
||||||
Snapshots() *snapshot.Tree
|
Snapshots() *snapshot.Tree
|
||||||
|
|
||||||
|
GetChainConfig() *params.ChainConfig
|
||||||
|
|
||||||
// TrieDB retrieves the low level trie database used for interacting
|
// TrieDB retrieves the low level trie database used for interacting
|
||||||
// with trie nodes.
|
// with trie nodes.
|
||||||
TrieDB() *trie.Database
|
TrieDB() *trie.Database
|
||||||
|
|
@ -363,8 +365,7 @@ func (d *Downloader) LegacySync(id string, head common.Hash, td, ttd *big.Int, m
|
||||||
|
|
||||||
if errors.Is(err, errInvalidChain) || errors.Is(err, errBadPeer) || errors.Is(err, errTimeout) ||
|
if errors.Is(err, errInvalidChain) || errors.Is(err, errBadPeer) || errors.Is(err, errTimeout) ||
|
||||||
errors.Is(err, errStallingPeer) || errors.Is(err, errUnsyncedPeer) || errors.Is(err, errEmptyHeaderSet) ||
|
errors.Is(err, errStallingPeer) || errors.Is(err, errUnsyncedPeer) || errors.Is(err, errEmptyHeaderSet) ||
|
||||||
errors.Is(err, errPeersUnavailable) || errors.Is(err, errTooOld) || errors.Is(err, errInvalidAncestor) ||
|
errors.Is(err, errPeersUnavailable) || errors.Is(err, errTooOld) || errors.Is(err, errInvalidAncestor) {
|
||||||
errors.Is(err, whitelist.ErrCheckpointMismatch) {
|
|
||||||
log.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err)
|
log.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err)
|
||||||
|
|
||||||
if d.dropPeer == nil {
|
if d.dropPeer == nil {
|
||||||
|
|
@ -382,7 +383,13 @@ func (d *Downloader) LegacySync(id string, head common.Hash, td, ttd *big.Int, m
|
||||||
return err // This is an expected fault, don't keep printing it in a spin-loop
|
return err // This is an expected fault, don't keep printing it in a spin-loop
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Warn("Synchronisation failed, retrying", "err", err)
|
// Warn in case of any error thrown by whitelisting module
|
||||||
|
if errors.Is(err, whitelist.ErrNoRemote) || errors.Is(err, whitelist.ErrMismatch) {
|
||||||
|
log.Warn("Synchronisation failed due to whitelist validation", "peer", id, "err", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warn("Synchronisation failed, retrying", "peer", id, "err", err)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -887,9 +894,10 @@ func (d *Downloader) getFetchHeadersByNumber(p *peerConnection) func(number uint
|
||||||
// In the rare scenario when we ended up on a long reorganisation (i.e. none of
|
// In the rare scenario when we ended up on a long reorganisation (i.e. none of
|
||||||
// the head links match), we do a binary search to find the common ancestor.
|
// the head links match), we do a binary search to find the common ancestor.
|
||||||
func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) (uint64, error) {
|
func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) (uint64, error) {
|
||||||
|
|
||||||
// Check the validity of peer from which the chain is to be downloaded
|
// Check the validity of peer from which the chain is to be downloaded
|
||||||
if d.ChainValidator != nil {
|
if d.ChainValidator != nil {
|
||||||
if _, err := d.IsValidPeer(remoteHeader, d.getFetchHeadersByNumber(p)); err != nil {
|
if _, err := d.IsValidPeer(d.getFetchHeadersByNumber(p)); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1968,6 +1976,11 @@ func (d *Downloader) DeliverSnapPacket(peer *snap.Peer, packet snap.Packet) erro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetWhitelistService returns the pointer to the whitelist service
|
||||||
|
func (d *Downloader) GetWhitelistService() ethereum.ChainValidator {
|
||||||
|
return d.ChainValidator
|
||||||
|
}
|
||||||
|
|
||||||
// readHeaderRange returns a list of headers, using the given last header as the base,
|
// readHeaderRange returns a list of headers, using the given last header as the base,
|
||||||
// and going backwards towards genesis. This method assumes that the caller already has
|
// and going backwards towards genesis. This method assumes that the caller already has
|
||||||
// placed a reasonable cap on count.
|
// placed a reasonable cap on count.
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint: staticcheck
|
//nolint: staticcheck
|
||||||
tester.downloader = New(db, new(event.TypeMux), tester.chain, nil, tester.dropPeer, success, whitelist.NewService(10))
|
tester.downloader = New(0, db, new(event.TypeMux), tester.chain, nil, tester.dropPeer, success, whitelist.NewService(db))
|
||||||
|
|
||||||
return tester
|
return tester
|
||||||
}
|
}
|
||||||
|
|
@ -1904,7 +1904,7 @@ func newWhitelistFake(validate func(count int) (bool, error)) *whitelistFake {
|
||||||
|
|
||||||
// IsValidPeer is the mock function which the downloader will use to validate the chain
|
// IsValidPeer is the mock function which the downloader will use to validate the chain
|
||||||
// to be received from a peer.
|
// to be received from a peer.
|
||||||
func (w *whitelistFake) IsValidPeer(_ *types.Header, _ func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
func (w *whitelistFake) IsValidPeer(_ func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
w.count++
|
w.count++
|
||||||
}()
|
}()
|
||||||
|
|
@ -1917,13 +1917,33 @@ func (w *whitelistFake) IsValidChain(current *types.Header, headers []*types.Hea
|
||||||
}
|
}
|
||||||
func (w *whitelistFake) ProcessCheckpoint(_ uint64, _ common.Hash) {}
|
func (w *whitelistFake) ProcessCheckpoint(_ uint64, _ common.Hash) {}
|
||||||
|
|
||||||
func (w *whitelistFake) GetCheckpointWhitelist() map[uint64]common.Hash {
|
func (w *whitelistFake) GetWhitelistedCheckpoint() (bool, uint64, common.Hash) {
|
||||||
return nil
|
return false, 0, common.Hash{}
|
||||||
}
|
}
|
||||||
func (w *whitelistFake) PurgeCheckpointWhitelist() {}
|
func (w *whitelistFake) PurgeWhitelistedCheckpoint() {}
|
||||||
|
|
||||||
|
func (w *whitelistFake) ProcessMilestone(_ uint64, _ common.Hash) {}
|
||||||
|
func (w *whitelistFake) ProcessFutureMilestone(_ uint64, _ common.Hash) {}
|
||||||
|
func (w *whitelistFake) GetWhitelistedMilestone() (bool, uint64, common.Hash) {
|
||||||
|
return false, 0, common.Hash{}
|
||||||
|
}
|
||||||
|
func (w *whitelistFake) PurgeWhitelistedMilestone() {}
|
||||||
|
|
||||||
func (w *whitelistFake) GetCheckpoints(current, sidechainHeader *types.Header, sidechainCheckpoints []*types.Header) (map[uint64]*types.Header, error) {
|
func (w *whitelistFake) GetCheckpoints(current, sidechainHeader *types.Header, sidechainCheckpoints []*types.Header) (map[uint64]*types.Header, error) {
|
||||||
return map[uint64]*types.Header{}, nil
|
return map[uint64]*types.Header{}, nil
|
||||||
}
|
}
|
||||||
|
func (w *whitelistFake) LockMutex(endBlockNum uint64) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (w *whitelistFake) UnlockMutex(doLock bool, milestoneId string, endBlockNum uint64, endBlockHash common.Hash) {
|
||||||
|
}
|
||||||
|
func (w *whitelistFake) UnlockSprint(endBlockNum uint64) {
|
||||||
|
}
|
||||||
|
func (w *whitelistFake) RemoveMilestoneID(milestoneId string) {
|
||||||
|
}
|
||||||
|
func (w *whitelistFake) GetMilestoneIDsList() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// TestFakedSyncProgress66WhitelistMismatch tests if in case of whitelisted
|
// TestFakedSyncProgress66WhitelistMismatch tests if in case of whitelisted
|
||||||
// checkpoint mismatch with opposite peer, the sync should fail.
|
// checkpoint mismatch with opposite peer, the sync should fail.
|
||||||
|
|
@ -1935,7 +1955,7 @@ func TestFakedSyncProgress66WhitelistMismatch(t *testing.T) {
|
||||||
|
|
||||||
tester := newTester(t)
|
tester := newTester(t)
|
||||||
validate := func(count int) (bool, error) {
|
validate := func(count int) (bool, error) {
|
||||||
return false, whitelist.ErrCheckpointMismatch
|
return false, whitelist.ErrMismatch
|
||||||
}
|
}
|
||||||
tester.downloader.ChainValidator = newWhitelistFake(validate)
|
tester.downloader.ChainValidator = newWhitelistFake(validate)
|
||||||
|
|
||||||
|
|
@ -1988,7 +2008,7 @@ func TestFakedSyncProgress66NoRemoteCheckpoint(t *testing.T) {
|
||||||
validate := func(count int) (bool, error) {
|
validate := func(count int) (bool, error) {
|
||||||
// only return the `ErrNoRemoteCheckpoint` error for the first call
|
// only return the `ErrNoRemoteCheckpoint` error for the first call
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return false, whitelist.ErrNoRemoteCheckpoint
|
return false, whitelist.ErrNoRemote
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
@ -2004,7 +2024,7 @@ func TestFakedSyncProgress66NoRemoteCheckpoint(t *testing.T) {
|
||||||
// Synchronise with the peer and make sure all blocks were retrieved
|
// Synchronise with the peer and make sure all blocks were retrieved
|
||||||
// Should fail in first attempt
|
// Should fail in first attempt
|
||||||
if err := tester.sync("light", nil, mode); err != nil {
|
if err := tester.sync("light", nil, mode); err != nil {
|
||||||
assert.Equal(t, whitelist.ErrNoRemoteCheckpoint, err, "failed synchronisation")
|
assert.Equal(t, whitelist.ErrNoRemote, err, "failed synchronisation")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try syncing again, should succeed
|
// Try syncing again, should succeed
|
||||||
|
|
|
||||||
67
eth/downloader/whitelist/checkpoint.go
Normal file
67
eth/downloader/whitelist/checkpoint.go
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
package whitelist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
type checkpoint struct {
|
||||||
|
finality[*rawdb.Checkpoint]
|
||||||
|
}
|
||||||
|
|
||||||
|
type checkpointService interface {
|
||||||
|
finalityService
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
//Metrics for collecting the whitelisted milestone number
|
||||||
|
whitelistedCheckpointNumberMeter = metrics.NewRegisteredGauge("chain/checkpoint/latest", nil)
|
||||||
|
|
||||||
|
//Metrics for collecting the number of invalid chains received
|
||||||
|
CheckpointChainMeter = metrics.NewRegisteredMeter("chain/checkpoint/isvalidchain", nil)
|
||||||
|
|
||||||
|
//Metrics for collecting the number of valid peers received
|
||||||
|
CheckpointPeerMeter = metrics.NewRegisteredMeter("chain/checkpoint/isvalidpeer", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsValidChain checks the validity of chain by comparing it
|
||||||
|
// against the local checkpoint entry
|
||||||
|
func (w *checkpoint) IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error) {
|
||||||
|
w.finality.RLock()
|
||||||
|
defer w.finality.RUnlock()
|
||||||
|
|
||||||
|
res, err := w.finality.IsValidChain(currentHeader, chain)
|
||||||
|
|
||||||
|
if res {
|
||||||
|
CheckpointChainMeter.Mark(int64(1))
|
||||||
|
} else {
|
||||||
|
CheckpointPeerMeter.Mark(int64(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidPeer checks if the chain we're about to receive from a peer is valid or not
|
||||||
|
// in terms of reorgs. We won't reorg beyond the last bor finality submitted to mainchain.
|
||||||
|
func (w *checkpoint) IsValidPeer(fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
||||||
|
res, err := w.finality.IsValidPeer(fetchHeadersByNumber)
|
||||||
|
|
||||||
|
if res {
|
||||||
|
CheckpointPeerMeter.Mark(int64(1))
|
||||||
|
} else {
|
||||||
|
CheckpointPeerMeter.Mark(int64(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *checkpoint) Process(block uint64, hash common.Hash) {
|
||||||
|
w.finality.Lock()
|
||||||
|
defer w.finality.Unlock()
|
||||||
|
|
||||||
|
w.finality.Process(block, hash)
|
||||||
|
|
||||||
|
whitelistedCheckpointNumberMeter.Update(int64(block))
|
||||||
|
}
|
||||||
96
eth/downloader/whitelist/finality.go
Normal file
96
eth/downloader/whitelist/finality.go
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
package whitelist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type finality[T rawdb.BlockFinality[T]] struct {
|
||||||
|
sync.RWMutex
|
||||||
|
db ethdb.Database
|
||||||
|
Hash common.Hash // Whitelisted Hash, populated by reaching out to heimdall
|
||||||
|
Number uint64 // Number , populated by reaching out to heimdall
|
||||||
|
interval uint64 // Interval, until which we can allow importing
|
||||||
|
doExist bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type finalityService interface {
|
||||||
|
IsValidPeer(fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error)
|
||||||
|
IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error)
|
||||||
|
Get() (bool, uint64, common.Hash)
|
||||||
|
Process(block uint64, hash common.Hash)
|
||||||
|
Purge()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidPeer checks if the chain we're about to receive from a peer is valid or not
|
||||||
|
// in terms of reorgs. We won't reorg beyond the last bor finality submitted to mainchain.
|
||||||
|
func (f *finality[T]) IsValidPeer(fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
||||||
|
// We want to validate the chain by comparing the last finalized block
|
||||||
|
f.RLock()
|
||||||
|
|
||||||
|
doExist := f.doExist
|
||||||
|
number := f.Number
|
||||||
|
hash := f.Hash
|
||||||
|
|
||||||
|
f.RUnlock()
|
||||||
|
|
||||||
|
return isValidPeer(fetchHeadersByNumber, doExist, number, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidChain checks the validity of chain by comparing it
|
||||||
|
// against the local checkpoint entry
|
||||||
|
// todo: need changes
|
||||||
|
func (f *finality[T]) IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error) {
|
||||||
|
// Return if we've received empty chain
|
||||||
|
if len(chain) == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := isValidChain(currentHeader, chain, f.doExist, f.Number, f.Hash)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *finality[T]) Process(block uint64, hash common.Hash) {
|
||||||
|
f.doExist = true
|
||||||
|
f.Hash = hash
|
||||||
|
f.Number = block
|
||||||
|
|
||||||
|
err := rawdb.WriteLastFinality[T](f.db, block, hash)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error in writing whitelist state to db", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the existing whitelisted
|
||||||
|
// entries of checkpoint of the form (doExist,block number,block hash.)
|
||||||
|
func (f *finality[T]) Get() (bool, uint64, common.Hash) {
|
||||||
|
f.RLock()
|
||||||
|
defer f.RUnlock()
|
||||||
|
|
||||||
|
if f.doExist {
|
||||||
|
return f.doExist, f.Number, f.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
block, hash, err := rawdb.ReadFinality[T](f.db)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error while reading whitelisted state from Db", "err", err)
|
||||||
|
return false, f.Number, f.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, block, hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purge purges the whitlisted checkpoint
|
||||||
|
func (f *finality[T]) Purge() {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.doExist = false
|
||||||
|
}
|
||||||
315
eth/downloader/whitelist/milestone.go
Normal file
315
eth/downloader/whitelist/milestone.go
Normal file
|
|
@ -0,0 +1,315 @@
|
||||||
|
package whitelist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/flags"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
type milestone struct {
|
||||||
|
finality[*rawdb.Milestone]
|
||||||
|
|
||||||
|
LockedMilestoneNumber uint64 // Locked sprint number
|
||||||
|
LockedMilestoneHash common.Hash //Hash for the locked endBlock
|
||||||
|
Locked bool //
|
||||||
|
LockedMilestoneIDs map[string]struct{} //list of milestone ids
|
||||||
|
|
||||||
|
FutureMilestoneList map[uint64]common.Hash // Future Milestone list
|
||||||
|
FutureMilestoneOrder []uint64 // Future Milestone Order
|
||||||
|
MaxCapacity int //Capacity of future Milestone list
|
||||||
|
}
|
||||||
|
|
||||||
|
type milestoneService interface {
|
||||||
|
finalityService
|
||||||
|
|
||||||
|
GetMilestoneIDsList() []string
|
||||||
|
RemoveMilestoneID(milestoneId string)
|
||||||
|
LockMutex(endBlockNum uint64) bool
|
||||||
|
UnlockMutex(doLock bool, milestoneId string, endBlockNum uint64, endBlockHash common.Hash)
|
||||||
|
UnlockSprint(endBlockNum uint64)
|
||||||
|
ProcessFutureMilestone(num uint64, hash common.Hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
//Metrics for collecting the whitelisted milestone number
|
||||||
|
whitelistedMilestoneMeter = metrics.NewRegisteredGauge("chain/milestone/latest", nil)
|
||||||
|
|
||||||
|
//Metrics for collecting the future milestone number
|
||||||
|
FutureMilestoneMeter = metrics.NewRegisteredGauge("chain/milestone/future", nil)
|
||||||
|
|
||||||
|
//Metrics for collecting the length of the MilestoneIds map
|
||||||
|
MilestoneIdsLengthMeter = metrics.NewRegisteredGauge("chain/milestone/idslength", nil)
|
||||||
|
|
||||||
|
//Metrics for collecting the number of valid chains received
|
||||||
|
MilestoneChainMeter = metrics.NewRegisteredMeter("chain/milestone/isvalidchain", nil)
|
||||||
|
|
||||||
|
//Metrics for collecting the number of valid peers received
|
||||||
|
MilestonePeerMeter = metrics.NewRegisteredMeter("chain/milestone/isvalidpeer", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsValidChain checks the validity of chain by comparing it
|
||||||
|
// against the local milestone entries
|
||||||
|
func (m *milestone) IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error) {
|
||||||
|
//Checking for the milestone flag
|
||||||
|
if !flags.Milestone {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m.finality.RLock()
|
||||||
|
defer m.finality.RUnlock()
|
||||||
|
|
||||||
|
var isValid bool = false
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if isValid {
|
||||||
|
MilestoneChainMeter.Mark(int64(1))
|
||||||
|
} else {
|
||||||
|
MilestoneChainMeter.Mark(int64(-1))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
res, err := m.finality.IsValidChain(currentHeader, chain)
|
||||||
|
|
||||||
|
if !res {
|
||||||
|
isValid = false
|
||||||
|
return isValid, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Locked && !m.IsReorgAllowed(chain, m.LockedMilestoneNumber, m.LockedMilestoneHash) {
|
||||||
|
isValid = false
|
||||||
|
return isValid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !m.IsFutureMilestoneCompatible(chain) {
|
||||||
|
isValid = false
|
||||||
|
return isValid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid = true
|
||||||
|
|
||||||
|
return isValid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValidPeer checks if the chain we're about to receive from a peer is valid or not
|
||||||
|
// in terms of reorgs. We won't reorg beyond the last bor finality submitted to mainchain.
|
||||||
|
func (m *milestone) IsValidPeer(fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
||||||
|
if !flags.Milestone {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := m.finality.IsValidPeer(fetchHeadersByNumber)
|
||||||
|
|
||||||
|
if res {
|
||||||
|
MilestonePeerMeter.Mark(int64(1))
|
||||||
|
} else {
|
||||||
|
MilestonePeerMeter.Mark(int64(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *milestone) Process(block uint64, hash common.Hash) {
|
||||||
|
m.finality.Lock()
|
||||||
|
defer m.finality.Unlock()
|
||||||
|
|
||||||
|
m.finality.Process(block, hash)
|
||||||
|
|
||||||
|
for i := 0; i < len(m.FutureMilestoneOrder); i++ {
|
||||||
|
if m.FutureMilestoneOrder[i] <= block {
|
||||||
|
m.dequeueFutureMilestone()
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
whitelistedMilestoneMeter.Update(int64(block))
|
||||||
|
|
||||||
|
m.UnlockSprint(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will Lock the mutex at the time of voting
|
||||||
|
// fixme: get rid of it
|
||||||
|
func (m *milestone) LockMutex(endBlockNum uint64) bool {
|
||||||
|
m.finality.Lock()
|
||||||
|
|
||||||
|
if m.doExist && endBlockNum <= m.Number { //if endNum is less than whitelisted milestone, then we won't lock the sprint
|
||||||
|
log.Debug("endBlockNumber is less than or equal to latesMilestoneNumber", "endBlock Number", endBlockNum, "LatestMilestone Number", m.Number)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Locked && endBlockNum < m.LockedMilestoneNumber {
|
||||||
|
log.Debug("endBlockNum is less than locked milestone number", "endBlock Number", endBlockNum, "Locked Milestone Number", m.LockedMilestoneNumber)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will unlock the mutex locked in LockMutex
|
||||||
|
// fixme: get rid of it
|
||||||
|
func (m *milestone) UnlockMutex(doLock bool, milestoneId string, endBlockNum uint64, endBlockHash common.Hash) {
|
||||||
|
m.Locked = m.Locked || doLock
|
||||||
|
|
||||||
|
if doLock {
|
||||||
|
m.UnlockSprint(m.LockedMilestoneNumber)
|
||||||
|
m.Locked = true
|
||||||
|
m.LockedMilestoneHash = endBlockHash
|
||||||
|
m.LockedMilestoneNumber = endBlockNum
|
||||||
|
m.LockedMilestoneIDs[milestoneId] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := rawdb.WriteLockField(m.db, m.Locked, m.LockedMilestoneNumber, m.LockedMilestoneHash, m.LockedMilestoneIDs)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error in writing lock data of milestone to db", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
milestoneIDLength := int64(len(m.LockedMilestoneIDs))
|
||||||
|
MilestoneIdsLengthMeter.Update(milestoneIDLength)
|
||||||
|
|
||||||
|
m.finality.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will unlock the locked sprint
|
||||||
|
func (m *milestone) UnlockSprint(endBlockNum uint64) {
|
||||||
|
if endBlockNum < m.LockedMilestoneNumber {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Locked = false
|
||||||
|
m.purgeMilestoneIDsList()
|
||||||
|
|
||||||
|
err := rawdb.WriteLockField(m.db, m.Locked, m.LockedMilestoneNumber, m.LockedMilestoneHash, m.LockedMilestoneIDs)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error in writing lock data of milestone to db", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will remove the stored milestoneID
|
||||||
|
func (m *milestone) RemoveMilestoneID(milestoneId string) {
|
||||||
|
m.finality.Lock()
|
||||||
|
|
||||||
|
delete(m.LockedMilestoneIDs, milestoneId)
|
||||||
|
|
||||||
|
if len(m.LockedMilestoneIDs) == 0 {
|
||||||
|
m.Locked = false
|
||||||
|
}
|
||||||
|
|
||||||
|
err := rawdb.WriteLockField(m.db, m.Locked, m.LockedMilestoneNumber, m.LockedMilestoneHash, m.LockedMilestoneIDs)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error in writing lock data of milestone to db", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.finality.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will check whether the incoming chain matches the locked sprint hash
|
||||||
|
func (m *milestone) IsReorgAllowed(chain []*types.Header, lockedMilestoneNumber uint64, lockedMilestoneHash common.Hash) bool {
|
||||||
|
if chain[len(chain)-1].Number.Uint64() <= lockedMilestoneNumber { //Can't reorg if the end block of incoming
|
||||||
|
return false //chain is less than locked sprint number
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(chain); i++ {
|
||||||
|
if chain[i].Number.Uint64() == lockedMilestoneNumber {
|
||||||
|
return chain[i].Hash() == lockedMilestoneHash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will return the list of milestoneIDs stored.
|
||||||
|
func (m *milestone) GetMilestoneIDsList() []string {
|
||||||
|
m.finality.RLock()
|
||||||
|
defer m.finality.RUnlock()
|
||||||
|
|
||||||
|
// fixme: use generics :)
|
||||||
|
keys := make([]string, 0, len(m.LockedMilestoneIDs))
|
||||||
|
for key := range m.LockedMilestoneIDs {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is remove the milestoneIDs stored in the list.
|
||||||
|
func (m *milestone) purgeMilestoneIDsList() {
|
||||||
|
m.LockedMilestoneIDs = make(map[string]struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *milestone) IsFutureMilestoneCompatible(chain []*types.Header) bool {
|
||||||
|
//Tip of the received chain
|
||||||
|
chainTipNumber := chain[len(chain)-1].Number.Uint64()
|
||||||
|
|
||||||
|
for i := len(m.FutureMilestoneOrder) - 1; i >= 0; i-- {
|
||||||
|
//Finding out the highest future milestone number
|
||||||
|
//which is less or equal to received chain tip
|
||||||
|
if chainTipNumber >= m.FutureMilestoneOrder[i] {
|
||||||
|
//Looking for the received chain 's particular block number(matching future milestone number)
|
||||||
|
for j := len(chain) - 1; j >= 0; j-- {
|
||||||
|
if chain[j].Number.Uint64() == m.FutureMilestoneOrder[i] {
|
||||||
|
endBlockNum := m.FutureMilestoneOrder[i]
|
||||||
|
endBlockHash := m.FutureMilestoneList[endBlockNum]
|
||||||
|
|
||||||
|
//Checking the received chain matches with future milestone
|
||||||
|
return chain[j].Hash() == endBlockHash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *milestone) ProcessFutureMilestone(num uint64, hash common.Hash) {
|
||||||
|
if len(m.FutureMilestoneOrder) < m.MaxCapacity {
|
||||||
|
m.enqueueFutureMilestone(num, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
if num < m.LockedMilestoneNumber {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Locked = false
|
||||||
|
m.purgeMilestoneIDsList()
|
||||||
|
|
||||||
|
err := rawdb.WriteLockField(m.db, m.Locked, m.LockedMilestoneNumber, m.LockedMilestoneHash, m.LockedMilestoneIDs)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error in writing lock data of milestone to db", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnqueueFutureMilestone add the future milestone to the list
|
||||||
|
func (m *milestone) enqueueFutureMilestone(key uint64, hash common.Hash) {
|
||||||
|
if _, ok := m.FutureMilestoneList[key]; ok {
|
||||||
|
log.Debug("Future milestone already exist", "endBlockNumber", key, "futureMilestoneHash", hash)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Enqueing new future milestone", "endBlockNumber", key, "futureMilestoneHash", hash)
|
||||||
|
|
||||||
|
m.FutureMilestoneList[key] = hash
|
||||||
|
m.FutureMilestoneOrder = append(m.FutureMilestoneOrder, key)
|
||||||
|
|
||||||
|
err := rawdb.WriteFutureMilestoneList(m.db, m.FutureMilestoneOrder, m.FutureMilestoneList)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error in writing future milestone data to db", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureMilestoneMeter.Update(int64(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DequeueFutureMilestone remove the future milestone entry from the list.
|
||||||
|
func (m *milestone) dequeueFutureMilestone() {
|
||||||
|
delete(m.FutureMilestoneList, m.FutureMilestoneOrder[0])
|
||||||
|
m.FutureMilestoneOrder = m.FutureMilestoneOrder[1:]
|
||||||
|
|
||||||
|
err := rawdb.WriteFutureMilestoneList(m.db, m.FutureMilestoneOrder, m.FutureMilestoneList)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error in writing future milestone data to db", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,135 +3,150 @@ package whitelist
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"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/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Checkpoint whitelist
|
|
||||||
type Service struct {
|
|
||||||
m sync.Mutex
|
|
||||||
checkpointWhitelist map[uint64]common.Hash // Checkpoint whitelist, populated by reaching out to heimdall
|
|
||||||
checkpointOrder []uint64 // Checkpoint order, populated by reaching out to heimdall
|
|
||||||
maxCapacity uint // Max capacity of the whitelist
|
|
||||||
checkpointInterval uint64 // Checkpoint interval, until which we can allow importing
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewService(maxCapacity uint) *Service {
|
|
||||||
return &Service{
|
|
||||||
checkpointWhitelist: make(map[uint64]common.Hash),
|
|
||||||
checkpointOrder: []uint64{},
|
|
||||||
maxCapacity: maxCapacity,
|
|
||||||
checkpointInterval: 256, // TODO: make it configurable through params?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
ErrMismatch = errors.New("mismatch error")
|
||||||
|
ErrNoRemote = errors.New("remote peer doesn't have a target block number")
|
||||||
|
|
||||||
ErrCheckpointMismatch = errors.New("checkpoint mismatch")
|
ErrCheckpointMismatch = errors.New("checkpoint mismatch")
|
||||||
ErrLongFutureChain = errors.New("received future chain of unacceptable length")
|
ErrLongFutureChain = errors.New("received future chain of unacceptable length")
|
||||||
ErrNoRemoteCheckpoint = errors.New("remote peer doesn't have a checkpoint")
|
ErrNoRemoteCheckpoint = errors.New("remote peer doesn't have a checkpoint")
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsValidPeer checks if the chain we're about to receive from a peer is valid or not
|
type Service struct {
|
||||||
// in terms of reorgs. We won't reorg beyond the last bor checkpoint submitted to mainchain.
|
checkpointService
|
||||||
func (w *Service) IsValidPeer(remoteHeader *types.Header, fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
milestoneService
|
||||||
// We want to validate the chain by comparing the last checkpointed block
|
|
||||||
// we're storing in `checkpointWhitelist` with the peer's block.
|
|
||||||
//
|
|
||||||
// Check for availaibility of the last checkpointed block.
|
|
||||||
// This can be also be empty if our heimdall is not responding
|
|
||||||
// or we're running without it.
|
|
||||||
if len(w.checkpointWhitelist) == 0 {
|
|
||||||
// worst case, we don't have the checkpoints in memory
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the last checkpoint entry
|
|
||||||
lastCheckpointBlockNum := w.checkpointOrder[len(w.checkpointOrder)-1]
|
|
||||||
lastCheckpointBlockHash := w.checkpointWhitelist[lastCheckpointBlockNum]
|
|
||||||
|
|
||||||
// todo: we can extract this as an interface and mock as well or just test IsValidChain in isolation from downloader passing fake fetchHeadersByNumber functions
|
|
||||||
headers, hashes, err := fetchHeadersByNumber(lastCheckpointBlockNum, 1, 0, false)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("%w: last checkpoint %d, err %v", ErrNoRemoteCheckpoint, lastCheckpointBlockNum, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(headers) == 0 {
|
|
||||||
return false, fmt.Errorf("%w: last checkpoint %d", ErrNoRemoteCheckpoint, lastCheckpointBlockNum)
|
|
||||||
}
|
|
||||||
|
|
||||||
reqBlockNum := headers[0].Number.Uint64()
|
|
||||||
reqBlockHash := hashes[0]
|
|
||||||
|
|
||||||
// Check against the checkpointed blocks
|
|
||||||
if reqBlockNum == lastCheckpointBlockNum && reqBlockHash == lastCheckpointBlockHash {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, ErrCheckpointMismatch
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValidChain checks the validity of chain by comparing it
|
func NewService(db ethdb.Database) *Service {
|
||||||
// against the local checkpoint entries
|
var checkpointDoExist = true
|
||||||
func (w *Service) IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error) {
|
|
||||||
// Check if we have checkpoints to validate incoming chain in memory
|
checkpointNumber, checkpointHash, err := rawdb.ReadFinality[*rawdb.Checkpoint](db)
|
||||||
if len(w.checkpointWhitelist) == 0 {
|
|
||||||
// We don't have any entries, no additional validation will be possible
|
if err != nil {
|
||||||
return true, nil
|
checkpointDoExist = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return if we've received empty chain
|
var milestoneDoExist = true
|
||||||
if len(chain) == 0 {
|
|
||||||
return false, nil
|
milestoneNumber, milestoneHash, err := rawdb.ReadFinality[*rawdb.Milestone](db)
|
||||||
|
if err != nil {
|
||||||
|
milestoneDoExist = false
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
locked, lockedMilestoneNumber, lockedMilestoneHash, lockedMilestoneIDs, err := rawdb.ReadLockField(db)
|
||||||
oldestCheckpointNumber uint64 = w.checkpointOrder[0]
|
if err != nil || !locked {
|
||||||
current uint64 = currentHeader.Number.Uint64()
|
locked = false
|
||||||
)
|
lockedMilestoneIDs = make(map[string]struct{})
|
||||||
|
|
||||||
// Check if we have whitelist entries in required range
|
|
||||||
if chain[len(chain)-1].Number.Uint64() < oldestCheckpointNumber {
|
|
||||||
// We have future whitelisted entries, so no additional validation will be possible
|
|
||||||
// This case will occur when bor is in middle of sync, but heimdall is ahead/fully synced.
|
|
||||||
return true, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split the chain into past and future chain
|
order, list, err := rawdb.ReadFutureMilestoneList(db)
|
||||||
pastChain, _ := splitChain(current, chain)
|
if err != nil {
|
||||||
|
order = make([]uint64, 0)
|
||||||
|
list = make(map[uint64]common.Hash)
|
||||||
|
}
|
||||||
|
|
||||||
// Note: Do not act on future chain and allow importing all kinds of future chains.
|
return &Service{
|
||||||
|
&checkpoint{
|
||||||
|
finality[*rawdb.Checkpoint]{
|
||||||
|
doExist: checkpointDoExist,
|
||||||
|
Number: checkpointNumber,
|
||||||
|
Hash: checkpointHash,
|
||||||
|
interval: 256,
|
||||||
|
db: db,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// Add an offset to future chain if it's not in continuity
|
&milestone{
|
||||||
// offset := 0
|
finality: finality[*rawdb.Milestone]{
|
||||||
// if len(futureChain) != 0 {
|
doExist: milestoneDoExist,
|
||||||
// offset += int(futureChain[0].Number.Uint64()-currentHeader.Number.Uint64()) - 1
|
Number: milestoneNumber,
|
||||||
// }
|
Hash: milestoneHash,
|
||||||
|
interval: 256,
|
||||||
|
db: db,
|
||||||
|
},
|
||||||
|
|
||||||
// Don't accept future chain of unacceptable length (from current block)
|
Locked: locked,
|
||||||
// if len(futureChain)+offset > int(w.checkpointInterval) {
|
LockedMilestoneNumber: lockedMilestoneNumber,
|
||||||
// return false, ErrLongFutureChain
|
LockedMilestoneHash: lockedMilestoneHash,
|
||||||
// }
|
LockedMilestoneIDs: lockedMilestoneIDs,
|
||||||
|
FutureMilestoneList: list,
|
||||||
|
FutureMilestoneOrder: order,
|
||||||
|
MaxCapacity: 10,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Iterate over the chain and validate against the last checkpoint
|
// IsValidPeer checks if the chain we're about to receive from a peer is valid or not
|
||||||
// It will handle all cases where the incoming chain has atleast one checkpoint
|
// in terms of reorgs. We won't reorg beyond the last bor checkpoint submitted to mainchain and last milestone voted in the heimdall
|
||||||
for i := len(pastChain) - 1; i >= 0; i-- {
|
func (s *Service) IsValidPeer(fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) {
|
||||||
if _, ok := w.checkpointWhitelist[pastChain[i].Number.Uint64()]; ok {
|
checkpointBool, err := s.checkpointService.IsValidPeer(fetchHeadersByNumber)
|
||||||
return pastChain[i].Hash() == w.checkpointWhitelist[pastChain[i].Number.Uint64()], nil
|
if !checkpointBool {
|
||||||
}
|
return checkpointBool, err
|
||||||
|
}
|
||||||
|
|
||||||
|
milestoneBool, err := s.milestoneService.IsValidPeer(fetchHeadersByNumber)
|
||||||
|
if !milestoneBool {
|
||||||
|
return milestoneBool, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) PurgeWhitelistedCheckpoint() {
|
||||||
|
s.checkpointService.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) PurgeWhitelistedMilestone() {
|
||||||
|
s.milestoneService.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) GetWhitelistedCheckpoint() (bool, uint64, common.Hash) {
|
||||||
|
return s.checkpointService.Get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) GetWhitelistedMilestone() (bool, uint64, common.Hash) {
|
||||||
|
return s.milestoneService.Get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) ProcessMilestone(endBlockNum uint64, endBlockHash common.Hash) {
|
||||||
|
s.milestoneService.Process(endBlockNum, endBlockHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash) {
|
||||||
|
s.checkpointService.Process(endBlockNum, endBlockHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error) {
|
||||||
|
checkpointBool, err := s.checkpointService.IsValidChain(currentHeader, chain)
|
||||||
|
if !checkpointBool {
|
||||||
|
return checkpointBool, err
|
||||||
|
}
|
||||||
|
|
||||||
|
milestoneBool, err := s.milestoneService.IsValidChain(currentHeader, chain)
|
||||||
|
if !milestoneBool {
|
||||||
|
return milestoneBool, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) GetMilestoneIDsList() []string {
|
||||||
|
return s.milestoneService.GetMilestoneIDsList()
|
||||||
|
}
|
||||||
|
|
||||||
func splitChain(current uint64, chain []*types.Header) ([]*types.Header, []*types.Header) {
|
func splitChain(current uint64, chain []*types.Header) ([]*types.Header, []*types.Header) {
|
||||||
var (
|
var (
|
||||||
pastChain []*types.Header
|
pastChain []*types.Header
|
||||||
futureChain []*types.Header
|
futureChain []*types.Header
|
||||||
first uint64 = chain[0].Number.Uint64()
|
first = chain[0].Number.Uint64()
|
||||||
last uint64 = chain[len(chain)-1].Number.Uint64()
|
last = chain[len(chain)-1].Number.Uint64()
|
||||||
)
|
)
|
||||||
|
|
||||||
if current >= first {
|
if current >= first {
|
||||||
|
|
@ -153,57 +168,68 @@ func splitChain(current uint64, chain []*types.Header) ([]*types.Header, []*type
|
||||||
return pastChain, futureChain
|
return pastChain, futureChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Service) ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash) {
|
//nolint:unparam
|
||||||
w.m.Lock()
|
func isValidChain(currentHeader *types.Header, chain []*types.Header, doExist bool, number uint64, hash common.Hash) (bool, error) {
|
||||||
defer w.m.Unlock()
|
// Check if we have milestone to validate incoming chain in memory
|
||||||
|
if !doExist {
|
||||||
w.enqueueCheckpointWhitelist(endBlockNum, endBlockHash)
|
// We don't have any entry, no additional validation will be possible
|
||||||
// If size of checkpoint whitelist map is greater than 10, remove the oldest entry.
|
return true, nil
|
||||||
|
|
||||||
if w.length() > int(w.maxCapacity) {
|
|
||||||
w.dequeueCheckpointWhitelist()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// GetCheckpointWhitelist returns the existing whitelisted
|
current := currentHeader.Number.Uint64()
|
||||||
// entries of checkpoint of the form block number -> block hash.
|
|
||||||
func (w *Service) GetCheckpointWhitelist() map[uint64]common.Hash {
|
|
||||||
w.m.Lock()
|
|
||||||
defer w.m.Unlock()
|
|
||||||
|
|
||||||
return w.checkpointWhitelist
|
// Check if imported chain is less than whitelisted number
|
||||||
}
|
if chain[len(chain)-1].Number.Uint64() < number {
|
||||||
|
if current >= number { //If current tip of the chain is greater than whitelist number then return false
|
||||||
// PurgeCheckpointWhitelist purges data from checkpoint whitelist map
|
return false, nil
|
||||||
func (w *Service) PurgeCheckpointWhitelist() {
|
} else {
|
||||||
w.m.Lock()
|
return true, nil
|
||||||
defer w.m.Unlock()
|
}
|
||||||
|
|
||||||
w.checkpointWhitelist = make(map[uint64]common.Hash)
|
|
||||||
w.checkpointOrder = make([]uint64, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnqueueWhitelistBlock enqueues blockNumber, blockHash to the checkpoint whitelist map
|
|
||||||
func (w *Service) enqueueCheckpointWhitelist(key uint64, val common.Hash) {
|
|
||||||
if _, ok := w.checkpointWhitelist[key]; !ok {
|
|
||||||
log.Debug("Enqueing new checkpoint whitelist", "block number", key, "block hash", val)
|
|
||||||
|
|
||||||
w.checkpointWhitelist[key] = val
|
|
||||||
w.checkpointOrder = append(w.checkpointOrder, key)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// DequeueWhitelistBlock dequeues block, blockhash from the checkpoint whitelist map
|
// Split the chain into past and future chain
|
||||||
func (w *Service) dequeueCheckpointWhitelist() {
|
pastChain, _ := splitChain(current, chain)
|
||||||
if len(w.checkpointOrder) > 0 {
|
|
||||||
log.Debug("Dequeing checkpoint whitelist", "block number", w.checkpointOrder[0], "block hash", w.checkpointWhitelist[w.checkpointOrder[0]])
|
|
||||||
|
|
||||||
delete(w.checkpointWhitelist, w.checkpointOrder[0])
|
// Iterate over the chain and validate against the last milestone
|
||||||
w.checkpointOrder = w.checkpointOrder[1:] // fixme: this slice is growing infinitely and never will be released. also a panic is possible if the last element is going to be removed
|
// It will handle all cases when the incoming chain has atleast one milestone
|
||||||
|
for i := len(pastChain) - 1; i >= 0; i-- {
|
||||||
|
if pastChain[i].Number.Uint64() == number {
|
||||||
|
res := pastChain[i].Hash() == hash
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// length returns the len of the whitelist.
|
// FIXME: remoteHeader is not used
|
||||||
func (w *Service) length() int {
|
func isValidPeer(fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error), doExist bool, number uint64, hash common.Hash) (bool, error) {
|
||||||
return len(w.checkpointWhitelist)
|
// Check for availaibility of the last milestone block.
|
||||||
|
// This can be also be empty if our heimdall is not responding
|
||||||
|
// or we're running without it.
|
||||||
|
if !doExist {
|
||||||
|
// worst case, we don't have the milestone in memory
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: we can extract this as an interface and mock as well or just test IsValidChain in isolation from downloader passing fake fetchHeadersByNumber functions
|
||||||
|
headers, hashes, err := fetchHeadersByNumber(number, 1, 0, false)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("%w: last whitelisted block number %d, err %v", ErrNoRemote, number, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(headers) == 0 {
|
||||||
|
return false, fmt.Errorf("%w: last whitlisted block number %d", ErrNoRemote, number)
|
||||||
|
}
|
||||||
|
|
||||||
|
reqBlockNum := headers[0].Number.Uint64()
|
||||||
|
reqBlockHash := hashes[0]
|
||||||
|
|
||||||
|
// Check against the whitelisted blocks
|
||||||
|
if reqBlockNum == number && reqBlockHash == hash {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, ErrMismatch
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
// nolint
|
||||||
package whitelist
|
package whitelist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -9,35 +10,243 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"pgregory.net/rapid"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"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/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewMockService creates a new mock whitelist service
|
// NewMockService creates a new mock whitelist service
|
||||||
func NewMockService(maxCapacity uint, checkpointInterval uint64) *Service {
|
func NewMockService(db ethdb.Database) *Service {
|
||||||
return &Service{
|
return &Service{
|
||||||
checkpointWhitelist: make(map[uint64]common.Hash),
|
|
||||||
checkpointOrder: []uint64{},
|
&checkpoint{
|
||||||
maxCapacity: maxCapacity,
|
finality[*rawdb.Checkpoint]{
|
||||||
checkpointInterval: checkpointInterval,
|
doExist: false,
|
||||||
|
interval: 256,
|
||||||
|
db: db,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
&milestone{
|
||||||
|
finality: finality[*rawdb.Milestone]{
|
||||||
|
doExist: false,
|
||||||
|
interval: 256,
|
||||||
|
db: db,
|
||||||
|
},
|
||||||
|
LockedMilestoneIDs: make(map[string]struct{}),
|
||||||
|
FutureMilestoneList: make(map[uint64]common.Hash),
|
||||||
|
FutureMilestoneOrder: make([]uint64, 0),
|
||||||
|
MaxCapacity: 10,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWhitelistCheckpoint checks the checkpoint whitelist map queue mechanism
|
// TestWhitelistCheckpoint checks the checkpoint whitelist setter and getter functions.
|
||||||
func TestWhitelistCheckpoint(t *testing.T) {
|
func TestWhitelistedCheckpoint(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := NewMockService(10, 10)
|
db := rawdb.NewMemoryDatabase()
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
s.enqueueCheckpointWhitelist(uint64(i), common.Hash{})
|
|
||||||
}
|
|
||||||
require.Equal(t, s.length(), 10, "expected 10 items in whitelist")
|
|
||||||
|
|
||||||
s.enqueueCheckpointWhitelist(11, common.Hash{})
|
//Creating the service for the whitelisting the checkpoints
|
||||||
s.dequeueCheckpointWhitelist()
|
s := NewMockService(db)
|
||||||
require.Equal(t, s.length(), 10, "expected 10 items in whitelist")
|
|
||||||
|
cp := s.checkpointService.(*checkpoint)
|
||||||
|
|
||||||
|
require.Equal(t, cp.doExist, false, "expected false as no cp exist at this point")
|
||||||
|
|
||||||
|
_, _, err := rawdb.ReadFinality[*rawdb.Checkpoint](db)
|
||||||
|
require.NotNil(t, err, "Error should be nil while reading from the db")
|
||||||
|
|
||||||
|
//Adding the checkpoint
|
||||||
|
s.ProcessCheckpoint(11, common.Hash{})
|
||||||
|
|
||||||
|
require.Equal(t, cp.doExist, true, "expected true as cp exist")
|
||||||
|
|
||||||
|
//Removing the checkpoint
|
||||||
|
s.PurgeWhitelistedCheckpoint()
|
||||||
|
|
||||||
|
require.Equal(t, cp.doExist, false, "expected false as no cp exist at this point")
|
||||||
|
|
||||||
|
//Adding the checkpoint
|
||||||
|
s.ProcessCheckpoint(12, common.Hash{1})
|
||||||
|
|
||||||
|
//Receiving the stored checkpoint
|
||||||
|
doExist, number, hash := s.GetWhitelistedCheckpoint()
|
||||||
|
|
||||||
|
//Validating the values received
|
||||||
|
require.Equal(t, doExist, true, "expected true ascheckpoint exist at this point")
|
||||||
|
require.Equal(t, number, uint64(12), "expected number to be 11 but got", number)
|
||||||
|
require.Equal(t, hash, common.Hash{1}, "expected the 1 hash but got", hash)
|
||||||
|
require.NotEqual(t, hash, common.Hash{}, "expected the hash to be different from zero hash")
|
||||||
|
|
||||||
|
c1 := s.checkpointService.(*checkpoint)
|
||||||
|
fmt.Println("!!!-0", c1.doExist)
|
||||||
|
s.PurgeWhitelistedCheckpoint()
|
||||||
|
fmt.Println("!!!-1", c1.doExist)
|
||||||
|
doExist, number, hash = s.GetWhitelistedCheckpoint()
|
||||||
|
fmt.Println("!!!-2", c1.doExist)
|
||||||
|
//Validating the values received from the db, not memory
|
||||||
|
require.Equal(t, doExist, true, "expected true ascheckpoint exist at this point")
|
||||||
|
require.Equal(t, number, uint64(12), "expected number to be 11 but got", number)
|
||||||
|
require.Equal(t, hash, common.Hash{1}, "expected the 1 hash but got", hash)
|
||||||
|
require.NotEqual(t, hash, common.Hash{}, "expected the hash to be different from zero hash")
|
||||||
|
|
||||||
|
checkpointNumber, checkpointHash, err := rawdb.ReadFinality[*rawdb.Checkpoint](db)
|
||||||
|
require.Nil(t, err, "Error should be nil while reading from the db")
|
||||||
|
require.Equal(t, checkpointHash, common.Hash{1}, "expected the 1 hash but got", hash)
|
||||||
|
require.Equal(t, checkpointNumber, uint64(12), "expected number to be 11 but got", number)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMilestone checks the milestone whitelist setter and getter functions
|
||||||
|
func TestMilestone(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
s := NewMockService(db)
|
||||||
|
|
||||||
|
milestone := s.milestoneService.(*milestone)
|
||||||
|
|
||||||
|
//Checking for the variables when no milestone is Processed
|
||||||
|
require.Equal(t, milestone.doExist, false, "expected false as no milestone exist at this point")
|
||||||
|
require.Equal(t, milestone.Locked, false, "expected false as it was not locked")
|
||||||
|
require.Equal(t, milestone.LockedMilestoneNumber, uint64(0), "expected 0 as it was not initialized")
|
||||||
|
|
||||||
|
_, _, err := rawdb.ReadFinality[*rawdb.Milestone](db)
|
||||||
|
require.NotNil(t, err, "Error should be nil while reading from the db")
|
||||||
|
|
||||||
|
//Acquiring the mutex lock
|
||||||
|
milestone.LockMutex(11)
|
||||||
|
require.Equal(t, milestone.Locked, false, "expected false as sprint is not locked till this point")
|
||||||
|
|
||||||
|
//Releasing the mutex lock
|
||||||
|
milestone.UnlockMutex(true, "milestoneID1", uint64(11), common.Hash{})
|
||||||
|
require.Equal(t, milestone.LockedMilestoneNumber, uint64(11), "expected 11 as it was not initialized")
|
||||||
|
require.Equal(t, milestone.Locked, true, "expected true as sprint is locked now")
|
||||||
|
require.Equal(t, len(milestone.LockedMilestoneIDs), 1, "expected 1 as only 1 milestoneID has been entered")
|
||||||
|
|
||||||
|
_, ok := milestone.LockedMilestoneIDs["milestoneID1"]
|
||||||
|
require.True(t, ok, "milestoneID1 should exist in the LockedMilestoneIDs map")
|
||||||
|
|
||||||
|
_, ok = milestone.LockedMilestoneIDs["milestoneID2"]
|
||||||
|
require.False(t, ok, "milestoneID2 shouldn't exist in the LockedMilestoneIDs map")
|
||||||
|
|
||||||
|
milestone.LockMutex(11)
|
||||||
|
milestone.UnlockMutex(true, "milestoneID2", uint64(11), common.Hash{})
|
||||||
|
require.Equal(t, len(milestone.LockedMilestoneIDs), 1, "expected 1 as only 1 milestoneID has been entered")
|
||||||
|
|
||||||
|
_, ok = milestone.LockedMilestoneIDs["milestoneID2"]
|
||||||
|
require.True(t, ok, "milestoneID2 should exist in the LockedMilestoneIDs map")
|
||||||
|
|
||||||
|
milestone.RemoveMilestoneID("milestoneID1")
|
||||||
|
require.Equal(t, len(milestone.LockedMilestoneIDs), 1, "expected 1 as one out of two has been removed in previous step")
|
||||||
|
require.Equal(t, milestone.Locked, true, "expected true as sprint is locked now")
|
||||||
|
|
||||||
|
milestone.RemoveMilestoneID("milestoneID2")
|
||||||
|
require.Equal(t, len(milestone.LockedMilestoneIDs), 0, "expected 1 as both the milestonesIDs has been removed in previous step")
|
||||||
|
require.Equal(t, milestone.Locked, false, "expected false")
|
||||||
|
|
||||||
|
milestone.LockMutex(11)
|
||||||
|
milestone.UnlockMutex(true, "milestoneID3", uint64(11), common.Hash{})
|
||||||
|
require.True(t, milestone.Locked, "expected true")
|
||||||
|
require.Equal(t, milestone.LockedMilestoneNumber, uint64(11), "Expected 11")
|
||||||
|
|
||||||
|
milestone.LockMutex(15)
|
||||||
|
require.True(t, milestone.Locked, "expected true")
|
||||||
|
require.Equal(t, milestone.LockedMilestoneNumber, uint64(11), "Expected 11")
|
||||||
|
milestone.UnlockMutex(true, "milestoneID4", uint64(15), common.Hash{})
|
||||||
|
require.True(t, milestone.Locked, "expected true as final confirmation regarding the lock has been made")
|
||||||
|
require.Equal(t, len(milestone.LockedMilestoneIDs), 1, "expected 1 as previous milestonesIDs has been removed in previous step")
|
||||||
|
|
||||||
|
//Adding the milestone
|
||||||
|
s.ProcessMilestone(11, common.Hash{})
|
||||||
|
|
||||||
|
require.True(t, milestone.Locked, "expected true as locked sprint is of number 15")
|
||||||
|
require.Equal(t, milestone.doExist, true, "expected true as milestone exist")
|
||||||
|
require.Equal(t, len(milestone.LockedMilestoneIDs), 1, "expected 1 as still last milestone of sprint number 15 exist")
|
||||||
|
|
||||||
|
//Reading from the Db
|
||||||
|
locked, lockedMilestoneNumber, lockedMilestoneHash, lockedMilestoneIDs, err := rawdb.ReadLockField(db)
|
||||||
|
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.True(t, locked, "expected true as locked sprint is of number 15")
|
||||||
|
require.Equal(t, lockedMilestoneNumber, uint64(15), "Expected 15")
|
||||||
|
require.Equal(t, lockedMilestoneHash, common.Hash{}, "Expected", common.Hash{})
|
||||||
|
require.Equal(t, len(lockedMilestoneIDs), 1, "expected 1 as still last milestone of sprint number 15 exist")
|
||||||
|
|
||||||
|
_, ok = lockedMilestoneIDs["milestoneID4"]
|
||||||
|
require.True(t, ok, "expected true as milestoneIDList should contain 'milestoneID4'")
|
||||||
|
|
||||||
|
//Asking the lock for sprintNumber less than last whitelisted milestone
|
||||||
|
require.False(t, milestone.LockMutex(11), "Cant lock the sprintNumber less than equal to latest whitelisted milestone")
|
||||||
|
milestone.UnlockMutex(false, "", uint64(11), common.Hash{}) //Unlock is required after every lock to release the mutex
|
||||||
|
|
||||||
|
//Adding the milestone
|
||||||
|
s.ProcessMilestone(51, common.Hash{})
|
||||||
|
require.False(t, milestone.Locked, "expected false as lock from sprint number 15 is removed")
|
||||||
|
require.Equal(t, milestone.doExist, true, "expected true as milestone exist")
|
||||||
|
require.Equal(t, len(milestone.LockedMilestoneIDs), 0, "expected 0 as all the milestones have been removed")
|
||||||
|
|
||||||
|
//Reading from the Db
|
||||||
|
locked, _, _, lockedMilestoneIDs, err = rawdb.ReadLockField(db)
|
||||||
|
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.False(t, locked, "expected true as locked sprint is of number 15")
|
||||||
|
require.Equal(t, len(lockedMilestoneIDs), 0, "expected 0 as milestoneID exist in the map")
|
||||||
|
|
||||||
|
//Removing the milestone
|
||||||
|
s.PurgeWhitelistedMilestone()
|
||||||
|
|
||||||
|
require.Equal(t, milestone.doExist, false, "expected false as no milestone exist at this point")
|
||||||
|
|
||||||
|
//Removing the milestone
|
||||||
|
s.ProcessMilestone(11, common.Hash{1})
|
||||||
|
|
||||||
|
doExist, number, hash := s.GetWhitelistedMilestone()
|
||||||
|
|
||||||
|
//validating the values received
|
||||||
|
require.Equal(t, doExist, true, "expected true as milestone exist at this point")
|
||||||
|
require.Equal(t, number, uint64(11), "expected number to be 11 but got", number)
|
||||||
|
require.Equal(t, hash, common.Hash{1}, "expected the 1 hash but got", hash)
|
||||||
|
|
||||||
|
s.PurgeWhitelistedMilestone()
|
||||||
|
doExist, number, hash = s.GetWhitelistedMilestone()
|
||||||
|
|
||||||
|
//Validating the values received from the db, not memory
|
||||||
|
require.Equal(t, doExist, true, "expected true as milestone exist at this point")
|
||||||
|
require.Equal(t, number, uint64(11), "expected number to be 11 but got", number)
|
||||||
|
require.Equal(t, hash, common.Hash{1}, "expected the 1 hash but got", hash)
|
||||||
|
|
||||||
|
milestoneNumber, milestoneHash, err := rawdb.ReadFinality[*rawdb.Milestone](db)
|
||||||
|
require.Nil(t, err, "Error should be nil while reading from the db")
|
||||||
|
require.Equal(t, milestoneHash, common.Hash{1}, "expected the 1 hash but got", hash)
|
||||||
|
require.Equal(t, milestoneNumber, uint64(11), "expected number to be 11 but got", number)
|
||||||
|
|
||||||
|
_, _, err = rawdb.ReadFutureMilestoneList(db)
|
||||||
|
require.NotNil(t, err, "Error should be not nil")
|
||||||
|
|
||||||
|
s.ProcessFutureMilestone(16, common.Hash{16})
|
||||||
|
require.Equal(t, len(milestone.FutureMilestoneOrder), 1, "expected length is 1 as we added only 1 future milestone")
|
||||||
|
require.Equal(t, milestone.FutureMilestoneOrder[0], uint64(16), "expected value is 16 but got", milestone.FutureMilestoneOrder[0])
|
||||||
|
require.Equal(t, milestone.FutureMilestoneList[16], common.Hash{16}, "expected value is", common.Hash{16}.String()[2:], "but got", milestone.FutureMilestoneList[16])
|
||||||
|
|
||||||
|
order, list, err := rawdb.ReadFutureMilestoneList(db)
|
||||||
|
require.Nil(t, err, "Error should be nil while reading from the db")
|
||||||
|
require.Equal(t, len(order), 1, "expected the 1 hash but got", len(order))
|
||||||
|
require.Equal(t, order[0], uint64(16), "expected number to be 16 but got", order[0])
|
||||||
|
require.Equal(t, list[order[0]], common.Hash{16}, "expected value is", common.Hash{16}.String()[2:], "but got", list[order[0]])
|
||||||
|
|
||||||
|
capicity := milestone.MaxCapacity
|
||||||
|
for i := 16; i <= 16*(capicity+1); i = i + 16 {
|
||||||
|
s.ProcessFutureMilestone(uint64(i), common.Hash{16})
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(t, len(milestone.FutureMilestoneOrder), capicity, "expected length is", capicity)
|
||||||
|
require.Equal(t, milestone.FutureMilestoneOrder[capicity-1], uint64(16*capicity), "expected value is", uint64(16*capicity), "but got", milestone.FutureMilestoneOrder[capicity-1])
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestIsValidPeer checks the IsValidPeer function in isolation
|
// TestIsValidPeer checks the IsValidPeer function in isolation
|
||||||
|
|
@ -45,18 +254,26 @@ func TestWhitelistCheckpoint(t *testing.T) {
|
||||||
func TestIsValidPeer(t *testing.T) {
|
func TestIsValidPeer(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := NewMockService(10, 10)
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
s := NewMockService(db)
|
||||||
|
|
||||||
// case1: no checkpoint whitelist, should consider the chain as valid
|
// case1: no checkpoint whitelist, should consider the chain as valid
|
||||||
res, err := s.IsValidPeer(nil, nil)
|
res, err := s.IsValidPeer(nil)
|
||||||
require.NoError(t, err, "expected no error")
|
require.NoError(t, err, "expected no error")
|
||||||
require.Equal(t, res, true, "expected chain to be valid")
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
|
|
||||||
// add checkpoint entries and mock fetchHeadersByNumber function
|
// add checkpoint entry and mock fetchHeadersByNumber function
|
||||||
s.ProcessCheckpoint(uint64(0), common.Hash{})
|
|
||||||
s.ProcessCheckpoint(uint64(1), common.Hash{})
|
s.ProcessCheckpoint(uint64(1), common.Hash{})
|
||||||
|
|
||||||
require.Equal(t, s.length(), 2, "expected 2 items in whitelist")
|
// add milestone entry and mock fetchHeadersByNumber function
|
||||||
|
s.ProcessMilestone(uint64(1), common.Hash{})
|
||||||
|
|
||||||
|
checkpoint := s.checkpointService.(*checkpoint)
|
||||||
|
milestone := s.milestoneService.(*milestone)
|
||||||
|
|
||||||
|
//Check whether the milestone and checkpoint exist
|
||||||
|
require.Equal(t, checkpoint.doExist, true, "expected true as checkpoint exists")
|
||||||
|
require.Equal(t, milestone.doExist, true, "expected true as milestone exists")
|
||||||
|
|
||||||
// create a false function, returning absolutely nothing
|
// create a false function, returning absolutely nothing
|
||||||
falseFetchHeadersByNumber := func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error) {
|
falseFetchHeadersByNumber := func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error) {
|
||||||
|
|
@ -64,20 +281,19 @@ func TestIsValidPeer(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// case2: false fetchHeadersByNumber function provided, should consider the chain as invalid
|
// case2: false fetchHeadersByNumber function provided, should consider the chain as invalid
|
||||||
// and throw `ErrNoRemoteCheckpoint` error
|
// and throw `ErrNoRemoteCheckoint` error
|
||||||
res, err = s.IsValidPeer(nil, falseFetchHeadersByNumber)
|
res, err = s.IsValidPeer(falseFetchHeadersByNumber)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected error, got nil")
|
t.Fatal("expected error, got nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !errors.Is(err, ErrNoRemoteCheckpoint) {
|
if !errors.Is(err, ErrNoRemote) {
|
||||||
t.Fatalf("expected error ErrNoRemoteCheckpoint, got %v", err)
|
t.Fatalf("expected error ErrNoRemote, got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(t, res, false, "expected chain to be invalid")
|
require.Equal(t, res, false, "expected peer chain to be invalid")
|
||||||
|
|
||||||
// case3: correct fetchHeadersByNumber function provided, should consider the chain as valid
|
// create a mock function, returning the required header
|
||||||
// create a mock function, returning a the required header
|
|
||||||
fetchHeadersByNumber := func(number uint64, _ int, _ int, _ bool) ([]*types.Header, []common.Hash, error) {
|
fetchHeadersByNumber := func(number uint64, _ int, _ int, _ bool) ([]*types.Header, []common.Hash, error) {
|
||||||
hash := common.Hash{}
|
hash := common.Hash{}
|
||||||
header := types.Header{Number: big.NewInt(0)}
|
header := types.Header{Number: big.NewInt(0)}
|
||||||
|
|
@ -96,18 +312,124 @@ func TestIsValidPeer(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err = s.IsValidPeer(nil, fetchHeadersByNumber)
|
// case3: correct fetchHeadersByNumber function provided, should consider the chain as valid
|
||||||
|
res, err = s.IsValidPeer(fetchHeadersByNumber)
|
||||||
require.NoError(t, err, "expected no error")
|
require.NoError(t, err, "expected no error")
|
||||||
require.Equal(t, res, true, "expected chain to be valid")
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
|
|
||||||
// add one more checkpoint whitelist entry
|
// add checkpoint whitelist entry
|
||||||
s.ProcessCheckpoint(uint64(2), common.Hash{})
|
s.ProcessCheckpoint(uint64(2), common.Hash{})
|
||||||
require.Equal(t, s.length(), 3, "expected 3 items in whitelist")
|
require.Equal(t, checkpoint.doExist, true, "expected true as checkpoint exists")
|
||||||
|
|
||||||
// case4: correct fetchHeadersByNumber function provided with wrong header
|
// case4: correct fetchHeadersByNumber function provided with wrong header
|
||||||
// for block number 2. Should consider the chain as invalid and throw an error
|
// for block number 2. Should consider the chain as invalid and throw an error
|
||||||
res, err = s.IsValidPeer(nil, fetchHeadersByNumber)
|
res, err = s.IsValidPeer(fetchHeadersByNumber)
|
||||||
require.Equal(t, err, ErrCheckpointMismatch, "expected checkpoint mismatch error")
|
require.Equal(t, err, ErrMismatch, "expected mismatch error")
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
|
|
||||||
|
// create a mock function, returning the required header
|
||||||
|
fetchHeadersByNumber = func(number uint64, _ int, _ int, _ bool) ([]*types.Header, []common.Hash, error) {
|
||||||
|
hash := common.Hash{}
|
||||||
|
header := types.Header{Number: big.NewInt(0)}
|
||||||
|
|
||||||
|
switch number {
|
||||||
|
case 0:
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
case 1:
|
||||||
|
header.Number = big.NewInt(1)
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
case 2:
|
||||||
|
header.Number = big.NewInt(2)
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
header.Number = big.NewInt(3)
|
||||||
|
hash3 := common.Hash{3}
|
||||||
|
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash3}, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, nil, errors.New("invalid number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.ProcessMilestone(uint64(3), common.Hash{})
|
||||||
|
|
||||||
|
//Case5: correct fetchHeadersByNumber function provided with hash mismatch, should consider the chain as invalid
|
||||||
|
res, err = s.IsValidPeer(fetchHeadersByNumber)
|
||||||
|
require.Equal(t, err, ErrMismatch, "expected milestone mismatch error")
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
|
|
||||||
|
s.ProcessMilestone(uint64(2), common.Hash{})
|
||||||
|
|
||||||
|
// create a mock function, returning the required header
|
||||||
|
fetchHeadersByNumber = func(number uint64, _ int, _ int, _ bool) ([]*types.Header, []common.Hash, error) {
|
||||||
|
hash := common.Hash{}
|
||||||
|
header := types.Header{Number: big.NewInt(0)}
|
||||||
|
|
||||||
|
switch number {
|
||||||
|
case 0:
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
case 1:
|
||||||
|
header.Number = big.NewInt(1)
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
case 2:
|
||||||
|
header.Number = big.NewInt(2)
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
default:
|
||||||
|
return nil, nil, errors.New("invalid number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// case6: correct fetchHeadersByNumber function provided, should consider the chain as valid
|
||||||
|
res, err = s.IsValidPeer(fetchHeadersByNumber)
|
||||||
|
require.NoError(t, err, "expected no error")
|
||||||
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
|
|
||||||
|
// create a mock function, returning the required header
|
||||||
|
fetchHeadersByNumber = func(number uint64, _ int, _ int, _ bool) ([]*types.Header, []common.Hash, error) {
|
||||||
|
hash := common.Hash{}
|
||||||
|
hash3 := common.Hash{3}
|
||||||
|
header := types.Header{Number: big.NewInt(0)}
|
||||||
|
|
||||||
|
switch number {
|
||||||
|
case 0:
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
case 1:
|
||||||
|
header.Number = big.NewInt(1)
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
case 2:
|
||||||
|
header.Number = big.NewInt(2)
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
header.Number = big.NewInt(2) // sending wrong header for misamatch
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash}, nil
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
header.Number = big.NewInt(4) // sending wrong header for misamatch
|
||||||
|
return []*types.Header{&header}, []common.Hash{hash3}, nil
|
||||||
|
default:
|
||||||
|
return nil, nil, errors.New("invalid number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add one more milestone in the list
|
||||||
|
s.ProcessMilestone(uint64(3), common.Hash{})
|
||||||
|
|
||||||
|
// case7: correct fetchHeadersByNumber function provided with wrong header for block 3, should consider the chain as invalid
|
||||||
|
res, err = s.IsValidPeer(fetchHeadersByNumber)
|
||||||
|
require.Equal(t, err, ErrMismatch, "expected milestone mismatch error")
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
|
|
||||||
|
//require.Equal(t, milestone.length(), 3, "expected 3 items in milestoneList")
|
||||||
|
|
||||||
|
//Add one more milestone in the list
|
||||||
|
s.ProcessMilestone(uint64(4), common.Hash{})
|
||||||
|
|
||||||
|
// case8: correct fetchHeadersByNumber function provided with wrong hash for block 3, should consider the chain as valid
|
||||||
|
res, err = s.IsValidPeer(fetchHeadersByNumber)
|
||||||
|
require.Equal(t, err, ErrMismatch, "expected milestone mismatch error")
|
||||||
require.Equal(t, res, false, "expected chain to be invalid")
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,71 +438,479 @@ func TestIsValidPeer(t *testing.T) {
|
||||||
func TestIsValidChain(t *testing.T) {
|
func TestIsValidChain(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := NewMockService(10, 10)
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
s := NewMockService(db)
|
||||||
chainA := createMockChain(1, 20) // A1->A2...A19->A20
|
chainA := createMockChain(1, 20) // A1->A2...A19->A20
|
||||||
// case1: no checkpoint whitelist, should consider the chain as valid
|
|
||||||
|
//Case1: no checkpoint whitelist and no milestone and no locking, should consider the chain as valid
|
||||||
res, err := s.IsValidChain(nil, chainA)
|
res, err := s.IsValidChain(nil, chainA)
|
||||||
require.Equal(t, res, true, "expected chain to be valid")
|
require.Nil(t, err)
|
||||||
require.Equal(t, err, nil, "expected error to be nil")
|
require.Equal(t, res, true, "Expected chain to be valid")
|
||||||
|
|
||||||
tempChain := createMockChain(21, 22) // A21->A22
|
tempChain := createMockChain(21, 22) // A21->A22
|
||||||
|
|
||||||
// add mock checkpoint entries
|
// add mock checkpoint entry
|
||||||
s.ProcessCheckpoint(tempChain[0].Number.Uint64(), tempChain[0].Hash())
|
|
||||||
s.ProcessCheckpoint(tempChain[1].Number.Uint64(), tempChain[1].Hash())
|
s.ProcessCheckpoint(tempChain[1].Number.Uint64(), tempChain[1].Hash())
|
||||||
|
|
||||||
require.Equal(t, s.length(), 2, "expected 2 items in whitelist")
|
//Make the mock chain with zero blocks
|
||||||
|
zeroChain := make([]*types.Header, 0)
|
||||||
|
|
||||||
// case2: We're behind the oldest whitelisted block entry, should consider
|
//Case2: As input chain is of zero length,should consider the chain as invalid
|
||||||
// the chain as valid as we're still far behind the latest blocks
|
res, err = s.IsValidChain(nil, zeroChain)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid", len(zeroChain))
|
||||||
|
|
||||||
|
//Case3A: As the received chain and current tip of local chain is behind the oldest whitelisted block entry, should consider
|
||||||
|
// the chain as valid
|
||||||
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
require.Equal(t, res, true, "expected chain to be valid")
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
require.Equal(t, err, nil, "expected error to be nil")
|
|
||||||
|
|
||||||
// Clear checkpoint whitelist and add blocks A5 and A15 in whitelist
|
//Case3B: As the received chain is behind the oldest whitelisted block entry,but current tip is at par with whitelisted checkpoint, should consider
|
||||||
s.PurgeCheckpointWhitelist()
|
// the chain as invalid
|
||||||
s.ProcessCheckpoint(chainA[5].Number.Uint64(), chainA[5].Hash())
|
res, err = s.IsValidChain(tempChain[1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid ")
|
||||||
|
|
||||||
|
// add mock milestone entry
|
||||||
|
s.ProcessMilestone(tempChain[1].Number.Uint64(), tempChain[1].Hash())
|
||||||
|
|
||||||
|
//Case4A: As the received chain and current tip of local chain is behind the oldest whitelisted block entry, should consider
|
||||||
|
// the chain as valid
|
||||||
|
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
|
|
||||||
|
//Case4B: As the received chain is behind the oldest whitelisted block entry and but current tip is at par with whitelisted milestine, should consider
|
||||||
|
// the chain as invalid
|
||||||
|
res, err = s.IsValidChain(tempChain[1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
|
|
||||||
|
//Remove the whitelisted checkpoint
|
||||||
|
s.PurgeWhitelistedCheckpoint()
|
||||||
|
|
||||||
|
//Case5: As the received chain is still invalid after removing the checkpoint as it is
|
||||||
|
//still behind the whitelisted milestone
|
||||||
|
res, err = s.IsValidChain(tempChain[1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
|
|
||||||
|
//Remove the whitelisted milestone
|
||||||
|
s.PurgeWhitelistedMilestone()
|
||||||
|
|
||||||
|
//At this stage there is no whitelisted milestone and checkpoint
|
||||||
|
|
||||||
|
checkpoint := s.checkpointService.(*checkpoint)
|
||||||
|
milestone := s.milestoneService.(*milestone)
|
||||||
|
|
||||||
|
//Locking for sprintNumber 15
|
||||||
|
milestone.LockMutex(chainA[len(chainA)-5].Number.Uint64())
|
||||||
|
milestone.UnlockMutex(true, "MilestoneID1", chainA[len(chainA)-5].Number.Uint64(), chainA[len(chainA)-5].Hash())
|
||||||
|
|
||||||
|
//Case6: As the received chain is valid as the locked sprintHash matches with the incoming chain.
|
||||||
|
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, true, "expected chain to be valid as incoming chain matches with the locked value ")
|
||||||
|
|
||||||
|
hash3 := common.Hash{3}
|
||||||
|
|
||||||
|
//Locking for sprintNumber 16 with different hash
|
||||||
|
milestone.LockMutex(chainA[len(chainA)-4].Number.Uint64())
|
||||||
|
milestone.UnlockMutex(true, "MilestoneID2", chainA[len(chainA)-4].Number.Uint64(), hash3)
|
||||||
|
|
||||||
|
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid as incoming chain does match with the locked value hash ")
|
||||||
|
|
||||||
|
//Locking for sprintNumber 19
|
||||||
|
milestone.LockMutex(chainA[len(chainA)-1].Number.Uint64())
|
||||||
|
milestone.UnlockMutex(true, "MilestoneID1", chainA[len(chainA)-1].Number.Uint64(), chainA[len(chainA)-1].Hash())
|
||||||
|
|
||||||
|
//Case7: As the received chain is valid as the locked sprintHash matches with the incoming chain.
|
||||||
|
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid as incoming chain is less than the locked value ")
|
||||||
|
|
||||||
|
//Locking for sprintNumber 19
|
||||||
|
milestone.LockMutex(uint64(21))
|
||||||
|
milestone.UnlockMutex(true, "MilestoneID1", uint64(21), hash3)
|
||||||
|
|
||||||
|
//Case8: As the received chain is invalid as the locked sprintHash matches is ahead of incoming chain.
|
||||||
|
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid as incoming chain is less than the locked value ")
|
||||||
|
|
||||||
|
//Unlocking the sprint
|
||||||
|
milestone.UnlockSprint(uint64(21))
|
||||||
|
|
||||||
|
// Clear checkpoint whitelist and add block A15 in whitelist
|
||||||
|
s.PurgeWhitelistedCheckpoint()
|
||||||
s.ProcessCheckpoint(chainA[15].Number.Uint64(), chainA[15].Hash())
|
s.ProcessCheckpoint(chainA[15].Number.Uint64(), chainA[15].Hash())
|
||||||
|
|
||||||
require.Equal(t, s.length(), 2, "expected 2 items in whitelist")
|
require.Equal(t, checkpoint.doExist, true, "expected true as checkpoint exists.")
|
||||||
|
|
||||||
// case3: Try importing a past chain having valid checkpoint, should
|
// case9: As the received chain is having valid checkpoint,should consider the chain as valid.
|
||||||
// consider the chain as valid
|
|
||||||
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
|
|
||||||
|
// add mock milestone entries
|
||||||
|
s.ProcessMilestone(tempChain[1].Number.Uint64(), tempChain[1].Hash())
|
||||||
|
|
||||||
|
// case10: Try importing a past chain having valid checkpoint, should
|
||||||
|
// consider the chain as invalid as still lastest milestone is ahead of the chain.
|
||||||
|
res, err = s.IsValidChain(tempChain[1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
|
|
||||||
|
// add mock milestone entries
|
||||||
|
s.ProcessMilestone(chainA[19].Number.Uint64(), chainA[19].Hash())
|
||||||
|
|
||||||
|
// case12: Try importing a chain having valid checkpoint and milestone, should
|
||||||
|
// consider the chain as valid
|
||||||
|
res, err = s.IsValidChain(tempChain[1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, true, "expected chain to be invalid")
|
||||||
|
|
||||||
|
// add mock milestone entries
|
||||||
|
s.ProcessMilestone(chainA[19].Number.Uint64(), chainA[19].Hash())
|
||||||
|
|
||||||
|
// case13: Try importing a past chain having valid checkpoint and milestone, should
|
||||||
|
// consider the chain as valid
|
||||||
|
res, err = s.IsValidChain(tempChain[1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
|
|
||||||
|
// add mock milestone entries with wrong hash
|
||||||
|
s.ProcessMilestone(chainA[19].Number.Uint64(), chainA[18].Hash())
|
||||||
|
|
||||||
|
// case14: Try importing a past chain having valid checkpoint and milestone with wrong hash, should
|
||||||
|
// consider the chain as invalid
|
||||||
|
res, err = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid as hash mismatches")
|
||||||
|
|
||||||
|
// Clear milestone and add blocks A15 in whitelist
|
||||||
|
s.ProcessMilestone(chainA[15].Number.Uint64(), chainA[15].Hash())
|
||||||
|
|
||||||
|
// case16: Try importing a past chain having valid checkpoint, should
|
||||||
|
// consider the chain as valid
|
||||||
|
res, err = s.IsValidChain(tempChain[1], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
require.Equal(t, res, true, "expected chain to be valid")
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
require.Equal(t, err, nil, "expected error to be nil")
|
|
||||||
|
|
||||||
// Clear checkpoint whitelist and mock blocks in whitelist
|
// Clear checkpoint whitelist and mock blocks in whitelist
|
||||||
tempChain = createMockChain(20, 20) // A20
|
tempChain = createMockChain(20, 20) // A20
|
||||||
|
|
||||||
s.PurgeCheckpointWhitelist()
|
s.PurgeWhitelistedCheckpoint()
|
||||||
s.ProcessCheckpoint(tempChain[0].Number.Uint64(), tempChain[0].Hash())
|
s.ProcessCheckpoint(tempChain[0].Number.Uint64(), tempChain[0].Hash())
|
||||||
|
|
||||||
require.Equal(t, s.length(), 1, "expected 1 items in whitelist")
|
require.Equal(t, checkpoint.doExist, true, "expected true")
|
||||||
|
|
||||||
// case4: Try importing a past chain having invalid checkpoint
|
// case17: Try importing a past chain having invalid checkpoint,should consider the chain as invalid
|
||||||
res, _ = s.IsValidChain(chainA[len(chainA)-1], chainA)
|
res, err = s.IsValidChain(tempChain[0], chainA)
|
||||||
|
require.Nil(t, err)
|
||||||
require.Equal(t, res, false, "expected chain to be invalid")
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
// Not checking error here because we return nil in case of checkpoint mismatch
|
// Not checking error here because we return nil in case of checkpoint mismatch
|
||||||
|
|
||||||
|
// case18: Try importing a future chain but within interval, should consider the chain as valid
|
||||||
|
res, err = s.IsValidChain(tempChain[len(tempChain)-1], tempChain)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, true, "expected chain to be invalid")
|
||||||
|
|
||||||
// create a future chain to be imported of length <= `checkpointInterval`
|
// create a future chain to be imported of length <= `checkpointInterval`
|
||||||
chainB := createMockChain(21, 30) // B21->B22...B29->B30
|
chainB := createMockChain(21, 30) // B21->B22...B29->B30
|
||||||
|
|
||||||
// case5: Try importing a future chain (1)
|
// case19: Try importing a future chain of acceptable length,should consider the chain as valid
|
||||||
res, err = s.IsValidChain(chainA[len(chainA)-1], chainB)
|
res, err = s.IsValidChain(tempChain[0], chainB)
|
||||||
|
require.Nil(t, err)
|
||||||
require.Equal(t, res, true, "expected chain to be valid")
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
require.Equal(t, err, nil, "expected error to be nil")
|
|
||||||
|
|
||||||
// create a future chain to be imported of length > `checkpointInterval`
|
s.PurgeWhitelistedCheckpoint()
|
||||||
chainB = createMockChain(21, 40) // C21->C22...C39->C40
|
s.PurgeWhitelistedMilestone()
|
||||||
|
|
||||||
// Note: Earlier, it used to reject future chains longer than some threshold.
|
chainB = createMockChain(21, 29) // C21->C22....C29
|
||||||
// That check is removed for now.
|
|
||||||
|
|
||||||
// case6: Try importing a future chain (2)
|
s.milestoneService.ProcessFutureMilestone(29, chainB[8].Hash())
|
||||||
res, err = s.IsValidChain(chainA[len(chainA)-1], chainB)
|
|
||||||
|
// case20: Try importing a future chain which match the future milestone should the chain as valid
|
||||||
|
res, err = s.IsValidChain(tempChain[0], chainB)
|
||||||
|
require.Nil(t, err)
|
||||||
require.Equal(t, res, true, "expected chain to be valid")
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
require.Equal(t, err, nil, "expected error to be nil")
|
|
||||||
|
chainB = createMockChain(21, 27) // C21->C22...C39->C40...C->256
|
||||||
|
|
||||||
|
// case21: Try importing a chain whose end point is less than future milestone
|
||||||
|
res, err = s.IsValidChain(tempChain[0], chainB)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, true, "expected chain to be valid")
|
||||||
|
|
||||||
|
chainB = createMockChain(30, 39) // C21->C22...C39->C40...C->256
|
||||||
|
|
||||||
|
//Processing wrong hash
|
||||||
|
s.milestoneService.ProcessFutureMilestone(38, chainB[9].Hash())
|
||||||
|
|
||||||
|
// case22: Try importing a future chain with mismatch future milestone
|
||||||
|
res, err = s.IsValidChain(tempChain[0], chainB)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, false, "expected chain to be invalid")
|
||||||
|
|
||||||
|
chainB = createMockChain(40, 49) // C40->C41...C48->C49
|
||||||
|
|
||||||
|
// case23: Try importing a future chain whose starting point is ahead of latest future milestone
|
||||||
|
res, err = s.IsValidChain(tempChain[0], chainB)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, res, true, "expected chain to be invalid")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPropertyBasedTestingMilestone(t *testing.T) {
|
||||||
|
rapid.Check(t, func(t *rapid.T) {
|
||||||
|
|
||||||
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
|
||||||
|
milestone := milestone{
|
||||||
|
finality: finality[*rawdb.Milestone]{
|
||||||
|
doExist: false,
|
||||||
|
Number: 0,
|
||||||
|
Hash: common.Hash{},
|
||||||
|
interval: 256,
|
||||||
|
db: db,
|
||||||
|
},
|
||||||
|
|
||||||
|
Locked: false,
|
||||||
|
LockedMilestoneNumber: 0,
|
||||||
|
LockedMilestoneHash: common.Hash{},
|
||||||
|
LockedMilestoneIDs: make(map[string]struct{}),
|
||||||
|
FutureMilestoneList: make(map[uint64]common.Hash),
|
||||||
|
FutureMilestoneOrder: make([]uint64, 0),
|
||||||
|
MaxCapacity: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
milestoneEndNum = rapid.Uint64().Draw(t, "endBlock")
|
||||||
|
milestoneID = rapid.String().Draw(t, "MilestoneID")
|
||||||
|
doLock = rapid.Bool().Draw(t, "Voted")
|
||||||
|
)
|
||||||
|
|
||||||
|
val := milestone.LockMutex(milestoneEndNum.(uint64))
|
||||||
|
if !val {
|
||||||
|
t.Error("LockMutex need to return true when there is no whitelisted milestone and locked milestone")
|
||||||
|
}
|
||||||
|
|
||||||
|
milestone.UnlockMutex(doLock.(bool), milestoneID.(string), milestoneEndNum.(uint64), common.Hash{})
|
||||||
|
|
||||||
|
if doLock.(bool) {
|
||||||
|
//Milestone should not be whitelisted
|
||||||
|
if milestone.doExist {
|
||||||
|
t.Error("Milestone is not expected to be whitelisted")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Local chain should be locked
|
||||||
|
if !milestone.Locked {
|
||||||
|
t.Error("Milestone is expected to be locked at", milestoneEndNum.(uint64))
|
||||||
|
}
|
||||||
|
|
||||||
|
if milestone.LockedMilestoneNumber != milestoneEndNum.(uint64) {
|
||||||
|
t.Error("Locked milestone number is expected to be", milestoneEndNum.(uint64))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(milestone.LockedMilestoneIDs) != 1 {
|
||||||
|
t.Error("List should contain 1 milestone")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := milestone.LockedMilestoneIDs[milestoneID.(string)]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
t.Error("List doesn't contain correct milestoneID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doLock.(bool) {
|
||||||
|
if milestone.doExist {
|
||||||
|
t.Error("Milestone is not expected to be whitelisted")
|
||||||
|
}
|
||||||
|
|
||||||
|
if milestone.Locked {
|
||||||
|
t.Error("Milestone is expected not to be locked")
|
||||||
|
}
|
||||||
|
|
||||||
|
if milestone.LockedMilestoneNumber != 0 {
|
||||||
|
t.Error("Locked milestone number is expected to be", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(milestone.LockedMilestoneIDs) != 0 {
|
||||||
|
t.Error("List should not contain milestone")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := milestone.LockedMilestoneIDs[milestoneID.(string)]
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
t.Error("List shouldn't contain any milestoneID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fitlerFn := func(i uint64) bool {
|
||||||
|
if i <= uint64(1000) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
start = rapid.Uint64Max(milestoneEndNum.(uint64)).Draw(t, "start for mock chain")
|
||||||
|
end = rapid.Uint64Min(start.(uint64)).Filter(fitlerFn).Draw(t, "end for mock chain")
|
||||||
|
)
|
||||||
|
|
||||||
|
chainTemp := createMockChain(start.(uint64), end.(uint64))
|
||||||
|
|
||||||
|
val, err := milestone.IsValidChain(chainTemp[0], chainTemp)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if doLock.(bool) && val {
|
||||||
|
t.Error("When the chain is locked at milestone, it should not pass IsValidChain for incompatible incoming chain")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doLock.(bool) && !val {
|
||||||
|
t.Error("When the chain is not locked at milestone, it should pass IsValidChain for incoming chain")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
milestoneEndNum2 = rapid.Uint64().Draw(t, "endBlockNum 2")
|
||||||
|
milestoneID2 = rapid.String().Draw(t, "MilestoneID 2")
|
||||||
|
doLock2 = rapid.Bool().Draw(t, "Voted 2")
|
||||||
|
)
|
||||||
|
|
||||||
|
val = milestone.LockMutex(milestoneEndNum2.(uint64))
|
||||||
|
|
||||||
|
if doLock.(bool) && milestoneEndNum.(uint64) > milestoneEndNum2.(uint64) && val {
|
||||||
|
t.Error("LockMutex need to return false as previous locked milestone is greater")
|
||||||
|
}
|
||||||
|
|
||||||
|
if doLock.(bool) && milestoneEndNum.(uint64) <= milestoneEndNum2.(uint64) && !val {
|
||||||
|
t.Error("LockMutex need to return true as previous locked milestone is less")
|
||||||
|
}
|
||||||
|
|
||||||
|
milestone.UnlockMutex(doLock2.(bool), milestoneID2.(string), milestoneEndNum2.(uint64), common.Hash{})
|
||||||
|
|
||||||
|
if doLock2.(bool) {
|
||||||
|
if milestone.doExist {
|
||||||
|
t.Error("Milestone is not expected to be whitelisted")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !milestone.Locked {
|
||||||
|
t.Error("Milestone is expected to be locked at", milestoneEndNum2.(uint64))
|
||||||
|
}
|
||||||
|
|
||||||
|
if milestone.LockedMilestoneNumber != milestoneEndNum2.(uint64) {
|
||||||
|
t.Error("Locked milestone number is expected to be", milestoneEndNum.(uint64))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(milestone.LockedMilestoneIDs) != 1 {
|
||||||
|
t.Error("List should contain 1 milestone")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := milestone.LockedMilestoneIDs[milestoneID2.(string)]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
t.Error("List doesn't contain correct milestoneID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doLock2.(bool) {
|
||||||
|
if milestone.doExist {
|
||||||
|
t.Error("Milestone is not expected to be whitelisted")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doLock.(bool) && milestone.Locked {
|
||||||
|
t.Error("Milestone is expected not to be locked")
|
||||||
|
}
|
||||||
|
|
||||||
|
if doLock.(bool) && !milestone.Locked {
|
||||||
|
t.Error("Milestone is expected to be locked at", milestoneEndNum.(uint64))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doLock.(bool) && milestone.LockedMilestoneNumber != 0 {
|
||||||
|
t.Error("Locked milestone number is expected to be", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if doLock.(bool) && milestone.LockedMilestoneNumber != milestoneEndNum.(uint64) {
|
||||||
|
t.Error("Locked milestone number is expected to be", milestoneEndNum.(uint64))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doLock.(bool) && len(milestone.LockedMilestoneIDs) != 0 {
|
||||||
|
t.Error("List should not contain milestone")
|
||||||
|
}
|
||||||
|
|
||||||
|
if doLock.(bool) && len(milestone.LockedMilestoneIDs) != 1 {
|
||||||
|
t.Error("List should not contain milestone")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := milestone.LockedMilestoneIDs[milestoneID.(string)]
|
||||||
|
|
||||||
|
if !doLock.(bool) && ok {
|
||||||
|
t.Error("List shouldn't contain any milestoneID")
|
||||||
|
}
|
||||||
|
|
||||||
|
if doLock.(bool) && !ok {
|
||||||
|
t.Error("List should contain milestoneID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
milestoneNum = rapid.Uint64().Draw(t, "milestone Number")
|
||||||
|
)
|
||||||
|
|
||||||
|
lockedValue := milestone.LockedMilestoneNumber
|
||||||
|
|
||||||
|
milestone.Process(milestoneNum.(uint64), common.Hash{})
|
||||||
|
|
||||||
|
isChainLocked := doLock.(bool) || doLock2.(bool)
|
||||||
|
|
||||||
|
if !milestone.doExist {
|
||||||
|
t.Error("Should have the whitelisted milestone")
|
||||||
|
}
|
||||||
|
|
||||||
|
if milestone.finality.Number != milestoneNum.(uint64) {
|
||||||
|
t.Error("Should have the whitelisted milestone", milestoneNum.(uint64))
|
||||||
|
}
|
||||||
|
|
||||||
|
if isChainLocked {
|
||||||
|
if milestoneNum.(uint64) < lockedValue {
|
||||||
|
if !milestone.Locked {
|
||||||
|
t.Error("Milestone is expected to be locked")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if milestone.Locked {
|
||||||
|
t.Error("Milestone is expected not to be locked")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
futureMilestoneNum = rapid.Uint64Min(milestoneNum.(uint64)).Draw(t, "future milestone Number")
|
||||||
|
)
|
||||||
|
|
||||||
|
isChainLocked = milestone.Locked
|
||||||
|
|
||||||
|
milestone.ProcessFutureMilestone(futureMilestoneNum.(uint64), common.Hash{})
|
||||||
|
|
||||||
|
if isChainLocked {
|
||||||
|
if futureMilestoneNum.(uint64) < lockedValue {
|
||||||
|
if !milestone.Locked {
|
||||||
|
t.Error("Milestone is expected to be locked")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if milestone.Locked {
|
||||||
|
t.Error("Milestone is expected not to be locked")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSplitChain(t *testing.T) {
|
func TestSplitChain(t *testing.T) {
|
||||||
|
|
@ -384,11 +1114,12 @@ func TestSplitChainProperties(t *testing.T) {
|
||||||
// starting from `start` to `end` (inclusive)
|
// starting from `start` to `end` (inclusive)
|
||||||
func createMockChain(start, end uint64) []*types.Header {
|
func createMockChain(start, end uint64) []*types.Header {
|
||||||
var (
|
var (
|
||||||
i uint64
|
i uint64
|
||||||
idx uint64
|
idx uint64
|
||||||
chain []*types.Header = make([]*types.Header, end-start+1)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
chain := make([]*types.Header, end-start+1)
|
||||||
|
|
||||||
for i = start; i <= end; i++ {
|
for i = start; i <= end; i++ {
|
||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
Number: big.NewInt(int64(i)),
|
Number: big.NewInt(int64(i)),
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,21 @@ func (mr *MockBackendMockRecorder) GetReceipts(arg0, arg1 interface{}) *gomock.C
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipts", reflect.TypeOf((*MockBackend)(nil).GetReceipts), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipts", reflect.TypeOf((*MockBackend)(nil).GetReceipts), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetVoteOnHash mocks base method.
|
||||||
|
func (m *MockBackend) GetVoteOnHash(arg0 context.Context, arg1, arg2 uint64, arg3, arg4 string) (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetVoteOnHash", arg0, arg1, arg2, arg3, arg4)
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVoteOnHash indicates an expected call of GetVoteOnHash.
|
||||||
|
func (mr *MockBackendMockRecorder) GetVoteOnHash(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVoteOnHash", reflect.TypeOf((*MockBackend)(nil).GetVoteOnHash), arg0, arg1, arg2, arg3, arg4)
|
||||||
|
}
|
||||||
|
|
||||||
// HeaderByHash mocks base method.
|
// HeaderByHash mocks base method.
|
||||||
func (m *MockBackend) HeaderByHash(arg0 context.Context, arg1 common.Hash) (*types.Header, error) {
|
func (m *MockBackend) HeaderByHash(arg0 context.Context, arg1 common.Hash) (*types.Header, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|
|
||||||
|
|
@ -495,6 +495,8 @@ func TestInvalidGetLogsRequest(t *testing.T) {
|
||||||
blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
|
blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
api.SetChainConfig(params.BorUnittestChainConfig)
|
||||||
|
|
||||||
// Reason: Cannot specify both BlockHash and FromBlock/ToBlock)
|
// Reason: Cannot specify both BlockHash and FromBlock/ToBlock)
|
||||||
testCases := []FilterCriteria{
|
testCases := []FilterCriteria{
|
||||||
0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
|
0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,10 @@ func (b *TestBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *TestBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *TestBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
|
func (b *TestBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
|
||||||
block := rawdb.ReadBlock(b.DB, hash, number)
|
block := rawdb.ReadBlock(b.DB, hash, number)
|
||||||
receipts := rawdb.ReadReceipts(b.DB, hash, number, block.Time(), params.TestChainConfig)
|
receipts := rawdb.ReadReceipts(b.DB, hash, number, block.Time(), params.TestChainConfig)
|
||||||
|
|
|
||||||
|
|
@ -10,94 +10,112 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// errCheckpointCount is returned when we are unable to fetch
|
|
||||||
// the checkpoint count from local heimdall.
|
|
||||||
errCheckpointCount = errors.New("failed to fetch checkpoint count")
|
|
||||||
|
|
||||||
// errNoCheckpoint is returned when there is not checkpoint proposed
|
|
||||||
// by heimdall yet or heimdall is not in sync
|
|
||||||
errNoCheckpoint = errors.New("no checkpoint proposed")
|
|
||||||
|
|
||||||
// errCheckpoint is returned when we are unable to fetch the
|
// errCheckpoint is returned when we are unable to fetch the
|
||||||
// latest checkpoint from the local heimdall.
|
// latest checkpoint from the local heimdall.
|
||||||
errCheckpoint = errors.New("failed to fetch latest checkpoint")
|
errCheckpoint = errors.New("failed to fetch latest checkpoint")
|
||||||
|
|
||||||
// errMissingCheckpoint is returned when we don't have the
|
// errMilestone is returned when we are unable to fetch the
|
||||||
// checkpoint blocks locally, yet.
|
// latest milestone from the local heimdall.
|
||||||
errMissingCheckpoint = errors.New("missing checkpoint blocks")
|
errMilestone = errors.New("failed to fetch latest milestone")
|
||||||
|
|
||||||
// errRootHash is returned when we aren't able to calculate the root hash
|
ErrNotInRejectedList = errors.New("MilestoneID not in rejected list")
|
||||||
// locally for a range of blocks.
|
|
||||||
errRootHash = errors.New("failed to get local root hash")
|
|
||||||
|
|
||||||
// errCheckpointRootHashMismatch is returned when the local root hash
|
|
||||||
// doesn't match with the root hash in checkpoint.
|
|
||||||
errCheckpointRootHashMismatch = errors.New("checkpoint roothash mismatch")
|
|
||||||
|
|
||||||
// errEndBlock is returned when we're unable to fetch a block locally.
|
|
||||||
errEndBlock = errors.New("failed to get end block")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// fetchWhitelistCheckpoints fetches the latest checkpoint/s from it's local heimdall
|
// fetchWhitelistCheckpoint fetches the latest checkpoint from it's local heimdall
|
||||||
// and verifies the data against bor data.
|
// and verifies the data against bor data.
|
||||||
func (h *ethHandler) fetchWhitelistCheckpoints(ctx context.Context, bor *bor.Bor, checkpointVerifier *checkpointVerifier, first bool) ([]uint64, []common.Hash, error) {
|
func (h *ethHandler) fetchWhitelistCheckpoint(ctx context.Context, bor *bor.Bor, eth *Ethereum, verifier *borVerifier) (uint64, common.Hash, error) {
|
||||||
// Create an array for block number and block hashes
|
|
||||||
//nolint:prealloc
|
|
||||||
var (
|
var (
|
||||||
blockNums []uint64 = make([]uint64, 0)
|
blockNum uint64
|
||||||
blockHashes []common.Hash = make([]common.Hash, 0)
|
blockHash common.Hash
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fetch the checkpoint count from heimdall
|
// fetch the latest checkpoint from Heimdall
|
||||||
count, err := bor.HeimdallClient.FetchCheckpointCount(ctx)
|
checkpoint, err := bor.HeimdallClient.FetchCheckpoint(ctx, -1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Failed to fetch checkpoint count for whitelisting", "err", err)
|
log.Debug("Failed to fetch latest checkpoint for whitelisting", "err", err)
|
||||||
return blockNums, blockHashes, errCheckpointCount
|
return blockNum, blockHash, errCheckpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
if count == 0 {
|
log.Info("Got new checkpoint from heimdall", "start", checkpoint.StartBlock.Uint64(), "end", checkpoint.EndBlock.Uint64(), "rootHash", checkpoint.RootHash.String())
|
||||||
return blockNums, blockHashes, errNoCheckpoint
|
|
||||||
|
// Verify if the checkpoint fetched can be added to the local whitelist entry or not
|
||||||
|
// If verified, it returns the hash of the end block of the checkpoint. If not,
|
||||||
|
// it will return appropriate error.
|
||||||
|
hash, err := verifier.verify(ctx, eth, h, checkpoint.StartBlock.Uint64(), checkpoint.EndBlock.Uint64(), checkpoint.RootHash.String()[2:], true)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Failed to whitelist checkpoint", "err", err)
|
||||||
|
return blockNum, blockHash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blockNum = checkpoint.EndBlock.Uint64()
|
||||||
|
blockHash = common.HexToHash(hash)
|
||||||
|
|
||||||
|
return blockNum, blockHash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchWhitelistMilestone fetches the latest milestone from it's local heimdall
|
||||||
|
// and verifies the data against bor data.
|
||||||
|
func (h *ethHandler) fetchWhitelistMilestone(ctx context.Context, bor *bor.Bor, eth *Ethereum, verifier *borVerifier) (uint64, common.Hash, error) {
|
||||||
var (
|
var (
|
||||||
start int64
|
num uint64
|
||||||
end int64
|
hash common.Hash
|
||||||
)
|
)
|
||||||
|
|
||||||
// Prepare the checkpoint range to fetch
|
// fetch latest milestone
|
||||||
if count <= 10 {
|
milestone, err := bor.HeimdallClient.FetchMilestone(ctx)
|
||||||
start = 1
|
if err != nil {
|
||||||
} else {
|
log.Error("Failed to fetch latest milestone for whitelisting", "err", err)
|
||||||
start = count - 10 + 1 // 10 is the max number of checkpoints to fetch
|
return num, hash, errMilestone
|
||||||
}
|
}
|
||||||
|
|
||||||
end = count
|
num = milestone.EndBlock.Uint64()
|
||||||
|
hash = milestone.Hash
|
||||||
|
|
||||||
// If we're in not in the first iteration, only fetch the latest checkpoint
|
log.Info("Got new milestone from heimdall", "start", milestone.StartBlock.Uint64(), "end", milestone.EndBlock.Uint64(), "hash", milestone.Hash.String())
|
||||||
if !first {
|
|
||||||
start = count
|
// Verify if the milestone fetched can be added to the local whitelist entry or not
|
||||||
|
// If verified, it returns the hash of the end block of the milestone. If not,
|
||||||
|
// it will return appropriate error.
|
||||||
|
_, err = verifier.verify(ctx, eth, h, milestone.StartBlock.Uint64(), milestone.EndBlock.Uint64(), milestone.Hash.String()[2:], false)
|
||||||
|
if err != nil {
|
||||||
|
h.downloader.UnlockSprint(milestone.EndBlock.Uint64())
|
||||||
|
return num, hash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := start; i <= end; i++ {
|
return num, hash, nil
|
||||||
// fetch `i` indexed checkpoint from heimdall
|
}
|
||||||
checkpoint, err := bor.HeimdallClient.FetchCheckpoint(ctx, i)
|
|
||||||
if err != nil {
|
func (h *ethHandler) fetchNoAckMilestone(ctx context.Context, bor *bor.Bor) (string, error) {
|
||||||
log.Debug("Failed to fetch latest checkpoint for whitelisting", "err", err)
|
var (
|
||||||
return blockNums, blockHashes, errCheckpoint
|
milestoneID string
|
||||||
}
|
)
|
||||||
|
|
||||||
// Verify if the checkpoint fetched can be added to the local whitelist entry or not
|
// fetch latest milestone
|
||||||
// If verified, it returns the hash of the end block of the checkpoint. If not,
|
milestoneID, err := bor.HeimdallClient.FetchLastNoAckMilestone(ctx)
|
||||||
// it will return appropriate error.
|
if err != nil {
|
||||||
|
log.Error("Failed to fetch latest no-ack milestone", "err", err)
|
||||||
hash, err := checkpointVerifier.verify(ctx, h, checkpoint)
|
|
||||||
if err != nil {
|
return milestoneID, errMilestone
|
||||||
return blockNums, blockHashes, err
|
}
|
||||||
}
|
|
||||||
|
return milestoneID, nil
|
||||||
blockNums = append(blockNums, checkpoint.EndBlock.Uint64())
|
}
|
||||||
blockHashes = append(blockHashes, common.HexToHash(hash))
|
|
||||||
}
|
func (h *ethHandler) fetchNoAckMilestoneByID(ctx context.Context, bor *bor.Bor, milestoneID string) error {
|
||||||
|
// fetch latest milestone
|
||||||
return blockNums, blockHashes, nil
|
err := bor.HeimdallClient.FetchNoAckMilestone(ctx, milestoneID)
|
||||||
|
|
||||||
|
// fixme: handle different types of errors
|
||||||
|
if errors.Is(err, ErrNotInRejectedList) {
|
||||||
|
log.Warn("MilestoneID not in rejected list", "milestoneID", milestoneID, "err", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to fetch no-ack milestone by ID ", "milestoneID", milestoneID, "err", err)
|
||||||
|
|
||||||
|
return errMilestone
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,17 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor"
|
"github.com/ethereum/go-ethereum/consensus/bor"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/milestone"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
"github.com/ethereum/go-ethereum/consensus/bor/heimdall/span"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockHeimdall struct {
|
type mockHeimdall struct {
|
||||||
fetchCheckpoint func(ctx context.Context, number int64) (*checkpoint.Checkpoint, error)
|
fetchCheckpoint func(ctx context.Context, number int64) (*checkpoint.Checkpoint, error)
|
||||||
fetchCheckpointCount func(ctx context.Context) (int64, error)
|
fetchCheckpointCount func(ctx context.Context) (int64, error)
|
||||||
|
fetchMilestone func(ctx context.Context) (*milestone.Milestone, error)
|
||||||
|
fetchMilestoneCount func(ctx context.Context) (int64, error)
|
||||||
|
fetchNoAckMilestone func(ctx context.Context, milestoneID string) error
|
||||||
|
fetchLastNoAckMilestone func(ctx context.Context) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockHeimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) {
|
func (m *mockHeimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) {
|
||||||
|
|
@ -33,78 +38,112 @@ func (m *mockHeimdall) FetchCheckpoint(ctx context.Context, number int64) (*chec
|
||||||
func (m *mockHeimdall) FetchCheckpointCount(ctx context.Context) (int64, error) {
|
func (m *mockHeimdall) FetchCheckpointCount(ctx context.Context) (int64, error) {
|
||||||
return m.fetchCheckpointCount(ctx)
|
return m.fetchCheckpointCount(ctx)
|
||||||
}
|
}
|
||||||
|
func (m *mockHeimdall) FetchMilestone(ctx context.Context) (*milestone.Milestone, error) {
|
||||||
|
return m.fetchMilestone(ctx)
|
||||||
|
}
|
||||||
|
func (m *mockHeimdall) FetchMilestoneCount(ctx context.Context) (int64, error) {
|
||||||
|
return m.fetchMilestoneCount(ctx)
|
||||||
|
}
|
||||||
|
func (m *mockHeimdall) FetchNoAckMilestone(ctx context.Context, milestoneID string) error {
|
||||||
|
return m.fetchNoAckMilestone(ctx, milestoneID)
|
||||||
|
}
|
||||||
|
func (m *mockHeimdall) FetchLastNoAckMilestone(ctx context.Context) (string, error) {
|
||||||
|
return m.fetchLastNoAckMilestone(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockHeimdall) FetchMilestoneID(ctx context.Context, milestoneID string) error {
|
||||||
|
return m.fetchNoAckMilestone(ctx, milestoneID)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *mockHeimdall) Close() {}
|
func (m *mockHeimdall) Close() {}
|
||||||
|
|
||||||
func TestFetchWhitelistCheckpoints(t *testing.T) {
|
func TestFetchWhitelistCheckpointAndMilestone(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// create an empty ethHandler
|
// create an empty ethHandler
|
||||||
handler := ðHandler{}
|
handler := ðHandler{}
|
||||||
|
|
||||||
// create a mock checkpoint verification function and use it to create a verifier
|
// create a mock checkpoint verification function and use it to create a verifier
|
||||||
verify := func(ctx context.Context, handler *ethHandler, checkpoint *checkpoint.Checkpoint) (string, error) {
|
verify := func(ctx context.Context, eth *Ethereum, handler *ethHandler, start uint64, end uint64, hash string, isCheckpoint bool) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
verifier := newCheckpointVerifier(verify)
|
verifier := newBorVerifier()
|
||||||
|
verifier.setVerify(verify)
|
||||||
|
|
||||||
// Create a mock heimdall instance and use it for creating a bor instance
|
// Create a mock heimdall instance and use it for creating a bor instance
|
||||||
var heimdall mockHeimdall
|
var heimdall mockHeimdall
|
||||||
|
|
||||||
bor := &bor.Bor{HeimdallClient: &heimdall}
|
bor := &bor.Bor{HeimdallClient: &heimdall}
|
||||||
|
|
||||||
// create 20 mock checkpoints
|
fetchCheckpointTest(t, &heimdall, bor, handler, verifier)
|
||||||
checkpoints := createMockCheckpoints(20)
|
fetchMilestoneTest(t, &heimdall, bor, handler, verifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *borVerifier) setVerify(verifyFn func(ctx context.Context, eth *Ethereum, handler *ethHandler, start uint64, end uint64, hash string, isCheckpoint bool) (string, error)) {
|
||||||
|
b.verify = verifyFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchCheckpointTest(t *testing.T, heimdall *mockHeimdall, bor *bor.Bor, handler *ethHandler, verifier *borVerifier) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var checkpoints []*checkpoint.Checkpoint
|
||||||
// create a mock fetch checkpoint function
|
// create a mock fetch checkpoint function
|
||||||
heimdall.fetchCheckpoint = func(_ context.Context, number int64) (*checkpoint.Checkpoint, error) {
|
heimdall.fetchCheckpoint = func(_ context.Context, number int64) (*checkpoint.Checkpoint, error) {
|
||||||
return checkpoints[number-1], nil // we're sure that number won't exceed 20
|
if len(checkpoints) == 0 {
|
||||||
|
return nil, errCheckpoint
|
||||||
|
} else if number == -1 {
|
||||||
|
return checkpoints[len(checkpoints)-1], nil
|
||||||
|
} else {
|
||||||
|
return checkpoints[number-1], nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a background context
|
// create a background context
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
testCases := []struct {
|
_, _, err := handler.fetchWhitelistCheckpoint(ctx, bor, nil, verifier)
|
||||||
name string
|
require.Equal(t, err, errCheckpoint)
|
||||||
first bool
|
|
||||||
count int64
|
|
||||||
length int
|
|
||||||
start uint64
|
|
||||||
end uint64
|
|
||||||
fetchErr error
|
|
||||||
expectedErr error
|
|
||||||
}{
|
|
||||||
{"fail to fetch checkpoint count", false, 0, 0, 0, 0, errCheckpointCount, errCheckpointCount},
|
|
||||||
{"no checkpoints available", false, 0, 0, 0, 0, nil, errNoCheckpoint},
|
|
||||||
{"fetch multiple checkpoints (count < 10)", true, 6, 6, 0, 6, nil, nil},
|
|
||||||
{"fetch multiple checkpoints (count = 10)", true, 10, 10, 0, 10, nil, nil},
|
|
||||||
{"fetch multiple checkpoints (count > 10)", true, 16, 10, 6, 16, nil, nil},
|
|
||||||
{"fetch single checkpoint", false, 18, 1, 17, 18, nil, nil},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
// create 4 mock checkpoints
|
||||||
tc := tc
|
checkpoints = createMockCheckpoints(4)
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
heimdall.fetchCheckpointCount = getMockFetchCheckpointFn(tc.count, tc.fetchErr)
|
blockNum, blockHash, err := handler.fetchWhitelistCheckpoint(ctx, bor, nil, verifier)
|
||||||
blockNums, blockHashes, err := handler.fetchWhitelistCheckpoints(ctx, bor, verifier, tc.first)
|
|
||||||
|
|
||||||
// Check if we have expected result
|
// Check if we have expected result
|
||||||
require.Equal(t, tc.expectedErr, err)
|
require.Equal(t, err, nil)
|
||||||
require.Equal(t, tc.length, len(blockNums))
|
require.Equal(t, checkpoints[len(checkpoints)-1].EndBlock.Uint64(), blockNum)
|
||||||
require.Equal(t, tc.length, len(blockHashes))
|
require.Equal(t, checkpoints[len(checkpoints)-1].RootHash, blockHash)
|
||||||
validateBlockNumber(t, blockNums, checkpoints[tc.start:tc.end])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateBlockNumber(t *testing.T, blockNums []uint64, checkpoints []*checkpoint.Checkpoint) {
|
func fetchMilestoneTest(t *testing.T, heimdall *mockHeimdall, bor *bor.Bor, handler *ethHandler, verifier *borVerifier) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
for i, blockNum := range blockNums {
|
var milestones []*milestone.Milestone
|
||||||
require.Equal(t, blockNum, checkpoints[i].EndBlock.Uint64(), "expect block number in array to match with checkpoint")
|
// create a mock fetch checkpoint function
|
||||||
|
heimdall.fetchMilestone = func(_ context.Context) (*milestone.Milestone, error) {
|
||||||
|
if len(milestones) == 0 {
|
||||||
|
return nil, errMilestone
|
||||||
|
} else {
|
||||||
|
return milestones[len(milestones)-1], nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create a background context
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
_, _, err := handler.fetchWhitelistMilestone(ctx, bor, nil, verifier)
|
||||||
|
require.Equal(t, err, errMilestone)
|
||||||
|
|
||||||
|
// create 4 mock checkpoints
|
||||||
|
milestones = createMockMilestones(4)
|
||||||
|
|
||||||
|
num, hash, err := handler.fetchWhitelistMilestone(ctx, bor, nil, verifier)
|
||||||
|
|
||||||
|
// Check if we have expected result
|
||||||
|
require.Equal(t, err, nil)
|
||||||
|
require.Equal(t, milestones[len(milestones)-1].EndBlock.Uint64(), num)
|
||||||
|
require.Equal(t, milestones[len(milestones)-1].Hash, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMockFetchCheckpointFn(number int64, err error) func(ctx context.Context) (int64, error) {
|
func getMockFetchCheckpointFn(number int64, err error) func(ctx context.Context) (int64, error) {
|
||||||
|
|
@ -133,3 +172,24 @@ func createMockCheckpoints(count int) []*checkpoint.Checkpoint {
|
||||||
|
|
||||||
return checkpoints
|
return checkpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createMockMilestones(count int) []*milestone.Milestone {
|
||||||
|
var (
|
||||||
|
milestones []*milestone.Milestone = make([]*milestone.Milestone, count)
|
||||||
|
startBlock int64 = 257 // any number can be used
|
||||||
|
)
|
||||||
|
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
milestones[i] = &milestone.Milestone{
|
||||||
|
Proposer: common.Address{},
|
||||||
|
StartBlock: big.NewInt(startBlock),
|
||||||
|
EndBlock: big.NewInt(startBlock + 255),
|
||||||
|
Hash: common.Hash{},
|
||||||
|
BorChainID: "137",
|
||||||
|
Timestamp: uint64(time.Now().Unix()),
|
||||||
|
}
|
||||||
|
startBlock += 256
|
||||||
|
}
|
||||||
|
|
||||||
|
return milestones
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,23 @@ import (
|
||||||
// GetRootHash returns the merkle root of the block headers
|
// GetRootHash returns the merkle root of the block headers
|
||||||
func (ec *Client) GetRootHash(ctx context.Context, startBlockNumber uint64, endBlockNumber uint64) (string, error) {
|
func (ec *Client) GetRootHash(ctx context.Context, startBlockNumber uint64, endBlockNumber uint64) (string, error) {
|
||||||
var rootHash string
|
var rootHash string
|
||||||
if err := ec.c.CallContext(ctx, &rootHash, "eth_getRootHash", startBlockNumber, endBlockNumber); err != nil {
|
if err := ec.c.CallContext(ctx, &rootHash, "bor_getRootHash", startBlockNumber, endBlockNumber); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootHash, nil
|
return rootHash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRootHash returns the merkle root of the block headers
|
||||||
|
func (ec *Client) GetVoteOnHash(ctx context.Context, startBlockNumber uint64, endBlockNumber uint64, hash string, milestoneID string) (bool, error) {
|
||||||
|
var value bool
|
||||||
|
if err := ec.c.CallContext(ctx, &value, "bor_getVoteOnHash", startBlockNumber, endBlockNumber, hash, milestoneID); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetBorBlockReceipt returns bor block receipt
|
// GetBorBlockReceipt returns bor block receipt
|
||||||
func (ec *Client) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
func (ec *Client) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
var r *types.Receipt
|
var r *types.Receipt
|
||||||
|
|
|
||||||
70
go.mod
70
go.mod
|
|
@ -17,15 +17,15 @@ require (
|
||||||
github.com/cloudflare/cloudflare-go v0.14.0
|
github.com/cloudflare/cloudflare-go v0.14.0
|
||||||
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811
|
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811
|
||||||
github.com/consensys/gnark-crypto v0.10.0
|
github.com/consensys/gnark-crypto v0.10.0
|
||||||
github.com/cosmos/cosmos-sdk v0.37.4
|
github.com/cosmos/cosmos-sdk v0.46.2
|
||||||
github.com/crate-crypto/go-kzg-4844 v0.3.0
|
github.com/crate-crypto/go-kzg-4844 v0.3.0
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/deckarep/golang-set/v2 v2.1.0
|
github.com/deckarep/golang-set/v2 v2.1.0
|
||||||
github.com/docker/docker v1.6.2
|
github.com/docker/docker v24.0.5+incompatible
|
||||||
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3
|
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3
|
||||||
github.com/emirpasic/gods v1.18.1
|
github.com/emirpasic/gods v1.18.1
|
||||||
github.com/ethereum/c-kzg-4844 v0.3.1
|
github.com/ethereum/c-kzg-4844 v0.3.1
|
||||||
github.com/fatih/color v1.9.0
|
github.com/fatih/color v1.13.0
|
||||||
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e
|
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e
|
||||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
|
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
|
|
@ -55,12 +55,13 @@ require (
|
||||||
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
|
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2
|
github.com/jackpal/go-nat-pmp v1.0.2
|
||||||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
||||||
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/julienschmidt/httprouter v1.3.0
|
github.com/julienschmidt/httprouter v1.3.0
|
||||||
github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c
|
github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c
|
||||||
github.com/kylelemons/godebug v1.1.0
|
github.com/kylelemons/godebug v1.1.0
|
||||||
github.com/maticnetwork/crand v1.0.2
|
github.com/maticnetwork/crand v1.0.2
|
||||||
github.com/maticnetwork/heimdall v0.3.1-0.20230105132832-d0063f71e3f0
|
github.com/maticnetwork/heimdall v0.3.1-0.20230227104835-81bd1055b0bc
|
||||||
github.com/maticnetwork/polyproto v0.0.2
|
github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53
|
||||||
github.com/mattn/go-colorable v0.1.13
|
github.com/mattn/go-colorable v0.1.13
|
||||||
github.com/mattn/go-isatty v0.0.16
|
github.com/mattn/go-isatty v0.0.16
|
||||||
github.com/mitchellh/cli v1.1.2
|
github.com/mitchellh/cli v1.1.2
|
||||||
|
|
@ -94,10 +95,32 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cloud.google.com/go/compute v1.7.0 // indirect
|
||||||
|
cloud.google.com/go/iam v0.5.0 // indirect
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pborman/uuid v1.2.1 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||||
|
github.com/subosito/gotenv v1.4.1 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
cloud.google.com/go v0.104.0 // indirect
|
||||||
|
cloud.google.com/go/pubsub v1.3.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect
|
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
|
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect
|
||||||
github.com/DataDog/zstd v1.5.2 // indirect
|
github.com/DataDog/zstd v1.5.2 // indirect
|
||||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||||
|
github.com/agext/levenshtein v1.2.1 // indirect
|
||||||
|
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||||
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
|
||||||
|
github.com/aws/aws-sdk-go v1.34.28 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
|
||||||
github.com/aws/smithy-go v1.1.0 // indirect
|
github.com/aws/smithy-go v1.1.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.7.0 // indirect
|
github.com/bits-and-blooms/bitset v1.7.0 // indirect
|
||||||
|
|
@ -124,7 +147,7 @@ require (
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
||||||
github.com/mmcloughlin/addchain v0.4.0 // indirect
|
github.com/mmcloughlin/addchain v0.4.0 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||||
|
|
@ -146,7 +169,6 @@ require (
|
||||||
go.uber.org/goleak v1.1.12
|
go.uber.org/goleak v1.1.12
|
||||||
golang.org/x/mod v0.11.0 // indirect
|
golang.org/x/mod v0.11.0 // indirect
|
||||||
golang.org/x/net v0.10.0 // indirect
|
golang.org/x/net v0.10.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
|
|
||||||
google.golang.org/grpc v1.51.0
|
google.golang.org/grpc v1.51.0
|
||||||
google.golang.org/protobuf v1.28.1
|
google.golang.org/protobuf v1.28.1
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
|
@ -156,10 +178,6 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
|
|
||||||
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d // indirect
|
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d // indirect
|
||||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
|
||||||
|
|
@ -175,10 +193,10 @@ require (
|
||||||
github.com/go-kit/kit v0.10.0 // indirect
|
github.com/go-kit/kit v0.10.0 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||||
github.com/go-redis/redis v6.15.7+incompatible // indirect
|
github.com/go-redis/redis v6.15.7+incompatible // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/gomodule/redigo v2.0.0+incompatible // indirect
|
github.com/gomodule/redigo v2.0.0+incompatible // indirect
|
||||||
github.com/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
|
github.com/googleapis/gax-go/v2 v2.5.1 // indirect
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||||
|
|
@ -188,25 +206,21 @@ require (
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
|
||||||
github.com/jstemmer/go-junit-report v0.9.1 // indirect
|
|
||||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||||
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
||||||
github.com/magiconair/properties v1.8.1 // indirect
|
github.com/magiconair/properties v1.8.6 // indirect
|
||||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
|
||||||
github.com/posener/complete v1.1.1 // indirect
|
github.com/posener/complete v1.1.1 // indirect
|
||||||
github.com/rakyll/statik v0.1.7 // indirect
|
github.com/rakyll/statik v0.1.7 // indirect
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||||
github.com/spf13/afero v1.2.2 // indirect
|
github.com/spf13/afero v1.8.2 // indirect
|
||||||
github.com/spf13/cast v1.4.1 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/spf13/cobra v1.5.0 // indirect
|
github.com/spf13/cobra v1.5.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/spf13/viper v1.4.0 // indirect
|
github.com/spf13/viper v1.13.0 // indirect
|
||||||
github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71 // indirect
|
github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71 // indirect
|
||||||
github.com/stumble/gorocksdb v0.0.3 // indirect
|
github.com/stumble/gorocksdb v0.0.3 // indirect
|
||||||
github.com/tendermint/btcd v0.1.1 // indirect
|
github.com/tendermint/btcd v0.1.1 // indirect
|
||||||
|
|
@ -218,33 +232,27 @@ require (
|
||||||
github.com/xdg-go/scram v1.0.2 // indirect
|
github.com/xdg-go/scram v1.0.2 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.2 // indirect
|
github.com/xdg-go/stringprep v1.0.2 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
|
||||||
golang.org/x/oauth2 v0.3.0 // indirect
|
golang.org/x/oauth2 v0.3.0 // indirect
|
||||||
|
gotest.tools/v3 v3.5.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.65.0 // indirect
|
|
||||||
cloud.google.com/go/pubsub v1.3.1 // indirect
|
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver v1.5.0 // indirect
|
github.com/Masterminds/semver v1.5.0 // indirect
|
||||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||||
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae // indirect
|
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae // indirect
|
||||||
github.com/RichardKnop/machinery v1.7.4 // indirect
|
github.com/RichardKnop/machinery v1.7.4 // indirect
|
||||||
github.com/RichardKnop/redsync v1.2.0 // indirect
|
github.com/RichardKnop/redsync v1.2.0 // indirect
|
||||||
github.com/agext/levenshtein v1.2.1 // indirect
|
|
||||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
|
|
||||||
github.com/aws/aws-sdk-go v1.34.28 // indirect
|
|
||||||
github.com/zclconf/go-cty v1.8.0 // indirect
|
github.com/zclconf/go-cty v1.8.0 // indirect
|
||||||
github.com/zondax/hid v0.9.0 // indirect
|
github.com/zondax/hid v0.9.0 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.3.0 // indirect
|
go.mongodb.org/mongo-driver v1.3.0 // indirect
|
||||||
go.opencensus.io v0.22.6 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.2.0
|
go.opentelemetry.io/otel/trace v1.2.0
|
||||||
go.opentelemetry.io/proto/otlp v0.10.0 // indirect
|
go.opentelemetry.io/proto/otlp v0.10.0 // indirect
|
||||||
google.golang.org/api v0.34.0 // indirect
|
google.golang.org/api v0.97.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b // indirect
|
google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/cosmos/cosmos-sdk => github.com/maticnetwork/cosmos-sdk v0.37.5-0.20220311095845-81690c6a53e7
|
replace github.com/cosmos/cosmos-sdk => github.com/maticnetwork/cosmos-sdk v0.37.5-0.20220311095845-81690c6a53e7
|
||||||
|
|
|
||||||
269
go.sum
269
go.sum
|
|
@ -4,6 +4,7 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR
|
||||||
cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg=
|
cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg=
|
||||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
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.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
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.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
|
|
@ -14,8 +15,25 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP
|
||||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
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.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.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
|
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
|
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||||
|
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||||
|
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||||
|
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||||
|
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||||
|
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||||
|
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
||||||
|
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
||||||
|
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||||
|
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||||
|
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||||
|
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||||
|
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||||
|
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
||||||
|
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
||||||
|
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
|
||||||
|
cloud.google.com/go v0.104.0 h1:gSmWO7DY1vOm0MVU6DNXM11BWHHsTUmsC5cv1fuW5X8=
|
||||||
|
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
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.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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
|
@ -23,8 +41,19 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM
|
||||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
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/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
|
cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
|
||||||
|
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||||
|
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
|
||||||
|
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
|
||||||
|
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
||||||
|
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
||||||
|
cloud.google.com/go/compute v1.7.0 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk=
|
||||||
|
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
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/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
|
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
||||||
|
cloud.google.com/go/iam v0.5.0 h1:fz9X5zyTWBmamZsqvqZqD7khbifcZF/q+Z1J8pfhIUg=
|
||||||
|
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
|
||||||
|
cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo=
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
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.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.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
|
@ -35,6 +64,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
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.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
|
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||||
|
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
|
||||||
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
|
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||||
|
|
@ -209,6 +240,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||||
github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA=
|
github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA=
|
||||||
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
|
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
|
@ -290,8 +322,8 @@ github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/
|
||||||
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||||
github.com/docker/docker v1.6.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v1.6.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v1.6.2 h1:HlFGsy+9/xrgMmhmN+NGhCc5SHGJ7I+kHosRR1xc/aI=
|
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
|
||||||
github.com/docker/docker v1.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||||
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||||
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE=
|
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE=
|
||||||
|
|
@ -312,6 +344,7 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
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.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/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||||
|
|
@ -330,8 +363,9 @@ github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQD
|
||||||
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
|
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
|
||||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
|
||||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY=
|
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY=
|
||||||
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
|
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
|
||||||
|
|
@ -343,6 +377,7 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
|
||||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||||
|
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
|
|
@ -462,8 +497,9 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
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-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
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.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
|
@ -472,6 +508,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
||||||
github.com/golang/mock v1.4.1/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.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
|
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
|
@ -491,6 +528,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||||
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.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
|
@ -529,6 +567,8 @@ 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 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/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
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-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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
|
@ -536,6 +576,14 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/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-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-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
|
@ -546,9 +594,20 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
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/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.1.0 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw=
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.5.1 h1:kBRZU0PSuI7PspsSb/ChWoVResUcwNVIdpB049pKTiw=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo=
|
||||||
|
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||||
|
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
|
@ -621,6 +680,7 @@ github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixH
|
||||||
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
||||||
github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
|
github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/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/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
||||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
|
|
@ -674,7 +734,6 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
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.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
|
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o=
|
github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
|
@ -719,6 +778,7 @@ github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH6
|
||||||
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.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/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/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
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=
|
||||||
|
|
@ -744,8 +804,9 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
|
||||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||||
|
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||||
|
|
@ -755,10 +816,12 @@ github.com/maticnetwork/cosmos-sdk v0.37.5-0.20220311095845-81690c6a53e7 h1:8NoE
|
||||||
github.com/maticnetwork/cosmos-sdk v0.37.5-0.20220311095845-81690c6a53e7/go.mod h1:uW55Ru86N5o3L8SVkVL1TPE+mV/WRM2la8sC3TR/Ajc=
|
github.com/maticnetwork/cosmos-sdk v0.37.5-0.20220311095845-81690c6a53e7/go.mod h1:uW55Ru86N5o3L8SVkVL1TPE+mV/WRM2la8sC3TR/Ajc=
|
||||||
github.com/maticnetwork/crand v1.0.2 h1:Af0tAivC8zrxXDpGWNWVT/0s1fOz8w0eRbahZgURS8I=
|
github.com/maticnetwork/crand v1.0.2 h1:Af0tAivC8zrxXDpGWNWVT/0s1fOz8w0eRbahZgURS8I=
|
||||||
github.com/maticnetwork/crand v1.0.2/go.mod h1:/NRNL3bj2eYdqpWmoIP5puxndTpi0XRxpj5ZKxfHjyg=
|
github.com/maticnetwork/crand v1.0.2/go.mod h1:/NRNL3bj2eYdqpWmoIP5puxndTpi0XRxpj5ZKxfHjyg=
|
||||||
github.com/maticnetwork/heimdall v0.3.1-0.20230105132832-d0063f71e3f0 h1:MYTAcBs4y88GEzesT8eAU472ZfQSLluW0qgkZTzNgwM=
|
|
||||||
github.com/maticnetwork/heimdall v0.3.1-0.20230105132832-d0063f71e3f0/go.mod h1:A3bUSe9jjMQHEPPOUW1JytM3x2g3t+jvsbPY66KBPIs=
|
github.com/maticnetwork/heimdall v0.3.1-0.20230105132832-d0063f71e3f0/go.mod h1:A3bUSe9jjMQHEPPOUW1JytM3x2g3t+jvsbPY66KBPIs=
|
||||||
github.com/maticnetwork/polyproto v0.0.2 h1:cPxuxbIDItdwGnucc3lZB58U8Zfe1mH73PWTGd15554=
|
github.com/maticnetwork/heimdall v0.3.1-0.20230227104835-81bd1055b0bc h1:7wEWQbYs6ESGsVBhjiVp7fZZyfaN4lg4XYLOLfRIpmY=
|
||||||
|
github.com/maticnetwork/heimdall v0.3.1-0.20230227104835-81bd1055b0bc/go.mod h1:P2DoKhovYP9G9Kj2EH/zHaiRJF1jNU7ZJOyelG4UCa8=
|
||||||
github.com/maticnetwork/polyproto v0.0.2/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
|
github.com/maticnetwork/polyproto v0.0.2/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
|
||||||
|
github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53 h1:PjYV+lghs106JKkrYgOnrsfDLoTc11BxZd4rUa4Rus4=
|
||||||
|
github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
|
||||||
github.com/maticnetwork/tendermint v0.26.0-dev0.0.20220923185258-3e7c7f86ce9f h1:iV69PJUEdwJJFXQvbADYVEMxDrkKAsPdHTg4U3F510I=
|
github.com/maticnetwork/tendermint v0.26.0-dev0.0.20220923185258-3e7c7f86ce9f h1:iV69PJUEdwJJFXQvbADYVEMxDrkKAsPdHTg4U3F510I=
|
||||||
github.com/maticnetwork/tendermint v0.26.0-dev0.0.20220923185258-3e7c7f86ce9f/go.mod h1:90S74348uYSGfWwNIgvzQiRRakSH/c7VVt1TR5mzIuY=
|
github.com/maticnetwork/tendermint v0.26.0-dev0.0.20220923185258-3e7c7f86ce9f/go.mod h1:90S74348uYSGfWwNIgvzQiRRakSH/c7VVt1TR5mzIuY=
|
||||||
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||||
|
|
@ -767,6 +830,7 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
|
@ -809,8 +873,9 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
|
||||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
|
||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
|
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
|
||||||
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
|
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||||
|
|
@ -875,10 +940,14 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
|
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
|
||||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||||
|
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
|
||||||
|
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
||||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||||
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||||
github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg=
|
github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg=
|
||||||
|
|
@ -897,6 +966,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||||
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=
|
||||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||||
|
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||||
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
|
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
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=
|
||||||
|
|
@ -999,11 +1069,13 @@ github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJ
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
|
||||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
|
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
|
||||||
|
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
|
|
||||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||||
|
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||||
|
|
@ -1017,8 +1089,9 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
|
||||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||||
|
github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
|
||||||
|
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
|
||||||
github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg=
|
github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg=
|
||||||
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=
|
||||||
|
|
@ -1047,6 +1120,8 @@ github.com/stumble/gorocksdb v0.0.3 h1:9UU+QA1pqFYJuf9+5p7z1IqdE5k0mma4UAeu2wmX8
|
||||||
github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYtSWXadLybY=
|
github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYtSWXadLybY=
|
||||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
|
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
|
||||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
|
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
|
||||||
|
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||||
|
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||||
github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
|
github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
|
||||||
github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
|
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
|
||||||
|
|
@ -1148,8 +1223,10 @@ 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.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/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.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.6 h1:BdkrbWrzDlV9dnbzoP7sfN+dHheJ4J9JOaYxcUDL+ok=
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||||
|
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||||
|
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||||
go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ=
|
go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ=
|
||||||
go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I=
|
go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 h1:xzbcGykysUh776gzD1LUPsNNHKWN0kQWDnJhn1ddUuk=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 h1:xzbcGykysUh776gzD1LUPsNNHKWN0kQWDnJhn1ddUuk=
|
||||||
|
|
@ -1197,7 +1274,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
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=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||||
|
|
@ -1242,6 +1321,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
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-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/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-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
|
@ -1252,6 +1332,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/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.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||||
|
|
@ -1302,18 +1384,31 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R
|
||||||
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-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
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-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/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-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
|
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
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.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
|
|
@ -1325,7 +1420,21 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||||
golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8=
|
golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8=
|
||||||
golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
|
golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
|
||||||
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=
|
||||||
|
|
@ -1340,6 +1449,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
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-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-20220601150217-0de741cfad7f/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.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
|
|
@ -1405,10 +1515,17 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/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-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
@ -1416,20 +1533,37 @@ golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/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-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/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-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/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=
|
||||||
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
@ -1529,10 +1663,17 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/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-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||||
|
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
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.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||||
|
|
@ -1546,8 +1687,9 @@ 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618=
|
|
||||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||||
|
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||||
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||||
gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
|
gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
|
||||||
|
|
@ -1577,8 +1719,32 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
||||||
google.golang.org/api v0.28.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.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
google.golang.org/api v0.34.0 h1:k40adF3uR+6x/+hO5Dh4ZFUqFp67vxvbpafFiJxl10A=
|
|
||||||
google.golang.org/api v0.34.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
google.golang.org/api v0.34.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
|
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
|
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||||
|
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||||
|
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||||
|
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||||
|
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
||||||
|
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
||||||
|
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
||||||
|
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
||||||
|
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
||||||
|
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||||
|
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||||
|
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||||
|
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||||
|
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
||||||
|
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
|
||||||
|
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
|
||||||
|
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
|
||||||
|
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
|
||||||
|
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
|
||||||
|
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
|
||||||
|
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
|
||||||
|
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
|
||||||
|
google.golang.org/api v0.97.0 h1:x/vEL1XDF/2V4xzdNgFPaKHluRESo2aTsL7QzHnBtGQ=
|
||||||
|
google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
|
@ -1627,10 +1793,60 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
|
||||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/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/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||||
|
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||||
|
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||||
|
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
|
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
|
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||||
|
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||||
|
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||||
|
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||||
|
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||||
|
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||||
|
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
|
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b h1:SfSkJugek6xm7lWywqth4r2iTrYLpD8lOj1nMIIhMNM=
|
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||||
|
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||||
|
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
|
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
|
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
|
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
|
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
|
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
|
google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce h1:+2ye9vAK4F9F/LCex8dT2cDk0VnTAwUL8uRgX/6nAMU=
|
||||||
|
google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
|
||||||
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
|
@ -1653,15 +1869,28 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
|
||||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
|
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||||
|
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
|
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
|
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
|
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
|
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
|
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
|
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
|
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
|
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||||
|
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
|
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||||
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||||
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY=
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY=
|
||||||
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=
|
||||||
|
|
@ -1692,6 +1921,8 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
|
|
@ -1720,6 +1951,8 @@ 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=
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
|
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
|
||||||
|
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
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-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
||||||
|
|
@ -250,9 +250,19 @@ type StateSyncFilter struct {
|
||||||
|
|
||||||
// interface for whitelist service
|
// interface for whitelist service
|
||||||
type ChainValidator interface {
|
type ChainValidator interface {
|
||||||
IsValidPeer(remoteHeader *types.Header, fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error)
|
IsValidPeer(fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error)
|
||||||
IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error)
|
IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error)
|
||||||
|
GetWhitelistedCheckpoint() (bool, uint64, common.Hash)
|
||||||
|
GetWhitelistedMilestone() (bool, uint64, common.Hash)
|
||||||
ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash)
|
ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash)
|
||||||
GetCheckpointWhitelist() map[uint64]common.Hash
|
ProcessMilestone(endBlockNum uint64, endBlockHash common.Hash)
|
||||||
PurgeCheckpointWhitelist()
|
ProcessFutureMilestone(num uint64, hash common.Hash)
|
||||||
|
PurgeWhitelistedCheckpoint()
|
||||||
|
PurgeWhitelistedMilestone()
|
||||||
|
|
||||||
|
LockMutex(endBlockNum uint64) bool
|
||||||
|
UnlockMutex(doLock bool, milestoneId string, endBlockNum uint64, endBlockHash common.Hash)
|
||||||
|
UnlockSprint(endBlockNum uint64)
|
||||||
|
RemoveMilestoneID(milestoneId string)
|
||||||
|
GetMilestoneIDsList() []string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,9 @@ type Config struct {
|
||||||
// Ancient is the directory to store the state in
|
// Ancient is the directory to store the state in
|
||||||
Ancient string `hcl:"ancient,optional" toml:"ancient,optional"`
|
Ancient string `hcl:"ancient,optional" toml:"ancient,optional"`
|
||||||
|
|
||||||
|
// DBEngine is used to select leveldb or pebble as database
|
||||||
|
DBEngine string `hcl:"db.engine,optional" toml:"db.engine,optional"`
|
||||||
|
|
||||||
// KeyStoreDir is the directory to store keystores
|
// KeyStoreDir is the directory to store keystores
|
||||||
KeyStoreDir string `hcl:"keystore,optional" toml:"keystore,optional"`
|
KeyStoreDir string `hcl:"keystore,optional" toml:"keystore,optional"`
|
||||||
|
|
||||||
|
|
@ -592,6 +595,7 @@ func DefaultConfig() *Config {
|
||||||
EnablePreimageRecording: false,
|
EnablePreimageRecording: false,
|
||||||
DataDir: DefaultDataDir(),
|
DataDir: DefaultDataDir(),
|
||||||
Ancient: "",
|
Ancient: "",
|
||||||
|
DBEngine: "leveldb",
|
||||||
Logging: &LoggingConfig{
|
Logging: &LoggingConfig{
|
||||||
Vmodule: "",
|
Vmodule: "",
|
||||||
Json: false,
|
Json: false,
|
||||||
|
|
@ -1276,6 +1280,7 @@ func (c *Config) buildNode() (*node.Config, error) {
|
||||||
cfg := &node.Config{
|
cfg := &node.Config{
|
||||||
Name: clientIdentifier,
|
Name: clientIdentifier,
|
||||||
DataDir: c.DataDir,
|
DataDir: c.DataDir,
|
||||||
|
DBEngine: c.DBEngine,
|
||||||
KeyStoreDir: c.KeyStoreDir,
|
KeyStoreDir: c.KeyStoreDir,
|
||||||
UseLightweightKDF: c.Accounts.UseLightweightKDF,
|
UseLightweightKDF: c.Accounts.UseLightweightKDF,
|
||||||
InsecureUnlockAllowed: c.Accounts.AllowInsecureUnlock,
|
InsecureUnlockAllowed: c.Accounts.AllowInsecureUnlock,
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,12 @@ func (c *Command) Flags() *flagset.Flagset {
|
||||||
Value: &c.cliConfig.Ancient,
|
Value: &c.cliConfig.Ancient,
|
||||||
Default: c.cliConfig.Ancient,
|
Default: c.cliConfig.Ancient,
|
||||||
})
|
})
|
||||||
|
f.StringFlag(&flagset.StringFlag{
|
||||||
|
Name: "db.engine",
|
||||||
|
Usage: "Backing database implementation to use ('leveldb' or 'pebble')",
|
||||||
|
Value: &c.cliConfig.DBEngine,
|
||||||
|
Default: c.cliConfig.DBEngine,
|
||||||
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "keystore",
|
Name: "keystore",
|
||||||
Usage: "Path of the directory where keystores are located",
|
Usage: "Path of the directory where keystores are located",
|
||||||
|
|
|
||||||
|
|
@ -2610,17 +2610,6 @@ func (api *DebugAPI) SetHead(number hexutil.Uint64) {
|
||||||
api.b.SetHead(uint64(number))
|
api.b.SetHead(uint64(number))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCheckpointWhitelist retrieves the current checkpoint whitelist
|
|
||||||
// entries (of the form block number -> block hash)
|
|
||||||
func (api *DebugAPI) GetCheckpointWhitelist() map[uint64]common.Hash {
|
|
||||||
return api.b.GetCheckpointWhitelist()
|
|
||||||
}
|
|
||||||
|
|
||||||
// PurgeCheckpointWhitelist purges the current checkpoint whitelist entries
|
|
||||||
func (api *DebugAPI) PurgeCheckpointWhitelist() {
|
|
||||||
api.b.PurgeCheckpointWhitelist()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTraceStack returns the current trace stack
|
// GetTraceStack returns the current trace stack
|
||||||
func (api *DebugAPI) GetTraceStack() string {
|
func (api *DebugAPI) GetTraceStack() string {
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
|
|
|
||||||
|
|
@ -102,13 +102,16 @@ type Backend interface {
|
||||||
// Bor related APIs
|
// Bor related APIs
|
||||||
SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription
|
SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription
|
||||||
GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error)
|
GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error)
|
||||||
|
GetVoteOnHash(ctx context.Context, startBlockNumber uint64, endBlockNumber uint64, hash string, milestoneID string) (bool, error)
|
||||||
GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error)
|
GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error)
|
||||||
GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error)
|
GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error)
|
||||||
GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
||||||
GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
||||||
SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription
|
SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription
|
||||||
GetCheckpointWhitelist() map[uint64]common.Hash
|
GetWhitelistedCheckpoint() (bool, uint64, common.Hash)
|
||||||
PurgeCheckpointWhitelist()
|
PurgeWhitelistedCheckpoint()
|
||||||
|
GetWhitelistedMilestone() (bool, uint64, common.Hash)
|
||||||
|
PurgeWhitelistedMilestone()
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAPIs(apiBackend Backend) []rpc.API {
|
func GetAPIs(apiBackend Backend) []rpc.API {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ func (s *BlockChainAPI) GetBorBlockReceipt(ctx context.Context, hash common.Hash
|
||||||
return s.b.GetBorBlockReceipt(ctx, hash)
|
return s.b.GetBorBlockReceipt(ctx, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *BlockChainAPI) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
|
||||||
|
return s.b.GetVoteOnHash(ctx, starBlockNr, endBlockNr, hash, milestoneId)
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Bor transaction utils
|
// Bor transaction utils
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -364,51 +364,51 @@ func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent)
|
||||||
func (b *backendMock) Engine() consensus.Engine { return nil }
|
func (b *backendMock) Engine() consensus.Engine { return nil }
|
||||||
|
|
||||||
func (b *backendMock) RPCRpcReturnDataLimit() uint64 {
|
func (b *backendMock) RPCRpcReturnDataLimit() uint64 {
|
||||||
//nolint: staticcheck
|
return 0
|
||||||
return b.RPCRpcReturnDataLimit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
|
func (b *backendMock) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
|
||||||
//nolint: staticcheck
|
return nil
|
||||||
return b.SubscribeStateSyncEvent(ch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
func (b *backendMock) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
|
||||||
//nolint: staticcheck
|
return "", nil
|
||||||
return b.GetRootHash(ctx, starBlockNr, endBlockNr)
|
}
|
||||||
|
|
||||||
|
func (b *backendMock) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
func (b *backendMock) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
//nolint: staticcheck
|
//nolint: nilnil
|
||||||
return b.GetBorBlockReceipt(ctx, hash)
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
func (b *backendMock) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
||||||
//nolint: staticcheck
|
// nolint: nilnil
|
||||||
return b.GetBorBlockLogs(ctx, hash)
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
func (b *backendMock) GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
||||||
//nolint: staticcheck
|
return nil, common.Hash{}, 0, 0, nil
|
||||||
return b.GetBorBlockTransaction(ctx, txHash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
func (b *backendMock) GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
||||||
//nolint: staticcheck
|
return nil, common.Hash{}, 0, 0, nil
|
||||||
return b.GetBorBlockTransactionWithBlockHash(ctx, txHash, blockHash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription {
|
func (b *backendMock) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription {
|
||||||
//nolint: staticcheck
|
return nil
|
||||||
return b.SubscribeChain2HeadEvent(ch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) GetCheckpointWhitelist() map[uint64]common.Hash {
|
func (b *backendMock) GetWhitelistedCheckpoint() (bool, uint64, common.Hash) {
|
||||||
//nolint: staticcheck
|
return false, 0, common.Hash{}
|
||||||
return b.GetCheckpointWhitelist()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendMock) PurgeCheckpointWhitelist() {
|
func (b *backendMock) GetWhitelistedMilestone() (bool, uint64, common.Hash) {
|
||||||
//nolint: staticcheck
|
return false, 0, common.Hash{}
|
||||||
b.PurgeCheckpointWhitelist()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backendMock) PurgeWhitelistedCheckpoint() {}
|
||||||
|
|
||||||
|
func (b *backendMock) PurgeWhitelistedMilestone() {}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,11 @@ web3._extend({
|
||||||
call: 'bor_getRootHash',
|
call: 'bor_getRootHash',
|
||||||
params: 2,
|
params: 2,
|
||||||
}),
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'getVoteOnHash',
|
||||||
|
call: 'bor_getVoteOnHash',
|
||||||
|
params: 4,
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -516,13 +516,23 @@ web3._extend({
|
||||||
inputFormatter:[web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter],
|
inputFormatter:[web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter],
|
||||||
}),
|
}),
|
||||||
new web3._extend.Method({
|
new web3._extend.Method({
|
||||||
name: 'getCheckpointWhitelist',
|
name: 'getWhitelistedCheckpoint',
|
||||||
call: 'debug_getCheckpointWhitelist',
|
call: 'debug_getWhitelistedCheckpoint',
|
||||||
params: 0,
|
params: 0,
|
||||||
}),
|
}),
|
||||||
new web3._extend.Method({
|
new web3._extend.Method({
|
||||||
name: 'purgeCheckpointWhitelist',
|
name: 'purgeWhitelistedCheckpoint',
|
||||||
call: 'debug_purgeCheckpointWhitelist',
|
call: 'debug_purgeWhitelistedCheckpoint',
|
||||||
|
params: 0,
|
||||||
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'getWhitelistedMilestone',
|
||||||
|
call: 'debug_getWhitelistedMilestone',
|
||||||
|
params: 0,
|
||||||
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'purgeWhitelistedMilestone',
|
||||||
|
call: 'debug_purgeWhitelistedMilestone',
|
||||||
params: 0,
|
params: 0,
|
||||||
}),
|
}),
|
||||||
new web3._extend.Method({
|
new web3._extend.Method({
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,9 @@ func (b *LesApiBackend) RPCRpcReturnDataLimit() uint64 {
|
||||||
func (b *LesApiBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
func (b *LesApiBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
|
||||||
return nil, errors.New("not implemented")
|
return nil, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
func (b *LesApiBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
|
||||||
|
return false, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
func (b *LesApiBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) {
|
||||||
return nil, errors.New("not implemented")
|
return nil, errors.New("not implemented")
|
||||||
|
|
@ -360,9 +363,16 @@ func (b *LesApiBackend) GetBorBlockTransactionWithBlockHash(ctx context.Context,
|
||||||
return nil, common.Hash{}, 0, 0, errors.New("not implemented")
|
return nil, common.Hash{}, 0, 0, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetCheckpointWhitelist() map[uint64]common.Hash {
|
func (b *LesApiBackend) GetWhitelistedCheckpoint() (bool, uint64, common.Hash) {
|
||||||
return nil
|
return false, 0, common.Hash{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) PurgeCheckpointWhitelist() {
|
func (b *LesApiBackend) PurgeWhitelistedCheckpoint() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) GetWhitelistedMilestone() (bool, uint64, common.Hash) {
|
||||||
|
return false, 0, common.Hash{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) PurgeWhitelistedMilestone() {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) {
|
||||||
|
|
||||||
// Note: NewLightChain adds the trusted checkpoint so it needs an ODR with
|
// Note: NewLightChain adds the trusted checkpoint so it needs an ODR with
|
||||||
// indexers already set but not started yet
|
// indexers already set but not started yet
|
||||||
|
|
||||||
|
// checker := whitelist.NewService(chainDb)
|
||||||
|
|
||||||
if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine, nil); err != nil {
|
if leth.blockchain, err = light.NewLightChain(leth.odr, leth.chainConfig, leth.engine, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ func (c *collector) addHistogram(name string, m metrics.Histogram) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.writeSummarySum(name, fmt.Sprintf("%f", sum))
|
c.writeSummarySum(name, fmt.Sprintf("%f", sum))
|
||||||
c.writeSummaryCounter(name, len(ps))
|
c.writeSummaryCounter(name, m.Count())
|
||||||
c.buff.WriteRune('\n')
|
c.buff.WriteRune('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +97,7 @@ func (c *collector) addTimer(name string, m metrics.Timer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.writeSummarySum(name, fmt.Sprintf("%f", sum))
|
c.writeSummarySum(name, fmt.Sprintf("%f", sum))
|
||||||
c.writeSummaryCounter(name, len(ps))
|
c.writeSummaryCounter(name, m.Count())
|
||||||
c.buff.WriteRune('\n')
|
c.buff.WriteRune('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ func TestCollector(t *testing.T) {
|
||||||
timer.Update(120 * time.Millisecond)
|
timer.Update(120 * time.Millisecond)
|
||||||
timer.Update(23 * time.Millisecond)
|
timer.Update(23 * time.Millisecond)
|
||||||
timer.Update(24 * time.Millisecond)
|
timer.Update(24 * time.Millisecond)
|
||||||
|
timer.Update(30 * time.Millisecond)
|
||||||
c.addTimer("test/timer", timer)
|
c.addTimer("test/timer", timer)
|
||||||
|
|
||||||
resettingTimer := metrics.NewResettingTimer()
|
resettingTimer := metrics.NewResettingTimer()
|
||||||
|
|
@ -58,6 +59,7 @@ func TestCollector(t *testing.T) {
|
||||||
resettingTimer.Update(120 * time.Millisecond)
|
resettingTimer.Update(120 * time.Millisecond)
|
||||||
resettingTimer.Update(13 * time.Millisecond)
|
resettingTimer.Update(13 * time.Millisecond)
|
||||||
resettingTimer.Update(14 * time.Millisecond)
|
resettingTimer.Update(14 * time.Millisecond)
|
||||||
|
resettingTimer.Update(30 * time.Millisecond)
|
||||||
c.addResettingTimer("test/resetting_timer", resettingTimer.Snapshot())
|
c.addResettingTimer("test/resetting_timer", resettingTimer.Snapshot())
|
||||||
|
|
||||||
emptyResettingTimer := metrics.NewResettingTimer().Snapshot()
|
emptyResettingTimer := metrics.NewResettingTimer().Snapshot()
|
||||||
|
|
@ -83,27 +85,27 @@ test_histogram {quantile="0.99"} 0
|
||||||
test_histogram {quantile="0.999"} 0
|
test_histogram {quantile="0.999"} 0
|
||||||
test_histogram {quantile="0.9999"} 0
|
test_histogram {quantile="0.9999"} 0
|
||||||
test_histogram_sum 0.000000
|
test_histogram_sum 0.000000
|
||||||
test_histogram_count 6
|
test_histogram_count 0
|
||||||
|
|
||||||
# TYPE test_meter gauge
|
# TYPE test_meter gauge
|
||||||
test_meter 9999999
|
test_meter 9999999
|
||||||
|
|
||||||
# TYPE test_timer summary
|
# TYPE test_timer summary
|
||||||
test_timer {quantile="0.5"} 2.25e+07
|
test_timer {quantile="0.5"} 2.3e+07
|
||||||
test_timer {quantile="0.75"} 4.8e+07
|
test_timer {quantile="0.75"} 3e+07
|
||||||
test_timer {quantile="0.95"} 1.2e+08
|
test_timer {quantile="0.95"} 1.2e+08
|
||||||
test_timer {quantile="0.99"} 1.2e+08
|
test_timer {quantile="0.99"} 1.2e+08
|
||||||
test_timer {quantile="0.999"} 1.2e+08
|
test_timer {quantile="0.999"} 1.2e+08
|
||||||
test_timer {quantile="0.9999"} 1.2e+08
|
test_timer {quantile="0.9999"} 1.2e+08
|
||||||
test_timer_sum 550500000.000000
|
test_timer_sum 533000000.000000
|
||||||
test_timer_count 6
|
test_timer_count 7
|
||||||
|
|
||||||
# TYPE test_resetting_timer summary
|
# TYPE test_resetting_timer summary
|
||||||
test_resetting_timer {quantile="0.50"} 12000000
|
test_resetting_timer {quantile="0.50"} 13000000
|
||||||
test_resetting_timer {quantile="0.95"} 120000000
|
test_resetting_timer {quantile="0.95"} 120000000
|
||||||
test_resetting_timer {quantile="0.99"} 120000000
|
test_resetting_timer {quantile="0.99"} 120000000
|
||||||
test_resetting_timer_sum 180000000
|
test_resetting_timer_sum 210000000
|
||||||
test_resetting_timer_count 6
|
test_resetting_timer_count 7
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,3 +162,95 @@ package miner
|
||||||
|
|
||||||
// return bor.New(chainConfig, chainDB, ethAPIMock, spanner, heimdallClientMock, contractMock, false)
|
// return bor.New(chainConfig, chainDB, ethAPIMock, spanner, heimdallClientMock, contractMock, false)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// type mockBackend struct {
|
||||||
|
// bc *core.BlockChain
|
||||||
|
// txPool *txpool.TxPool
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // PeerCount implements Backend.
|
||||||
|
// func (*mockBackend) PeerCount() int {
|
||||||
|
// panic("unimplemented")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func NewMockBackend(bc *core.BlockChain, txPool *txpool.TxPool) *mockBackend {
|
||||||
|
// return &mockBackend{
|
||||||
|
// bc: bc,
|
||||||
|
// txPool: txPool,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (m *mockBackend) BlockChain() *core.BlockChain {
|
||||||
|
// return m.bc
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (m *mockBackend) TxPool() *txpool.TxPool {
|
||||||
|
// return m.txPool
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) {
|
||||||
|
// return nil, errors.New("not supported")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// type testBlockChain struct {
|
||||||
|
// statedb *state.StateDB
|
||||||
|
// gasLimit uint64
|
||||||
|
// chainHeadFeed *event.Feed
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (bc *testBlockChain) CurrentBlock() *types.Header {
|
||||||
|
// return &types.Header{
|
||||||
|
// GasLimit: bc.gasLimit,
|
||||||
|
// Number: new(big.Int),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
|
||||||
|
// return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
|
||||||
|
// return bc.statedb, nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
|
||||||
|
// return bc.chainHeadFeed.Subscribe(ch)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var (
|
||||||
|
// // Test chain configurations
|
||||||
|
// testTxPoolConfig txpool.Config
|
||||||
|
// ethashChainConfig *params.ChainConfig
|
||||||
|
// cliqueChainConfig *params.ChainConfig
|
||||||
|
|
||||||
|
// // Test accounts
|
||||||
|
// testBankKey, _ = crypto.GenerateKey()
|
||||||
|
// TestBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
|
||||||
|
// testBankFunds = big.NewInt(9000000000000000000)
|
||||||
|
|
||||||
|
// testUserKey, _ = crypto.GenerateKey()
|
||||||
|
// testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey)
|
||||||
|
|
||||||
|
// // Test transactions
|
||||||
|
// pendingTxs []*types.Transaction
|
||||||
|
// newTxs []*types.Transaction
|
||||||
|
|
||||||
|
// testConfig = &Config{
|
||||||
|
// Recommit: time.Second,
|
||||||
|
// GasCeil: params.GenesisGasLimit,
|
||||||
|
// CommitInterruptFlag: true,
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
|
||||||
|
// func init() {
|
||||||
|
// testTxPoolConfig = txpool.DefaultConfig
|
||||||
|
// testTxPoolConfig.Journal = ""
|
||||||
|
// ethashChainConfig = new(params.ChainConfig)
|
||||||
|
// *ethashChainConfig = *params.TestChainConfig
|
||||||
|
// cliqueChainConfig = new(params.ChainConfig)
|
||||||
|
// *cliqueChainConfig = *params.TestChainConfig
|
||||||
|
// cliqueChainConfig.Clique = ¶ms.CliqueConfig{
|
||||||
|
// Period: 10,
|
||||||
|
// Epoch: 30000,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import (
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
BlockChain() *core.BlockChain
|
BlockChain() *core.BlockChain
|
||||||
TxPool() *txpool.TxPool
|
TxPool() *txpool.TxPool
|
||||||
|
PeerCount() int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config is the configuration parameters of mining.
|
// Config is the configuration parameters of mining.
|
||||||
|
|
@ -77,7 +78,7 @@ type Miner struct {
|
||||||
engine consensus.Engine
|
engine consensus.Engine
|
||||||
exitCh chan struct{}
|
exitCh chan struct{}
|
||||||
startCh chan struct{}
|
startCh chan struct{}
|
||||||
stopCh chan struct{}
|
stopCh chan chan struct{}
|
||||||
worker *worker
|
worker *worker
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
@ -89,8 +90,8 @@ func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *even
|
||||||
eth: eth,
|
eth: eth,
|
||||||
engine: engine,
|
engine: engine,
|
||||||
exitCh: make(chan struct{}),
|
exitCh: make(chan struct{}),
|
||||||
|
stopCh: make(chan chan struct{}),
|
||||||
startCh: make(chan struct{}),
|
startCh: make(chan struct{}),
|
||||||
stopCh: make(chan struct{}),
|
|
||||||
worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, true),
|
worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, true),
|
||||||
}
|
}
|
||||||
miner.wg.Add(1)
|
miner.wg.Add(1)
|
||||||
|
|
@ -167,10 +168,11 @@ func (miner *Miner) update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldStart = true
|
shouldStart = true
|
||||||
case <-miner.stopCh:
|
case ch := <-miner.stopCh:
|
||||||
shouldStart = false
|
shouldStart = false
|
||||||
|
|
||||||
miner.worker.stop()
|
miner.worker.stop()
|
||||||
|
close(ch)
|
||||||
case <-miner.exitCh:
|
case <-miner.exitCh:
|
||||||
miner.worker.close()
|
miner.worker.close()
|
||||||
return
|
return
|
||||||
|
|
@ -182,8 +184,8 @@ func (miner *Miner) Start() {
|
||||||
miner.startCh <- struct{}{}
|
miner.startCh <- struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (miner *Miner) Stop() {
|
func (miner *Miner) Stop(ch chan struct{}) {
|
||||||
miner.stopCh <- struct{}{}
|
miner.stopCh <- ch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (miner *Miner) Close() {
|
func (miner *Miner) Close() {
|
||||||
|
|
|
||||||
|
|
@ -197,13 +197,15 @@ func TestMinerStartStopAfterDownloaderEvents(t *testing.T) {
|
||||||
mux.Post(downloader.DoneEvent{})
|
mux.Post(downloader.DoneEvent{})
|
||||||
waitForMiningState(t, miner, true)
|
waitForMiningState(t, miner, true)
|
||||||
|
|
||||||
miner.Stop()
|
ch := make(chan struct{})
|
||||||
|
miner.Stop(ch)
|
||||||
waitForMiningState(t, miner, false)
|
waitForMiningState(t, miner, false)
|
||||||
|
|
||||||
miner.Start()
|
miner.Start()
|
||||||
waitForMiningState(t, miner, true)
|
waitForMiningState(t, miner, true)
|
||||||
|
|
||||||
miner.Stop()
|
ch = make(chan struct{})
|
||||||
|
miner.Stop(ch)
|
||||||
waitForMiningState(t, miner, false)
|
waitForMiningState(t, miner, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,7 +249,8 @@ func TestStartStopMiner(t *testing.T) {
|
||||||
miner.Start()
|
miner.Start()
|
||||||
waitForMiningState(t, miner, true)
|
waitForMiningState(t, miner, true)
|
||||||
|
|
||||||
miner.Stop()
|
ch := make(chan struct{})
|
||||||
|
miner.Stop(ch)
|
||||||
|
|
||||||
waitForMiningState(t, miner, false)
|
waitForMiningState(t, miner, false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package miner
|
package miner
|
||||||
|
|
||||||
// TODO - Fix this - Arpit
|
|
||||||
|
|
||||||
// import (
|
// import (
|
||||||
// "context"
|
// "context"
|
||||||
// "crypto/rand"
|
// "crypto/rand"
|
||||||
|
|
@ -18,7 +16,6 @@ package miner
|
||||||
// "github.com/ethereum/go-ethereum/consensus/ethash"
|
// "github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
// "github.com/ethereum/go-ethereum/core/state"
|
// "github.com/ethereum/go-ethereum/core/state"
|
||||||
// "github.com/ethereum/go-ethereum/core/txpool"
|
// "github.com/ethereum/go-ethereum/core/txpool"
|
||||||
// "github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
|
||||||
// "github.com/ethereum/go-ethereum/crypto"
|
// "github.com/ethereum/go-ethereum/crypto"
|
||||||
// "github.com/ethereum/go-ethereum/ethdb"
|
// "github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
|
||||||
|
|
@ -54,7 +51,7 @@ package miner
|
||||||
|
|
||||||
// func init() {
|
// func init() {
|
||||||
|
|
||||||
// testTxPoolConfig = legacypool.DefaultConfig
|
// testTxPoolConfig = txpool.DefaultConfig
|
||||||
// testTxPoolConfig.Journal = ""
|
// testTxPoolConfig.Journal = ""
|
||||||
// ethashChainConfig = new(params.ChainConfig)
|
// ethashChainConfig = new(params.ChainConfig)
|
||||||
// *ethashChainConfig = *params.TestChainConfig
|
// *ethashChainConfig = *params.TestChainConfig
|
||||||
|
|
@ -64,7 +61,6 @@ package miner
|
||||||
// Period: 10,
|
// Period: 10,
|
||||||
// Epoch: 30000,
|
// Epoch: 30000,
|
||||||
// }
|
// }
|
||||||
// TestBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
|
|
||||||
|
|
||||||
// signer := types.LatestSigner(params.TestChainConfig)
|
// signer := types.LatestSigner(params.TestChainConfig)
|
||||||
|
|
||||||
|
|
@ -99,6 +95,11 @@ package miner
|
||||||
// uncleBlock *types.Block
|
// uncleBlock *types.Block
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// // PeerCount implements Backend.
|
||||||
|
// func (*testWorkerBackend) PeerCount() int {
|
||||||
|
// panic("unimplemented")
|
||||||
|
// }
|
||||||
|
|
||||||
// func newTestWorkerBackend(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, n int) *testWorkerBackend {
|
// func newTestWorkerBackend(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, n int) *testWorkerBackend {
|
||||||
// var gspec = core.Genesis{
|
// var gspec = core.Genesis{
|
||||||
// Config: chainConfig,
|
// Config: chainConfig,
|
||||||
|
|
@ -277,6 +278,9 @@ package miner
|
||||||
// mux: mux,
|
// mux: mux,
|
||||||
// chain: eth.BlockChain(),
|
// chain: eth.BlockChain(),
|
||||||
// isLocalBlock: isLocalBlock,
|
// isLocalBlock: isLocalBlock,
|
||||||
|
// localUncles: make(map[common.Hash]*types.Block),
|
||||||
|
// remoteUncles: make(map[common.Hash]*types.Block),
|
||||||
|
// unconfirmed: newUnconfirmedBlocks(eth.BlockChain(), sealingLogAtDepth),
|
||||||
// pendingTasks: make(map[common.Hash]*task),
|
// pendingTasks: make(map[common.Hash]*task),
|
||||||
// txsCh: make(chan core.NewTxsEvent, txChanSize),
|
// txsCh: make(chan core.NewTxsEvent, txChanSize),
|
||||||
// chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
// chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
||||||
|
|
|
||||||
|
|
@ -591,7 +591,15 @@ func (w *worker) mainLoop(ctx context.Context) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case req := <-w.newWorkCh:
|
case req := <-w.newWorkCh:
|
||||||
w.commitWork(req.ctx, req.interrupt, req.timestamp)
|
if w.chainConfig.ChainID.Cmp(params.BorMainnetChainConfig.ChainID) == 0 || w.chainConfig.ChainID.Cmp(params.MumbaiChainConfig.ChainID) == 0 {
|
||||||
|
if w.eth.PeerCount() > 0 {
|
||||||
|
//nolint:contextcheck
|
||||||
|
w.commitWork(req.ctx, req.interrupt, req.timestamp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//nolint:contextcheck
|
||||||
|
w.commitWork(req.ctx, req.interrupt, req.timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
case req := <-w.getWorkCh:
|
case req := <-w.getWorkCh:
|
||||||
block, fees, err := w.generateWork(req.ctx, req.params)
|
block, fees, err := w.generateWork(req.ctx, req.params)
|
||||||
|
|
|
||||||
|
|
@ -366,6 +366,10 @@ func (srv *Server) SetMaxPeers(maxPeers int) {
|
||||||
|
|
||||||
// PeerCount returns the number of connected peers.
|
// PeerCount returns the number of connected peers.
|
||||||
func (srv *Server) PeerCount() int {
|
func (srv *Server) PeerCount() int {
|
||||||
|
if !srv.running {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
var count int
|
var count int
|
||||||
|
|
||||||
srv.doPeerOp(func(ps map[enode.ID]*Peer) {
|
srv.doPeerOp(func(ps map[enode.ID]*Peer) {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ chain = "mainnet"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = ""
|
# keystore = ""
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ chain = "mainnet"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = ""
|
# keystore = ""
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ chain = "mainnet"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = "$BOR_DIR/keystore"
|
# keystore = "$BOR_DIR/keystore"
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ chain = "mainnet"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = "$BOR_DIR/keystore"
|
# keystore = "$BOR_DIR/keystore"
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor
|
Source: bor
|
||||||
Version: 0.4.0
|
Version: 1.0.0-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor
|
Source: bor
|
||||||
Version: 0.4.0
|
Version: 1.0.0-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor-profile
|
Source: bor-profile
|
||||||
Version: 0.4.0
|
Version: 1.0.0-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor-profile
|
Source: bor-profile
|
||||||
Version: 0.4.0
|
Version: 1.0.0-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor-profile
|
Source: bor-profile
|
||||||
Version: 0.4.0
|
Version: 1.0.0-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source: bor-profile
|
Source: bor-profile
|
||||||
Version: 0.4.0
|
Version: 1.0.0-beta
|
||||||
Section: develop
|
Section: develop
|
||||||
Priority: standard
|
Priority: standard
|
||||||
Maintainer: Polygon <release-team@polygon.technology>
|
Maintainer: Polygon <release-team@polygon.technology>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,4 @@
|
||||||
###############
|
###############
|
||||||
# Remove bor installs
|
# Remove bor installs
|
||||||
##############
|
##############
|
||||||
sudo rm -rf /var/lib/bor/config.toml
|
|
||||||
sudo rm -rf /lib/systemd/system/bor.service
|
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ chain = "mumbai"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = ""
|
# keystore = ""
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ chain = "mumbai"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = ""
|
# keystore = ""
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ chain = "mumbai"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = "$BOR_DIR/keystore"
|
# keystore = "$BOR_DIR/keystore"
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ chain = "mumbai"
|
||||||
# vmdebug = false
|
# vmdebug = false
|
||||||
datadir = "/var/lib/bor/data"
|
datadir = "/var/lib/bor/data"
|
||||||
# ancient = ""
|
# ancient = ""
|
||||||
|
# db.engine = "leveldb"
|
||||||
# keystore = "$BOR_DIR/keystore"
|
# keystore = "$BOR_DIR/keystore"
|
||||||
# "rpc.batchlimit" = 100
|
# "rpc.batchlimit" = 100
|
||||||
# "rpc.returndatalimit" = 100000
|
# "rpc.returndatalimit" = 100000
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ var (
|
||||||
|
|
||||||
// BorTestChainConfig contains the chain parameters to run a node on the Test network.
|
// BorTestChainConfig contains the chain parameters to run a node on the Test network.
|
||||||
BorTestChainConfig = &ChainConfig{
|
BorTestChainConfig = &ChainConfig{
|
||||||
ChainID: big.NewInt(80001),
|
ChainID: big.NewInt(80002),
|
||||||
HomesteadBlock: big.NewInt(0),
|
HomesteadBlock: big.NewInt(0),
|
||||||
DAOForkBlock: nil,
|
DAOForkBlock: nil,
|
||||||
DAOForkSupport: true,
|
DAOForkSupport: true,
|
||||||
|
|
@ -149,7 +149,7 @@ var (
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
BorUnittestChainConfig = &ChainConfig{
|
BorUnittestChainConfig = &ChainConfig{
|
||||||
ChainID: big.NewInt(80001),
|
ChainID: big.NewInt(80003),
|
||||||
HomesteadBlock: big.NewInt(0),
|
HomesteadBlock: big.NewInt(0),
|
||||||
DAOForkBlock: nil,
|
DAOForkBlock: nil,
|
||||||
DAOForkSupport: true,
|
DAOForkSupport: true,
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VersionMajor = 0 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 4 // Minor version component of the current release
|
VersionMinor = 0 // Minor version component of the current release
|
||||||
VersionPatch = 0 // Patch version component of the current release
|
VersionPatch = 0 // Patch version component of the current release
|
||||||
VersionMeta = "" // Version metadata to append to the version string
|
VersionMeta = "beta" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
var GitCommit string
|
var GitCommit string
|
||||||
|
|
|
||||||
31
rpc/types.go
31
rpc/types.go
|
|
@ -68,6 +68,11 @@ const (
|
||||||
LatestBlockNumber = BlockNumber(-2)
|
LatestBlockNumber = BlockNumber(-2)
|
||||||
PendingBlockNumber = BlockNumber(-1)
|
PendingBlockNumber = BlockNumber(-1)
|
||||||
EarliestBlockNumber = BlockNumber(0)
|
EarliestBlockNumber = BlockNumber(0)
|
||||||
|
|
||||||
|
latest = "latest"
|
||||||
|
earliest = "earliest"
|
||||||
|
pending = "pending"
|
||||||
|
finalized = "finalized"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
|
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
|
||||||
|
|
@ -84,13 +89,13 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch input {
|
switch input {
|
||||||
case "earliest":
|
case earliest:
|
||||||
*bn = EarliestBlockNumber
|
*bn = EarliestBlockNumber
|
||||||
return nil
|
return nil
|
||||||
case "latest":
|
case latest:
|
||||||
*bn = LatestBlockNumber
|
*bn = LatestBlockNumber
|
||||||
return nil
|
return nil
|
||||||
case "pending":
|
case pending:
|
||||||
*bn = PendingBlockNumber
|
*bn = PendingBlockNumber
|
||||||
return nil
|
return nil
|
||||||
case "finalized":
|
case "finalized":
|
||||||
|
|
@ -179,23 +184,20 @@ func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch input {
|
switch input {
|
||||||
case "earliest":
|
case earliest:
|
||||||
bn := EarliestBlockNumber
|
bn := EarliestBlockNumber
|
||||||
bnh.BlockNumber = &bn
|
bnh.BlockNumber = &bn
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
case "latest":
|
|
||||||
|
case latest:
|
||||||
bn := LatestBlockNumber
|
bn := LatestBlockNumber
|
||||||
bnh.BlockNumber = &bn
|
bnh.BlockNumber = &bn
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
case "pending":
|
|
||||||
bn := PendingBlockNumber
|
|
||||||
bnh.BlockNumber = &bn
|
|
||||||
|
|
||||||
return nil
|
case pending:
|
||||||
case "finalized":
|
bn := PendingBlockNumber
|
||||||
bn := FinalizedBlockNumber
|
|
||||||
bnh.BlockNumber = &bn
|
bnh.BlockNumber = &bn
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -204,6 +206,13 @@ func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
|
||||||
bnh.BlockNumber = &bn
|
bnh.BlockNumber = &bn
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
case finalized:
|
||||||
|
bn := FinalizedBlockNumber
|
||||||
|
bnh.BlockNumber = &bn
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if len(input) == 66 {
|
if len(input) == 66 {
|
||||||
hash := common.Hash{}
|
hash := common.Hash{}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue