From 0a6398125201601f8c68c163e4a10f79ced6d7d8 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Thu, 27 Jan 2022 15:52:45 +0530 Subject: [PATCH 01/80] add seperate module config for http and ws From 0232c6a2665af363d114a68f4fec6e6b0c35f804 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Wed, 2 Feb 2022 12:01:47 +0100 Subject: [PATCH 02/80] Do not build classic docker image --- .github/workflows/dockerimage.yml | 29 ----------------------------- Dockerfile.classic | 18 ------------------ 2 files changed, 47 deletions(-) delete mode 100644 .github/workflows/dockerimage.yml delete mode 100644 Dockerfile.classic diff --git a/.github/workflows/dockerimage.yml b/.github/workflows/dockerimage.yml deleted file mode 100644 index a8dc11949f..0000000000 --- a/.github/workflows/dockerimage.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Bor Docker Image CI - -on: - push: - branches-ignore: - - '**' - tags: - - 'v*.*.*' - # to be used by fork patch-releases ^^ - - 'v*.*.*-*' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the Bor Docker image - env: - DOCKERHUB: ${{ secrets.DOCKERHUB }} - DOCKERHUB_KEY: ${{ secrets.DOCKERHUB_KEY }} - run: | - ls -l - echo "Docker login" - docker login -u $DOCKERHUB -p $DOCKERHUB_KEY - echo "running build" - docker build -f Dockerfile.classic -t maticnetwork/bor:${GITHUB_REF/refs\/tags\//} . - echo "pushing image" - docker push maticnetwork/bor:${GITHUB_REF/refs\/tags\//} - echo "DONE!" diff --git a/Dockerfile.classic b/Dockerfile.classic deleted file mode 100644 index 2fa38f08f9..0000000000 --- a/Dockerfile.classic +++ /dev/null @@ -1,18 +0,0 @@ -# Build Geth in a stock Go builder container -FROM golang:1.18.1-alpine as builder - -RUN apk add --no-cache make gcc musl-dev linux-headers git bash - -ADD . /bor -RUN cd /bor && make bor-all - -CMD ["/bin/bash"] - -# Pull Bor into a second stage deploy alpine container -FROM alpine:latest - -RUN apk add --no-cache ca-certificates -COPY --from=builder /bor/build/bin/bor /usr/local/bin/ -COPY --from=builder /bor/build/bin/bootnode /usr/local/bin/ - -EXPOSE 8545 8546 8547 30303 30303/udp From b416577a8e79c8f340300e45c6b377204c24b4dd Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Thu, 3 Feb 2022 09:30:27 +0100 Subject: [PATCH 03/80] Protobuf tooling fix and upgrade (#313) * Protobuf tooling fix and upgrade * Paths for protobuf files has changed, reflect that in Makefile * Fix the tooling to make it work in macos * Update protoc version and regenarate files. * Regen proto --- Makefile | 2 +- internal/cli/server/proto/server.pb.go | 545 ++++++++++---------- internal/cli/server/proto/server.proto | 2 +- internal/cli/server/proto/server_grpc.pb.go | 6 +- scripts/tools-protobuf.sh | 17 +- 5 files changed, 289 insertions(+), 283 deletions(-) diff --git a/Makefile b/Makefile index 6469b8510f..5bee26f690 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ bor-all: cp $(GOBIN)/* $(GOPATH)/bin/ protoc: - protoc --go_out=. --go-grpc_out=. ./command/server/proto/*.proto + protoc --go_out=. --go-grpc_out=. ./internal/cli/server/proto/*.proto geth: $(GORUN) build/ci.go install ./cmd/geth diff --git a/internal/cli/server/proto/server.pb.go b/internal/cli/server/proto/server.pb.go index a709c538ae..2b45fb37e9 100644 --- a/internal/cli/server/proto/server.pb.go +++ b/internal/cli/server/proto/server.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.25.0 -// protoc v3.17.3 -// source: command/server/proto/server.proto +// protoc v3.19.3 +// source: internal/cli/server/proto/server.proto package proto @@ -59,11 +59,11 @@ func (x PprofRequest_Type) String() string { } func (PprofRequest_Type) Descriptor() protoreflect.EnumDescriptor { - return file_command_server_proto_server_proto_enumTypes[0].Descriptor() + return file_internal_cli_server_proto_server_proto_enumTypes[0].Descriptor() } func (PprofRequest_Type) Type() protoreflect.EnumType { - return &file_command_server_proto_server_proto_enumTypes[0] + return &file_internal_cli_server_proto_server_proto_enumTypes[0] } func (x PprofRequest_Type) Number() protoreflect.EnumNumber { @@ -72,7 +72,7 @@ func (x PprofRequest_Type) Number() protoreflect.EnumNumber { // Deprecated: Use PprofRequest_Type.Descriptor instead. func (PprofRequest_Type) EnumDescriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{16, 0} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16, 0} } type ChainWatchRequest struct { @@ -84,7 +84,7 @@ type ChainWatchRequest struct { func (x *ChainWatchRequest) Reset() { *x = ChainWatchRequest{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[0] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -97,7 +97,7 @@ func (x *ChainWatchRequest) String() string { func (*ChainWatchRequest) ProtoMessage() {} func (x *ChainWatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[0] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -110,7 +110,7 @@ func (x *ChainWatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainWatchRequest.ProtoReflect.Descriptor instead. func (*ChainWatchRequest) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{0} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{0} } type ChainWatchResponse struct { @@ -126,7 +126,7 @@ type ChainWatchResponse struct { func (x *ChainWatchResponse) Reset() { *x = ChainWatchResponse{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[1] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -139,7 +139,7 @@ func (x *ChainWatchResponse) String() string { func (*ChainWatchResponse) ProtoMessage() {} func (x *ChainWatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[1] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -152,7 +152,7 @@ func (x *ChainWatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainWatchResponse.ProtoReflect.Descriptor instead. func (*ChainWatchResponse) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{1} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{1} } func (x *ChainWatchResponse) GetOldchain() []*BlockStub { @@ -188,7 +188,7 @@ type BlockStub struct { func (x *BlockStub) Reset() { *x = BlockStub{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[2] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -201,7 +201,7 @@ func (x *BlockStub) String() string { func (*BlockStub) ProtoMessage() {} func (x *BlockStub) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[2] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -214,7 +214,7 @@ func (x *BlockStub) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockStub.ProtoReflect.Descriptor instead. func (*BlockStub) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{2} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{2} } func (x *BlockStub) GetHash() string { @@ -243,7 +243,7 @@ type PeersAddRequest struct { func (x *PeersAddRequest) Reset() { *x = PeersAddRequest{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[3] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -256,7 +256,7 @@ func (x *PeersAddRequest) String() string { func (*PeersAddRequest) ProtoMessage() {} func (x *PeersAddRequest) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[3] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -269,7 +269,7 @@ func (x *PeersAddRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersAddRequest.ProtoReflect.Descriptor instead. func (*PeersAddRequest) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{3} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{3} } func (x *PeersAddRequest) GetEnode() string { @@ -295,7 +295,7 @@ type PeersAddResponse struct { func (x *PeersAddResponse) Reset() { *x = PeersAddResponse{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[4] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -308,7 +308,7 @@ func (x *PeersAddResponse) String() string { func (*PeersAddResponse) ProtoMessage() {} func (x *PeersAddResponse) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[4] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -321,7 +321,7 @@ func (x *PeersAddResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersAddResponse.ProtoReflect.Descriptor instead. func (*PeersAddResponse) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{4} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{4} } type PeersRemoveRequest struct { @@ -336,7 +336,7 @@ type PeersRemoveRequest struct { func (x *PeersRemoveRequest) Reset() { *x = PeersRemoveRequest{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[5] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -349,7 +349,7 @@ func (x *PeersRemoveRequest) String() string { func (*PeersRemoveRequest) ProtoMessage() {} func (x *PeersRemoveRequest) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[5] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -362,7 +362,7 @@ func (x *PeersRemoveRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersRemoveRequest.ProtoReflect.Descriptor instead. func (*PeersRemoveRequest) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{5} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{5} } func (x *PeersRemoveRequest) GetEnode() string { @@ -388,7 +388,7 @@ type PeersRemoveResponse struct { func (x *PeersRemoveResponse) Reset() { *x = PeersRemoveResponse{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[6] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -401,7 +401,7 @@ func (x *PeersRemoveResponse) String() string { func (*PeersRemoveResponse) ProtoMessage() {} func (x *PeersRemoveResponse) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[6] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -414,7 +414,7 @@ func (x *PeersRemoveResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersRemoveResponse.ProtoReflect.Descriptor instead. func (*PeersRemoveResponse) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{6} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{6} } type PeersListRequest struct { @@ -426,7 +426,7 @@ type PeersListRequest struct { func (x *PeersListRequest) Reset() { *x = PeersListRequest{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[7] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -439,7 +439,7 @@ func (x *PeersListRequest) String() string { func (*PeersListRequest) ProtoMessage() {} func (x *PeersListRequest) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[7] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -452,7 +452,7 @@ func (x *PeersListRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersListRequest.ProtoReflect.Descriptor instead. func (*PeersListRequest) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{7} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{7} } type PeersListResponse struct { @@ -466,7 +466,7 @@ type PeersListResponse struct { func (x *PeersListResponse) Reset() { *x = PeersListResponse{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[8] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -479,7 +479,7 @@ func (x *PeersListResponse) String() string { func (*PeersListResponse) ProtoMessage() {} func (x *PeersListResponse) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[8] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -492,7 +492,7 @@ func (x *PeersListResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersListResponse.ProtoReflect.Descriptor instead. func (*PeersListResponse) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{8} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{8} } func (x *PeersListResponse) GetPeers() []*Peer { @@ -513,7 +513,7 @@ type PeersStatusRequest struct { func (x *PeersStatusRequest) Reset() { *x = PeersStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[9] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -526,7 +526,7 @@ func (x *PeersStatusRequest) String() string { func (*PeersStatusRequest) ProtoMessage() {} func (x *PeersStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[9] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -539,7 +539,7 @@ func (x *PeersStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersStatusRequest.ProtoReflect.Descriptor instead. func (*PeersStatusRequest) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{9} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{9} } func (x *PeersStatusRequest) GetEnode() string { @@ -560,7 +560,7 @@ type PeersStatusResponse struct { func (x *PeersStatusResponse) Reset() { *x = PeersStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[10] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -573,7 +573,7 @@ func (x *PeersStatusResponse) String() string { func (*PeersStatusResponse) ProtoMessage() {} func (x *PeersStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[10] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -586,7 +586,7 @@ func (x *PeersStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersStatusResponse.ProtoReflect.Descriptor instead. func (*PeersStatusResponse) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{10} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{10} } func (x *PeersStatusResponse) GetPeer() *Peer { @@ -613,7 +613,7 @@ type Peer struct { func (x *Peer) Reset() { *x = Peer{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[11] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -626,7 +626,7 @@ func (x *Peer) String() string { func (*Peer) ProtoMessage() {} func (x *Peer) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[11] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -639,7 +639,7 @@ func (x *Peer) ProtoReflect() protoreflect.Message { // Deprecated: Use Peer.ProtoReflect.Descriptor instead. func (*Peer) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{11} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{11} } func (x *Peer) GetId() string { @@ -702,7 +702,7 @@ type ChainSetHeadRequest struct { func (x *ChainSetHeadRequest) Reset() { *x = ChainSetHeadRequest{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[12] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -715,7 +715,7 @@ func (x *ChainSetHeadRequest) String() string { func (*ChainSetHeadRequest) ProtoMessage() {} func (x *ChainSetHeadRequest) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[12] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -728,7 +728,7 @@ func (x *ChainSetHeadRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainSetHeadRequest.ProtoReflect.Descriptor instead. func (*ChainSetHeadRequest) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{12} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{12} } func (x *ChainSetHeadRequest) GetNumber() uint64 { @@ -747,7 +747,7 @@ type ChainSetHeadResponse struct { func (x *ChainSetHeadResponse) Reset() { *x = ChainSetHeadResponse{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[13] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -760,7 +760,7 @@ func (x *ChainSetHeadResponse) String() string { func (*ChainSetHeadResponse) ProtoMessage() {} func (x *ChainSetHeadResponse) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[13] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -773,7 +773,7 @@ func (x *ChainSetHeadResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainSetHeadResponse.ProtoReflect.Descriptor instead. func (*ChainSetHeadResponse) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{13} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{13} } type StatusResponse struct { @@ -792,7 +792,7 @@ type StatusResponse struct { func (x *StatusResponse) Reset() { *x = StatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[14] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -805,7 +805,7 @@ func (x *StatusResponse) String() string { func (*StatusResponse) ProtoMessage() {} func (x *StatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[14] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -818,7 +818,7 @@ func (x *StatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. func (*StatusResponse) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{14} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{14} } func (x *StatusResponse) GetCurrentBlock() *Header { @@ -875,7 +875,7 @@ type Header struct { func (x *Header) Reset() { *x = Header{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[15] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -888,7 +888,7 @@ func (x *Header) String() string { func (*Header) ProtoMessage() {} func (x *Header) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[15] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -901,7 +901,7 @@ func (x *Header) ProtoReflect() protoreflect.Message { // Deprecated: Use Header.ProtoReflect.Descriptor instead. func (*Header) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{15} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{15} } func (x *Header) GetHash() string { @@ -931,7 +931,7 @@ type PprofRequest struct { func (x *PprofRequest) Reset() { *x = PprofRequest{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[16] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -944,7 +944,7 @@ func (x *PprofRequest) String() string { func (*PprofRequest) ProtoMessage() {} func (x *PprofRequest) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[16] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -957,7 +957,7 @@ func (x *PprofRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PprofRequest.ProtoReflect.Descriptor instead. func (*PprofRequest) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{16} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16} } func (x *PprofRequest) GetType() PprofRequest_Type { @@ -996,7 +996,7 @@ type PprofResponse struct { func (x *PprofResponse) Reset() { *x = PprofResponse{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[17] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1009,7 +1009,7 @@ func (x *PprofResponse) String() string { func (*PprofResponse) ProtoMessage() {} func (x *PprofResponse) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[17] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1022,7 +1022,7 @@ func (x *PprofResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PprofResponse.ProtoReflect.Descriptor instead. func (*PprofResponse) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{17} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{17} } func (m *PprofResponse) GetEvent() isPprofResponse_Event { @@ -1088,7 +1088,7 @@ type StatusResponse_Fork struct { func (x *StatusResponse_Fork) Reset() { *x = StatusResponse_Fork{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[18] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1101,7 +1101,7 @@ func (x *StatusResponse_Fork) String() string { func (*StatusResponse_Fork) ProtoMessage() {} func (x *StatusResponse_Fork) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[18] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1114,7 +1114,7 @@ func (x *StatusResponse_Fork) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusResponse_Fork.ProtoReflect.Descriptor instead. func (*StatusResponse_Fork) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{14, 0} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{14, 0} } func (x *StatusResponse_Fork) GetName() string { @@ -1151,7 +1151,7 @@ type StatusResponse_Syncing struct { func (x *StatusResponse_Syncing) Reset() { *x = StatusResponse_Syncing{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[19] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1164,7 +1164,7 @@ func (x *StatusResponse_Syncing) String() string { func (*StatusResponse_Syncing) ProtoMessage() {} func (x *StatusResponse_Syncing) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[19] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1177,7 +1177,7 @@ func (x *StatusResponse_Syncing) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusResponse_Syncing.ProtoReflect.Descriptor instead. func (*StatusResponse_Syncing) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{14, 1} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{14, 1} } func (x *StatusResponse_Syncing) GetStartingBlock() int64 { @@ -1213,7 +1213,7 @@ type PprofResponse_Open struct { func (x *PprofResponse_Open) Reset() { *x = PprofResponse_Open{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[20] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1226,7 +1226,7 @@ func (x *PprofResponse_Open) String() string { func (*PprofResponse_Open) ProtoMessage() {} func (x *PprofResponse_Open) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[20] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1239,7 +1239,7 @@ func (x *PprofResponse_Open) ProtoReflect() protoreflect.Message { // Deprecated: Use PprofResponse_Open.ProtoReflect.Descriptor instead. func (*PprofResponse_Open) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{17, 0} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{17, 0} } func (x *PprofResponse_Open) GetHeaders() map[string]string { @@ -1267,7 +1267,7 @@ type PprofResponse_Input struct { func (x *PprofResponse_Input) Reset() { *x = PprofResponse_Input{} if protoimpl.UnsafeEnabled { - mi := &file_command_server_proto_server_proto_msgTypes[21] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1280,7 +1280,7 @@ func (x *PprofResponse_Input) String() string { func (*PprofResponse_Input) ProtoMessage() {} func (x *PprofResponse_Input) ProtoReflect() protoreflect.Message { - mi := &file_command_server_proto_server_proto_msgTypes[21] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1293,7 +1293,7 @@ func (x *PprofResponse_Input) ProtoReflect() protoreflect.Message { // Deprecated: Use PprofResponse_Input.ProtoReflect.Descriptor instead. func (*PprofResponse_Input) Descriptor() ([]byte, []int) { - return file_command_server_proto_server_proto_rawDescGZIP(), []int{17, 1} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{17, 1} } func (x *PprofResponse_Input) GetData() []byte { @@ -1303,181 +1303,182 @@ func (x *PprofResponse_Input) GetData() []byte { return nil } -var File_command_server_proto_server_proto protoreflect.FileDescriptor - -var file_command_server_proto_server_proto_rawDesc = []byte{ - 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, - 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13, 0x0a, 0x11, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x84, 0x01, 0x0a, - 0x12, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6f, 0x6c, 0x64, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x12, 0x2c, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x37, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, - 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x0f, - 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, - 0x12, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, - 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x50, 0x65, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x12, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x05, 0x70, 0x65, 0x65, - 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2a, 0x0a, 0x12, - 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x36, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1f, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, - 0x22, 0x98, 0x01, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, - 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, - 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, - 0x72, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x04, 0x63, 0x61, 0x70, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x22, 0x2d, 0x0a, 0x13, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0xe2, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x33, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0d, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, - 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x6e, - 0x63, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x79, 0x6e, - 0x63, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x79, - 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x30, - 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x6b, 0x73, - 0x1a, 0x4c, 0x0a, 0x04, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x77, - 0x0a, 0x07, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, - 0x22, 0x0a, 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x98, 0x01, - 0x0a, 0x0c, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, - 0x22, 0x26, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x4f, 0x4b, - 0x55, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x50, 0x55, 0x10, 0x01, 0x12, 0x09, 0x0a, - 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x02, 0x22, 0xe1, 0x02, 0x0a, 0x0d, 0x50, 0x70, 0x72, - 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x6f, 0x70, - 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, - 0x70, 0x65, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x69, - 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, +var File_internal_cli_server_proto_server_proto protoreflect.FileDescriptor + +var file_internal_cli_server_proto_server_proto_rawDesc = []byte{ + 0x0a, 0x26, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13, 0x0a, 0x11, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x84, 0x01, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6f, 0x6c, + 0x64, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x37, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x53, 0x74, 0x75, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x22, 0x41, 0x0a, 0x0f, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x65, 0x64, 0x22, 0x12, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, + 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x15, + 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x50, 0x65, 0x65, + 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, + 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, + 0x73, 0x22, 0x2a, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x36, 0x0a, + 0x13, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x04, 0x70, 0x65, 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, + 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x65, 0x6e, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63, 0x61, 0x70, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, + 0x22, 0x2d, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, + 0x16, 0x0a, 0x14, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe2, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x33, 0x0a, + 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x79, + 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x79, 0x6e, 0x63, + 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x05, + 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x1a, 0x4c, 0x0a, 0x04, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x1a, 0x77, 0x0a, 0x07, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x24, + 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x68, 0x69, 0x67, 0x68, + 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x34, 0x0a, 0x06, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, 0x0c, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x26, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, + 0x06, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x50, 0x55, + 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x02, 0x22, 0xe1, 0x02, + 0x0a, 0x0d, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2f, 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, + 0x12, 0x32, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x05, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x12, 0x2a, 0x0a, 0x03, 0x65, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x48, 0x00, 0x52, 0x03, 0x65, 0x6f, 0x66, + 0x1a, 0x98, 0x01, 0x0a, 0x04, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x40, 0x0a, 0x07, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, - 0x2a, 0x0a, 0x03, 0x65, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x48, 0x00, 0x52, 0x03, 0x65, 0x6f, 0x66, 0x1a, 0x98, 0x01, 0x0a, 0x04, - 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x40, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, - 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x1b, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x32, 0x8b, 0x04, 0x0a, - 0x03, 0x42, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x05, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x12, 0x13, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x50, 0x65, - 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, - 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, - 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, - 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, - 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x2e, 0x70, + 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x1a, + 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x1b, 0x0a, 0x05, 0x49, + 0x6e, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x32, 0x8b, 0x04, 0x0a, 0x03, 0x42, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x05, 0x50, 0x70, 0x72, + 0x6f, 0x66, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, + 0x3b, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x12, 0x16, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, + 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x19, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, + 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, - 0x65, 0x61, 0x64, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, - 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, - 0x74, 0x63, 0x68, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x17, 0x5a, 0x15, 0x2f, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x37, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, + 0x1c, 0x5a, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6c, 0x69, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_command_server_proto_server_proto_rawDescOnce sync.Once - file_command_server_proto_server_proto_rawDescData = file_command_server_proto_server_proto_rawDesc + file_internal_cli_server_proto_server_proto_rawDescOnce sync.Once + file_internal_cli_server_proto_server_proto_rawDescData = file_internal_cli_server_proto_server_proto_rawDesc ) -func file_command_server_proto_server_proto_rawDescGZIP() []byte { - file_command_server_proto_server_proto_rawDescOnce.Do(func() { - file_command_server_proto_server_proto_rawDescData = protoimpl.X.CompressGZIP(file_command_server_proto_server_proto_rawDescData) +func file_internal_cli_server_proto_server_proto_rawDescGZIP() []byte { + file_internal_cli_server_proto_server_proto_rawDescOnce.Do(func() { + file_internal_cli_server_proto_server_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_cli_server_proto_server_proto_rawDescData) }) - return file_command_server_proto_server_proto_rawDescData + return file_internal_cli_server_proto_server_proto_rawDescData } -var file_command_server_proto_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_command_server_proto_server_proto_msgTypes = make([]protoimpl.MessageInfo, 23) -var file_command_server_proto_server_proto_goTypes = []interface{}{ +var file_internal_cli_server_proto_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_internal_cli_server_proto_server_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_internal_cli_server_proto_server_proto_goTypes = []interface{}{ (PprofRequest_Type)(0), // 0: proto.PprofRequest.Type (*ChainWatchRequest)(nil), // 1: proto.ChainWatchRequest (*ChainWatchResponse)(nil), // 2: proto.ChainWatchResponse @@ -1504,7 +1505,7 @@ var file_command_server_proto_server_proto_goTypes = []interface{}{ nil, // 23: proto.PprofResponse.Open.HeadersEntry (*emptypb.Empty)(nil), // 24: google.protobuf.Empty } -var file_command_server_proto_server_proto_depIdxs = []int32{ +var file_internal_cli_server_proto_server_proto_depIdxs = []int32{ 3, // 0: proto.ChainWatchResponse.oldchain:type_name -> proto.BlockStub 3, // 1: proto.ChainWatchResponse.newchain:type_name -> proto.BlockStub 12, // 2: proto.PeersListResponse.peers:type_name -> proto.Peer @@ -1541,13 +1542,13 @@ var file_command_server_proto_server_proto_depIdxs = []int32{ 0, // [0:13] is the sub-list for field type_name } -func init() { file_command_server_proto_server_proto_init() } -func file_command_server_proto_server_proto_init() { - if File_command_server_proto_server_proto != nil { +func init() { file_internal_cli_server_proto_server_proto_init() } +func file_internal_cli_server_proto_server_proto_init() { + if File_internal_cli_server_proto_server_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_command_server_proto_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChainWatchRequest); i { case 0: return &v.state @@ -1559,7 +1560,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChainWatchResponse); i { case 0: return &v.state @@ -1571,7 +1572,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockStub); i { case 0: return &v.state @@ -1583,7 +1584,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersAddRequest); i { case 0: return &v.state @@ -1595,7 +1596,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersAddResponse); i { case 0: return &v.state @@ -1607,7 +1608,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersRemoveRequest); i { case 0: return &v.state @@ -1619,7 +1620,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersRemoveResponse); i { case 0: return &v.state @@ -1631,7 +1632,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersListRequest); i { case 0: return &v.state @@ -1643,7 +1644,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersListResponse); i { case 0: return &v.state @@ -1655,7 +1656,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersStatusRequest); i { case 0: return &v.state @@ -1667,7 +1668,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersStatusResponse); i { case 0: return &v.state @@ -1679,7 +1680,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Peer); i { case 0: return &v.state @@ -1691,7 +1692,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChainSetHeadRequest); i { case 0: return &v.state @@ -1703,7 +1704,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChainSetHeadResponse); i { case 0: return &v.state @@ -1715,7 +1716,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StatusResponse); i { case 0: return &v.state @@ -1727,7 +1728,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Header); i { case 0: return &v.state @@ -1739,7 +1740,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PprofRequest); i { case 0: return &v.state @@ -1751,7 +1752,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PprofResponse); i { case 0: return &v.state @@ -1763,7 +1764,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StatusResponse_Fork); i { case 0: return &v.state @@ -1775,7 +1776,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StatusResponse_Syncing); i { case 0: return &v.state @@ -1787,7 +1788,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PprofResponse_Open); i { case 0: return &v.state @@ -1799,7 +1800,7 @@ func file_command_server_proto_server_proto_init() { return nil } } - file_command_server_proto_server_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_internal_cli_server_proto_server_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PprofResponse_Input); i { case 0: return &v.state @@ -1812,7 +1813,7 @@ func file_command_server_proto_server_proto_init() { } } } - file_command_server_proto_server_proto_msgTypes[17].OneofWrappers = []interface{}{ + file_internal_cli_server_proto_server_proto_msgTypes[17].OneofWrappers = []interface{}{ (*PprofResponse_Open_)(nil), (*PprofResponse_Input_)(nil), (*PprofResponse_Eof)(nil), @@ -1821,19 +1822,19 @@ func file_command_server_proto_server_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_command_server_proto_server_proto_rawDesc, + RawDescriptor: file_internal_cli_server_proto_server_proto_rawDesc, NumEnums: 1, NumMessages: 23, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_command_server_proto_server_proto_goTypes, - DependencyIndexes: file_command_server_proto_server_proto_depIdxs, - EnumInfos: file_command_server_proto_server_proto_enumTypes, - MessageInfos: file_command_server_proto_server_proto_msgTypes, + GoTypes: file_internal_cli_server_proto_server_proto_goTypes, + DependencyIndexes: file_internal_cli_server_proto_server_proto_depIdxs, + EnumInfos: file_internal_cli_server_proto_server_proto_enumTypes, + MessageInfos: file_internal_cli_server_proto_server_proto_msgTypes, }.Build() - File_command_server_proto_server_proto = out.File - file_command_server_proto_server_proto_rawDesc = nil - file_command_server_proto_server_proto_goTypes = nil - file_command_server_proto_server_proto_depIdxs = nil + File_internal_cli_server_proto_server_proto = out.File + file_internal_cli_server_proto_server_proto_rawDesc = nil + file_internal_cli_server_proto_server_proto_goTypes = nil + file_internal_cli_server_proto_server_proto_depIdxs = nil } diff --git a/internal/cli/server/proto/server.proto b/internal/cli/server/proto/server.proto index 2dc84bff78..7259e7dacb 100644 --- a/internal/cli/server/proto/server.proto +++ b/internal/cli/server/proto/server.proto @@ -4,7 +4,7 @@ package proto; import "google/protobuf/empty.proto"; -option go_package = "/command/server/proto"; +option go_package = "/internal/cli/server/proto"; service Bor { rpc Pprof(PprofRequest) returns (stream PprofResponse); diff --git a/internal/cli/server/proto/server_grpc.pb.go b/internal/cli/server/proto/server_grpc.pb.go index 9ed2593e47..b3a6244c18 100644 --- a/internal/cli/server/proto/server_grpc.pb.go +++ b/internal/cli/server/proto/server_grpc.pb.go @@ -1,8 +1,4 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.17.3 -// source: command/server/proto/server.proto package proto @@ -409,5 +405,5 @@ var Bor_ServiceDesc = grpc.ServiceDesc{ ServerStreams: true, }, }, - Metadata: "command/server/proto/server.proto", + Metadata: "internal/cli/server/proto/server.proto", } diff --git a/scripts/tools-protobuf.sh b/scripts/tools-protobuf.sh index fe03cab3cb..04144134f4 100755 --- a/scripts/tools-protobuf.sh +++ b/scripts/tools-protobuf.sh @@ -1,15 +1,24 @@ #!/bin/bash # Install protobuf -PROTOC_ZIP=protoc-3.12.0-linux-x86_64.zip -curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.12.0/$PROTOC_ZIP +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + os="linux" +elif [[ "$OSTYPE" == "darwin"* ]]; then + os="osx" +else + echo "Unsupported platform" + exit 1 +fi + +PROTOC_ZIP=protoc-3.19.3-$os-x86_64.zip +curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.19.3/$PROTOC_ZIP sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc sudo unzip -o $PROTOC_ZIP -d /usr/local 'include/*' rm -f $PROTOC_ZIP # Change permissions to use the binary -sudo chmod 755 -R /usr/local/bin/protoc -sudo chmod 755 -R /usr/local/include +sudo chmod -R 755 /usr/local/bin/protoc +sudo chmod -R 755 /usr/local/include # Install golang extensions (DO NOT CHANGE THE VERSIONS) go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.25.0 From 66fc055a7b7fc0695f0e00e1d7976b4aeede9975 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Thu, 3 Feb 2022 14:37:46 +0100 Subject: [PATCH 04/80] Build and run the new CLI (#318) * Build and run the new CLI --- .goreleaser.yml | 8 ++++---- Makefile | 10 +--------- README.md | 12 ------------ builder/files/bor.service | 22 +++++++++++----------- 4 files changed, 16 insertions(+), 36 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 331d8de6b5..d09cc43206 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -7,7 +7,7 @@ release: builds: - id: darwin-amd64 - main: ./cmd/geth + main: ./cmd/cli binary: bor goos: - darwin @@ -22,7 +22,7 @@ builds: -s -w - id: darwin-arm64 - main: ./cmd/geth + main: ./cmd/cli binary: bor goos: - darwin @@ -37,7 +37,7 @@ builds: -s -w - id: linux-amd64 - main: ./cmd/geth + main: ./cmd/cli binary: bor goos: - linux @@ -53,7 +53,7 @@ builds: -s -w -extldflags "-static" - id: linux-arm64 - main: ./cmd/geth + main: ./cmd/cli binary: bor goos: - linux diff --git a/Makefile b/Makefile index 5bee26f690..678af31c46 100644 --- a/Makefile +++ b/Makefile @@ -10,16 +10,8 @@ GORUN = env GO111MODULE=on go run GOPATH = $(shell go env GOPATH) bor: - $(GORUN) build/ci.go install ./cmd/geth - mkdir -p $(GOPATH)/bin/ - cp $(GOBIN)/geth $(GOBIN)/bor - cp $(GOBIN)/* $(GOPATH)/bin/ - -bor-all: - $(GORUN) build/ci.go install mkdir -p $(GOPATH)/bin/ - cp $(GOBIN)/geth $(GOBIN)/bor - cp $(GOBIN)/* $(GOPATH)/bin/ + go build -o $(GOBIN)/bor ./cmd/cli/main.go protoc: protoc --go_out=. --go-grpc_out=. ./internal/cli/server/proto/*.proto diff --git a/README.md b/README.md index 1dacae0219..4e33a551d0 100644 --- a/README.md +++ b/README.md @@ -63,12 +63,6 @@ them using your favourite package manager. Once the dependencies are installed, $ make bor ``` -- or, to build the full suite of utilities: - - ```shell - $ make bor-all - ``` - ### Make awesome changes! 1. Create new branch for your changes @@ -113,12 +107,6 @@ them using your favourite package manager. Once the dependencies are installed,
-Build the beta client: - -```shell -go build -o bor-beta command/*.go -``` - ## License The go-ethereum library (i.e. all code outside of the `cmd` directory) is licensed under the diff --git a/builder/files/bor.service b/builder/files/bor.service index fa84320a6c..4f834a3cb4 100644 --- a/builder/files/bor.service +++ b/builder/files/bor.service @@ -6,19 +6,19 @@ [Service] Restart=on-failure RestartSec=5s - ExecStart=/usr/local/bin/bor \ - --bor-mumbai \ - # --bor-mainnet \ - --datadir /var/lib/bor/data \ - --bootnodes "enode://0cb82b395094ee4a2915e9714894627de9ed8498fb881cec6db7c65e8b9a5bd7f2f25cc84e71e89d0947e51c76e85d0847de848c7782b13c0255247a6758178c@44.232.55.71:30303,enode://88116f4295f5a31538ae409e4d44ad40d22e44ee9342869e7d68bdec55b0f83c1530355ce8b41fbec0928a7d75a5745d528450d30aec92066ab6ba1ee351d710@159.203.9.164:30303" + ExecStart=/usr/local/bin/bor server \ + -chain=mumbai \ + # -chain=mainnet \ + -datadir /var/lib/bor/data \ + -bootnodes "enode://0cb82b395094ee4a2915e9714894627de9ed8498fb881cec6db7c65e8b9a5bd7f2f25cc84e71e89d0947e51c76e85d0847de848c7782b13c0255247a6758178c@44.232.55.71:30303,enode://88116f4295f5a31538ae409e4d44ad40d22e44ee9342869e7d68bdec55b0f83c1530355ce8b41fbec0928a7d75a5745d528450d30aec92066ab6ba1ee351d710@159.203.9.164:30303" # Validator params # Uncomment and configure the following lines in case you run a validator - # --keystore /var/lib/bor/keystore \ - # --unlock [VALIDATOR ADDRESS] \ - # --password /var/lib/bor/password.txt \ - # --allow-insecure-unlock \ - # --nodiscover --maxpeers 1 \ - # --mine + # -keystore /var/lib/bor/keystore \ + # -unlock [VALIDATOR ADDRESS] \ + # -password /var/lib/bor/password.txt \ + # -allow-insecure-unlock \ + # -nodiscover -maxpeers 1 \ + # -mine Type=simple User=root KillSignal=SIGINT From e10b10a3dd321d8daa6b2dd91343c13ae2fe9e48 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Fri, 4 Feb 2022 20:10:26 +0530 Subject: [PATCH 05/80] start http rpc server and eth namespace by default (#319) --- internal/cli/server/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 06ec8c16af..9f5e4fa81f 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -443,11 +443,11 @@ func DefaultConfig() *Config { GasCap: ethconfig.Defaults.RPCGasCap, TxFeeCap: ethconfig.Defaults.RPCTxFeeCap, Http: &APIConfig{ - Enabled: false, + Enabled: true, Port: 8545, Prefix: "", Host: "localhost", - Modules: []string{"web3", "net"}, + Modules: []string{"eth", "web3", "net"}, }, Ws: &APIConfig{ Enabled: false, From 1ef2726beb6fae2eac66ca5f72215706b144ba7a Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Fri, 21 Jan 2022 17:56:30 +0530 Subject: [PATCH 06/80] Add ability to run using chain json file --- internal/cli/server/chains/chain.go | 30 +++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/internal/cli/server/chains/chain.go b/internal/cli/server/chains/chain.go index 05c12ef0b0..570619609d 100644 --- a/internal/cli/server/chains/chain.go +++ b/internal/cli/server/chains/chain.go @@ -1,6 +1,9 @@ package chains import ( + "encoding/json" + "io/ioutil" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" ) @@ -19,6 +22,29 @@ var chains = map[string]*Chain{ } func GetChain(name string) (*Chain, bool) { - chain, ok := chains[name] - return chain, ok + chain, err := ImportFromFile(name) + if err != nil { + chain, ok := chains[name] + return chain, ok + } + return chain, true +} + +func ImportFromFile(filename string) (*Chain, error) { + data, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + + return importChain(data) +} + +func importChain(content []byte) (*Chain, error) { + var chain *Chain + + if err := json.Unmarshal(content, &chain); err != nil { + return nil, err + } + + return chain, nil } From b3984096e2b212fc28d41304ac851749f030abcd Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Fri, 21 Jan 2022 19:28:07 +0530 Subject: [PATCH 07/80] Updated file check --- internal/cli/server/chains/chain.go | 25 +++++++++++++++++++------ internal/cli/server/config.go | 9 +++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/internal/cli/server/chains/chain.go b/internal/cli/server/chains/chain.go index 570619609d..4fc7bad5d1 100644 --- a/internal/cli/server/chains/chain.go +++ b/internal/cli/server/chains/chain.go @@ -2,7 +2,10 @@ package chains import ( "encoding/json" + "errors" + "fmt" "io/ioutil" + "os" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -21,13 +24,23 @@ var chains = map[string]*Chain{ "mumbai": mumbaiTestnet, } -func GetChain(name string) (*Chain, bool) { - chain, err := ImportFromFile(name) - if err != nil { - chain, ok := chains[name] - return chain, ok +func GetChain(name string) (*Chain, error) { + var chain *Chain + var err error + if _, fileErr := os.Stat(name); fileErr == nil { + if chain, err = ImportFromFile(name); err != nil { + return nil, fmt.Errorf("error importing chain from file: %v", err) + } + return chain, nil + } else if errors.Is(fileErr, os.ErrNotExist) { + var ok bool + if chain, ok = chains[name]; !ok { + return nil, fmt.Errorf("chain %s not found", name) + } + return chain, nil + } else { + return nil, fileErr } - return chain, true } func ImportFromFile(filename string) (*Chain, error) { diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 9f5e4fa81f..29cb8ffa21 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -591,12 +591,9 @@ func readConfigFile(path string) (*Config, error) { } func (c *Config) loadChain() error { - if c.Developer.Enabled { - return nil - } - chain, ok := chains.GetChain(c.Chain) - if !ok { - return fmt.Errorf("chain '%s' not found", c.Chain) + chain, err := chains.GetChain(c.Chain) + if err != nil { + return err } c.chain = chain From d7ebe2fca1c06cc6f15a0d825803cff2420d2f80 Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Mon, 24 Jan 2022 11:26:31 +0530 Subject: [PATCH 08/80] Add test case for Import from file --- internal/cli/server/chains/chain_test.go | 36 ++++++++ .../server/chains/test_files/chain_test.json | 92 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 internal/cli/server/chains/chain_test.go create mode 100644 internal/cli/server/chains/test_files/chain_test.json diff --git a/internal/cli/server/chains/chain_test.go b/internal/cli/server/chains/chain_test.go new file mode 100644 index 0000000000..d9bc638af2 --- /dev/null +++ b/internal/cli/server/chains/chain_test.go @@ -0,0 +1,36 @@ +package chains + +import ( + "testing" +) + +func TestImportFromFile(t *testing.T) { + type args struct { + filename string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "ImportFromFile correct json file", + args: args{filename: "test_files/chain_test.json"}, + wantErr: false, + }, + { + name: "ImportFromFile nonexistent json file", + args: args{filename: "test_files/chain_test_nonexistent.json"}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := ImportFromFile(tt.args.filename) + if (err != nil) != tt.wantErr { + t.Errorf("ImportFromFile() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} diff --git a/internal/cli/server/chains/test_files/chain_test.json b/internal/cli/server/chains/test_files/chain_test.json new file mode 100644 index 0000000000..5bfe155d27 --- /dev/null +++ b/internal/cli/server/chains/test_files/chain_test.json @@ -0,0 +1,92 @@ +{ + "Hash":"0x7b66506a9ebdbf30d32b43c5f15a3b1216269a1ec3a75aa3182b86176a2b1ca7", + "Genesis":{ + "config":{ + "chainId":80001, + "homesteadBlock":0, + "daoForkSupport":true, + "eip150Block":0, + "eip150Hash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":2722000, + "muirGlacierBlock":2722000, + "berlinBlock":13996000, + "londonBlock":13996000, + "bor":{ + "period":{ + "0":2 + }, + "producerDelay":6, + "sprint":64, + "backupMultiplier":{ + "0":2 + }, + "validatorContract":"0x0000000000000000000000000000000000001000", + "stateReceiverContract":"0x0000000000000000000000000000000000001001", + "overrideStateSyncRecords":null, + "blockAlloc":{ + "22244000":{ + "0000000000000000000000000000000000001010":{ + "balance":"0x0", + "code":"0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611548565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154e565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115db565b005b348015610b2e57600080fd5b50610b376115f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161e90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da96023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163e90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d866023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165d565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611755565b90505b92915050565b6040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b12565b611be8565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611dcc605291396040516020018082805190602001908083835b6020831061159d578051825260208201915060208101905060208303925061157a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e3611381565b6115ec57600080fd5b6115f58161165d565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162d57600080fd5b600082840390508091505092915050565b60008082840190508381101561165357600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169757600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d557600080fd5b505afa1580156117e9573d6000803e3d6000fd5b505050506040513d60208110156117ff57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561189157600080fd5b505afa1580156118a5573d6000803e3d6000fd5b505050506040513d60208110156118bb57600080fd5b810190808051906020019092919050505090506118d9868686611c32565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119e157600080fd5b505afa1580156119f5573d6000803e3d6000fd5b505050506040513d6020811015611a0b57600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9957600080fd5b505afa158015611aad573d6000803e3d6000fd5b505050506040513d6020811015611ac357600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b60208310611b645780518252602082019150602081019050602083039250611b41565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d1a573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820ccd6c2a9c259832bbb367986ee06cd87af23022681b0cb22311a864b701d939564736f6c63430005100032" + } + } + }, + "burntContract":{ + "22640000":"0x70bcA57F4579f58670aB2d18Ef16e02C17553C38" + }, + "jaipurBlock":22770000 + } + }, + "nonce":"0x0", + "timestamp":"0x5ce28211", + "extraData":"0x", + "gasLimit":"0x989680", + "difficulty":"0x1", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0000000000000000000000000000000000001000":{ + "code":"0x608060405234801561001057600080fd5b50600436106101f05760003560e01c806360c8614d1161010f578063af26aa96116100a2578063d5b844eb11610071578063d5b844eb14610666578063dcf2793a14610684578063e3b7c924146106b6578063f59cf565146106d4576101f0565b8063af26aa96146105c7578063b71d7a69146105e7578063b7ab4db514610617578063c1b3c91914610636576101f0565b806370ba5707116100de57806370ba57071461052b57806398ab2b621461055b5780639d11b80714610579578063ae756451146105a9576101f0565b806360c8614d1461049c57806365b3a1e2146104bc57806366332354146104db578063687a9bd6146104f9576101f0565b80633434735f1161018757806344d6528f1161015657806344d6528f146103ee5780634dbc959f1461041e57806355614fcc1461043c578063582a8d081461046c576101f0565b80633434735f1461035257806335ddfeea1461037057806343ee8213146103a057806344c15cb1146103be576101f0565b806323f2a73f116101c357806323f2a73f146102a45780632bc06564146102d45780632de3a180146102f25780632eddf35214610322576101f0565b8063047a6c5b146101f55780630c35b1cb146102275780631270b5741461025857806323c2a2b414610288575b600080fd5b61020f600480360361020a9190810190612b24565b610706565b60405161021e93929190613463565b60405180910390f35b610241600480360361023c9190810190612b24565b61075d565b60405161024f929190613284565b60405180910390f35b610272600480360361026d9190810190612b4d565b610939565b60405161027f91906132bb565b60405180910390f35b6102a2600480360361029d9190810190612c2c565b610a91565b005b6102be60048036036102b99190810190612b4d565b61112a565b6040516102cb91906132bb565b60405180910390f35b6102dc611281565b6040516102e99190613411565b60405180910390f35b61030c60048036036103079190810190612a81565b611286565b60405161031991906132d6565b60405180910390f35b61033c60048036036103379190810190612b24565b611307565b6040516103499190613411565b60405180910390f35b61035a611437565b6040516103679190613269565b60405180910390f35b61038a60048036036103859190810190612abd565b61144f565b60405161039791906132bb565b60405180910390f35b6103a861151a565b6040516103b591906132d6565b60405180910390f35b6103d860048036036103d39190810190612b89565b611531565b6040516103e59190613411565b60405180910390f35b61040860048036036104039190810190612b4d565b611619565b60405161041591906133f6565b60405180910390f35b610426611781565b6040516104339190613411565b60405180910390f35b61045660048036036104519190810190612a06565b611791565b60405161046391906132bb565b60405180910390f35b61048660048036036104819190810190612a2f565b6117ab565b60405161049391906132d6565b60405180910390f35b6104a4611829565b6040516104b393929190613463565b60405180910390f35b6104c461189d565b6040516104d2929190613284565b60405180910390f35b6104e3611b6e565b6040516104f09190613411565b60405180910390f35b610513600480360361050e9190810190612bf0565b611b73565b6040516105229392919061342c565b60405180910390f35b61054560048036036105409190810190612a06565b611bd7565b60405161055291906132bb565b60405180910390f35b610563611bf1565b60405161057091906132d6565b60405180910390f35b610593600480360361058e9190810190612b24565b611c08565b6040516105a09190613411565b60405180910390f35b6105b1611d39565b6040516105be91906132d6565b60405180910390f35b6105cf611d50565b6040516105de93929190613463565b60405180910390f35b61060160048036036105fc9190810190612b24565b611db1565b60405161060e9190613411565b60405180910390f35b61061f611eb1565b60405161062d929190613284565b60405180910390f35b610650600480360361064b9190810190612b24565b611ec5565b60405161065d9190613411565b60405180910390f35b61066e611ee6565b60405161067b919061349a565b60405180910390f35b61069e60048036036106999190810190612bf0565b611eeb565b6040516106ad9392919061342c565b60405180910390f35b6106be611f4f565b6040516106cb9190613411565b60405180910390f35b6106ee60048036036106e99190810190612b24565b611f61565b6040516106fd93929190613463565b60405180910390f35b60008060006002600085815260200190815260200160002060000154600260008681526020019081526020016000206001015460026000878152602001908152602001600020600201549250925092509193909250565b60608060ff83116107795761077061189d565b91509150610934565b600061078484611db1565b9050606060016000838152602001908152602001600020805490506040519080825280602002602001820160405280156107cd5781602001602082028038833980820191505090505b509050606060016000848152602001908152602001600020805490506040519080825280602002602001820160405280156108175781602001602082028038833980820191505090505b50905060008090505b60016000858152602001908152602001600020805490508110156109295760016000858152602001908152602001600020818154811061085c57fe5b906000526020600020906003020160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683828151811061089a57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001600085815260200190815260200160002081815481106108f257fe5b90600052602060002090600302016001015482828151811061091057fe5b6020026020010181815250508080600101915050610820565b508181945094505050505b915091565b6000606060016000858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610a0c578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190610970565b50505050905060008090505b8151811015610a84578373ffffffffffffffffffffffffffffffffffffffff16828281518110610a4457fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff161415610a7757600192505050610a8b565b8080600101915050610a18565b5060009150505b92915050565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0a906133d6565b60405180910390fd5b6000610b1d611781565b90506000811415610b3157610b30611f8b565b5b610b456001826122ac90919063ffffffff16565b8814610b86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7d90613356565b60405180910390fd5b868611610bc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bbf906133b6565b60405180910390fd5b6000604060018989030181610bd957fe5b0614610c1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1190613396565b60405180910390fd5b8660026000838152602001908152602001600020600101541115610c73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6a90613336565b60405180910390fd5b6000600260008a81526020019081526020016000206000015414610ccc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc390613376565b60405180910390fd5b604051806060016040528089815260200188815260200187815250600260008a8152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050600388908060018154018082558091505090600182039060005260206000200160009091929091909150555060008060008a815260200190815260200160002081610d669190612800565b506000600160008a815260200190815260200160002081610d879190612800565b506060610ddf610dda87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506122cb565b6122f9565b905060008090505b8151811015610f51576060610e0e838381518110610e0157fe5b60200260200101516122f9565b90506000808c81526020019081526020016000208054809190600101610e349190612800565b506040518060600160405280610e5d83600081518110610e5057fe5b60200260200101516123d6565b8152602001610e7f83600181518110610e7257fe5b60200260200101516123d6565b8152602001610ea183600281518110610e9457fe5b6020026020010151612447565b73ffffffffffffffffffffffffffffffffffffffff168152506000808d81526020019081526020016000208381548110610ed757fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050508080600101915050610de7565b506060610fa9610fa486868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506122cb565b6122f9565b905060008090505b815181101561111d576060610fd8838381518110610fcb57fe5b60200260200101516122f9565b9050600160008d81526020019081526020016000208054809190600101610fff9190612800565b5060405180606001604052806110288360008151811061101b57fe5b60200260200101516123d6565b815260200161104a8360018151811061103d57fe5b60200260200101516123d6565b815260200161106c8360028151811061105f57fe5b6020026020010151612447565b73ffffffffffffffffffffffffffffffffffffffff16815250600160008e815260200190815260200160002083815481106110a357fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050508080600101915050610fb1565b5050505050505050505050565b60006060600080858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156111fc578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611160565b50505050905060008090505b8151811015611274578373ffffffffffffffffffffffffffffffffffffffff1682828151811061123457fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff1614156112675760019250505061127b565b8080600101915050611208565b5060009150505b92915050565b604081565b60006002600160f81b84846040516020016112a3939291906131d6565b6040516020818303038152906040526040516112bf9190613213565b602060405180830381855afa1580156112dc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506112ff9190810190612a58565b905092915050565b60006060600080848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156113d9578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001906001019061133d565b505050509050600080905060008090505b825181101561142c5761141d83828151811061140257fe5b602002602001015160200151836122ac90919063ffffffff16565b915080806001019150506113ea565b508092505050919050565b73fffffffffffffffffffffffffffffffffffffffe81565b600080600080859050600060218087518161146657fe5b04029050600081111561147f5761147c876117ab565b91505b6000602190505b818111611509576000600182038801519050818801519550806000602081106114ab57fe5b1a60f81b9450600060f81b857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156114f0576114e98685611286565b93506114fd565b6114fa8487611286565b93505b50602181019050611486565b508782149450505050509392505050565b60405161152690613254565b604051809103902081565b60008060009050600080905060008090505b84518167ffffffffffffffff16101561160c57606061156e868367ffffffffffffffff16604161246a565b9050600061158582896124f690919063ffffffff16565b905061158f612832565b6115998a83611619565b90506115a58a8361112a565b80156115dc57508473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16115b156115fe578194506115fb8160200151876122ac90919063ffffffff16565b95505b505050604181019050611543565b5081925050509392505050565b611621612832565b6060600080858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156116f1578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611655565b50505050905060008090505b8151811015611779578373ffffffffffffffffffffffffffffffffffffffff1682828151811061172957fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff16141561176c5781818151811061175d57fe5b60200260200101519250611779565b80806001019150506116fd565b505092915050565b600061178c43611db1565b905090565b60006117a461179e611781565b8361112a565b9050919050565b60006002600060f81b836040516020016117c69291906131aa565b6040516020818303038152906040526040516117e29190613213565b602060405180830381855afa1580156117ff573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506118229190810190612a58565b9050919050565b60008060008061184a600161183c611781565b6122ac90919063ffffffff16565b905060026000828152602001908152602001600020600001546002600083815260200190815260200160002060010154600260008481526020019081526020016000206002015493509350935050909192565b606080606060056040519080825280602002602001820160405280156118d25781602001602082028038833980820191505090505b50905073c26880a0af2ea0c7e8130e6ec47af756465452e8816000815181106118f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073be188d6641e8b680743a4815dfa0f6208038960f8160018151811061195357fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c275dc8be39f50d12f66b6a63629c39da5bae5bd816002815181106119af57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073f903ba9e006193c1527bfbe65fe2123704ea3f9981600381518110611a0b57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073928ed6a3e94437bbd316ccad78479f1d163a6a8c81600481518110611a6757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060606005604051908082528060200260200182016040528015611ad35781602001602082028038833980820191505090505b50905061271081600081518110611ae657fe5b60200260200101818152505061271081600181518110611b0257fe5b60200260200101818152505061271081600281518110611b1e57fe5b60200260200101818152505061271081600381518110611b3a57fe5b60200260200101818152505061271081600481518110611b5657fe5b60200260200101818152505081819350935050509091565b60ff81565b60016020528160005260406000208181548110611b8c57fe5b9060005260206000209060030201600091509150508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b6000611bea611be4611781565b83610939565b9050919050565b604051611bfd9061322a565b604051809103902081565b6000606060016000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611cdb578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611c3f565b505050509050600080905060008090505b8251811015611d2e57611d1f838281518110611d0457fe5b602002602001015160200151836122ac90919063ffffffff16565b91508080600101915050611cec565b508092505050919050565b604051611d459061323f565b604051809103902081565b600080600080611d5e611781565b905060026000828152602001908152602001600020600001546002600083815260200190815260200160002060010154600260008481526020019081526020016000206002015493509350935050909192565b60008060038054905090505b6000811115611e7157611dce612869565b6002600060036001850381548110611de257fe5b906000526020600020015481526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905083816020015111158015611e3f57506000816040015114155b8015611e4f575080604001518411155b15611e6257806000015192505050611eac565b50808060019003915050611dbd565b5060006003805490501115611ea757600360016003805490500381548110611e9557fe5b90600052602060002001549050611eac565b600090505b919050565b606080611ebd4361075d565b915091509091565b60038181548110611ed257fe5b906000526020600020016000915090505481565b600281565b60006020528160005260406000208181548110611f0457fe5b9060005260206000209060030201600091509150508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b600060404381611f5b57fe5b04905090565b60026020528060005260406000206000915090508060000154908060010154908060020154905083565b606080611f9661189d565b8092508193505050600080905060405180606001604052808281526020016000815260200160ff81525060026000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050600381908060018154018082558091505090600182039060005260206000200160009091929091909150555060008060008381526020019081526020016000208161203f9190612800565b50600060016000838152602001908152602001600020816120609190612800565b5060008090505b83518110156121825760008083815260200190815260200160002080548091906001016120949190612800565b5060405180606001604052808281526020018483815181106120b257fe5b602002602001015181526020018583815181106120cb57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16815250600080848152602001908152602001600020828154811061210957fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508080600101915050612067565b5060008090505b83518110156122a6576001600083815260200190815260200160002080548091906001016121b79190612800565b5060405180606001604052808281526020018483815181106121d557fe5b602002602001015181526020018583815181106121ee57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681525060016000848152602001908152602001600020828154811061222d57fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508080600101915050612189565b50505050565b6000808284019050838110156122c157600080fd5b8091505092915050565b6122d361288a565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061230482612600565b61230d57600080fd5b60006123188361264e565b905060608160405190808252806020026020018201604052801561235657816020015b6123436128a4565b81526020019060019003908161233b5790505b509050600061236885602001516126bf565b8560200151019050600080600090505b848110156123c95761238983612748565b91506040518060400160405280838152602001848152508482815181106123ac57fe5b602002602001018190525081830192508080600101915050612378565b5082945050505050919050565b60008082600001511180156123f057506021826000015111155b6123f957600080fd5b600061240883602001516126bf565b9050600081846000015103905060008083866020015101905080519150602083101561243b57826020036101000a820491505b81945050505050919050565b6000601582600001511461245a57600080fd5b612463826123d6565b9050919050565b60608183018451101561247c57600080fd5b6060821560008114612499576040519150602082016040526124ea565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156124d757805183526020830192506020810190506124ba565b50868552601f19601f8301166040525050505b50809150509392505050565b600080600080604185511461251157600093505050506125fa565b602085015192506040850151915060ff6041860151169050601b8160ff16101561253c57601b810190505b601b8160ff16141580156125545750601c8160ff1614155b1561256557600093505050506125fa565b60006001878386866040516000815260200160405260405161258a94939291906132f1565b6020604051602081039080840390855afa1580156125ac573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125f257600080fd5b809450505050505b92915050565b600080826000015114156126175760009050612649565b60008083602001519050805160001a915060c060ff168260ff16101561264257600092505050612649565b6001925050505b919050565b6000808260000151141561266557600090506126ba565b6000809050600061267984602001516126bf565b84602001510190506000846000015185602001510190505b808210156126b3576126a282612748565b820191508280600101935050612691565b8293505050505b919050565b600080825160001a9050608060ff168110156126df576000915050612743565b60b860ff16811080612704575060c060ff168110158015612703575060f860ff1681105b5b15612713576001915050612743565b60c060ff168110156127335760018060b80360ff16820301915050612743565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561276957600191506127f6565b60b860ff16811015612786576001608060ff1682030191506127f5565b60c060ff168110156127b65760b78103600185019450806020036101000a855104600182018101935050506127f4565b60f860ff168110156127d357600160c060ff1682030191506127f3565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b81548183558181111561282d5760030281600302836000526020600020918201910161282c91906128be565b5b505050565b60405180606001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b60405180606001604052806000815260200160008152602001600081525090565b604051806040016040528060008152602001600081525090565b604051806040016040528060008152602001600081525090565b61291191905b8082111561290d5760008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506003016128c4565b5090565b90565b60008135905061292381613693565b92915050565b600081359050612938816136aa565b92915050565b60008151905061294d816136aa565b92915050565b60008083601f84011261296557600080fd5b8235905067ffffffffffffffff81111561297e57600080fd5b60208301915083600182028301111561299657600080fd5b9250929050565b600082601f8301126129ae57600080fd5b81356129c16129bc826134e2565b6134b5565b915080825260208301602083018583830111156129dd57600080fd5b6129e883828461363d565b50505092915050565b600081359050612a00816136c1565b92915050565b600060208284031215612a1857600080fd5b6000612a2684828501612914565b91505092915050565b600060208284031215612a4157600080fd5b6000612a4f84828501612929565b91505092915050565b600060208284031215612a6a57600080fd5b6000612a788482850161293e565b91505092915050565b60008060408385031215612a9457600080fd5b6000612aa285828601612929565b9250506020612ab385828601612929565b9150509250929050565b600080600060608486031215612ad257600080fd5b6000612ae086828701612929565b9350506020612af186828701612929565b925050604084013567ffffffffffffffff811115612b0e57600080fd5b612b1a8682870161299d565b9150509250925092565b600060208284031215612b3657600080fd5b6000612b44848285016129f1565b91505092915050565b60008060408385031215612b6057600080fd5b6000612b6e858286016129f1565b9250506020612b7f85828601612914565b9150509250929050565b600080600060608486031215612b9e57600080fd5b6000612bac868287016129f1565b9350506020612bbd86828701612929565b925050604084013567ffffffffffffffff811115612bda57600080fd5b612be68682870161299d565b9150509250925092565b60008060408385031215612c0357600080fd5b6000612c11858286016129f1565b9250506020612c22858286016129f1565b9150509250929050565b600080600080600080600060a0888a031215612c4757600080fd5b6000612c558a828b016129f1565b9750506020612c668a828b016129f1565b9650506040612c778a828b016129f1565b955050606088013567ffffffffffffffff811115612c9457600080fd5b612ca08a828b01612953565b9450945050608088013567ffffffffffffffff811115612cbf57600080fd5b612ccb8a828b01612953565b925092505092959891949750929550565b6000612ce88383612d0c565b60208301905092915050565b6000612d00838361317d565b60208301905092915050565b612d15816135b2565b82525050565b612d24816135b2565b82525050565b6000612d358261352e565b612d3f8185613569565b9350612d4a8361350e565b8060005b83811015612d7b578151612d628882612cdc565b9750612d6d8361354f565b925050600181019050612d4e565b5085935050505092915050565b6000612d9382613539565b612d9d818561357a565b9350612da88361351e565b8060005b83811015612dd9578151612dc08882612cf4565b9750612dcb8361355c565b925050600181019050612dac565b5085935050505092915050565b612def816135c4565b82525050565b612e06612e01826135d0565b61367f565b82525050565b612e15816135fc565b82525050565b612e2c612e27826135fc565b613689565b82525050565b6000612e3d82613544565b612e47818561358b565b9350612e5781856020860161364c565b80840191505092915050565b6000612e706004836135a7565b91507f766f7465000000000000000000000000000000000000000000000000000000006000830152600482019050919050565b6000612eb0602d83613596565b91507f537461727420626c6f636b206d7573742062652067726561746572207468616e60008301527f2063757272656e74207370616e000000000000000000000000000000000000006020830152604082019050919050565b6000612f16600f83613596565b91507f496e76616c6964207370616e20696400000000000000000000000000000000006000830152602082019050919050565b6000612f56601383613596565b91507f5370616e20616c726561647920657869737473000000000000000000000000006000830152602082019050919050565b6000612f96604583613596565b91507f446966666572656e6365206265747765656e20737461727420616e6420656e6460008301527f20626c6f636b206d75737420626520696e206d756c7469706c6573206f66207360208301527f7072696e740000000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000613022602a83613596565b91507f456e6420626c6f636b206d7573742062652067726561746572207468616e207360008301527f7461727420626c6f636b000000000000000000000000000000000000000000006020830152604082019050919050565b6000613088601283613596565b91507f4e6f742053797374656d204164646573732100000000000000000000000000006000830152602082019050919050565b60006130c86005836135a7565b91507f38303030310000000000000000000000000000000000000000000000000000006000830152600582019050919050565b6000613108600e836135a7565b91507f6865696d64616c6c2d38303030310000000000000000000000000000000000006000830152600e82019050919050565b606082016000820151613151600085018261317d565b506020820151613164602085018261317d565b5060408201516131776040850182612d0c565b50505050565b61318681613626565b82525050565b61319581613626565b82525050565b6131a481613630565b82525050565b60006131b68285612df5565b6001820191506131c68284612e1b565b6020820191508190509392505050565b60006131e28286612df5565b6001820191506131f28285612e1b565b6020820191506132028284612e1b565b602082019150819050949350505050565b600061321f8284612e32565b915081905092915050565b600061323582612e63565b9150819050919050565b600061324a826130bb565b9150819050919050565b600061325f826130fb565b9150819050919050565b600060208201905061327e6000830184612d1b565b92915050565b6000604082019050818103600083015261329e8185612d2a565b905081810360208301526132b28184612d88565b90509392505050565b60006020820190506132d06000830184612de6565b92915050565b60006020820190506132eb6000830184612e0c565b92915050565b60006080820190506133066000830187612e0c565b613313602083018661319b565b6133206040830185612e0c565b61332d6060830184612e0c565b95945050505050565b6000602082019050818103600083015261334f81612ea3565b9050919050565b6000602082019050818103600083015261336f81612f09565b9050919050565b6000602082019050818103600083015261338f81612f49565b9050919050565b600060208201905081810360008301526133af81612f89565b9050919050565b600060208201905081810360008301526133cf81613015565b9050919050565b600060208201905081810360008301526133ef8161307b565b9050919050565b600060608201905061340b600083018461313b565b92915050565b6000602082019050613426600083018461318c565b92915050565b6000606082019050613441600083018661318c565b61344e602083018561318c565b61345b6040830184612d1b565b949350505050565b6000606082019050613478600083018661318c565b613485602083018561318c565b613492604083018461318c565b949350505050565b60006020820190506134af600083018461319b565b92915050565b6000604051905081810181811067ffffffffffffffff821117156134d857600080fd5b8060405250919050565b600067ffffffffffffffff8211156134f957600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006135bd82613606565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b8381101561366a57808201518184015260208101905061364f565b83811115613679576000848401525b50505050565b6000819050919050565b6000819050919050565b61369c816135b2565b81146136a757600080fd5b50565b6136b3816135fc565b81146136be57600080fd5b50565b6136ca81613626565b81146136d557600080fd5b5056fea365627a7a723158208f52ee07630ffe523cc6ad3e15f437f973dcfa36729cd697f9b0fc4a145a48f06c6578706572696d656e74616cf564736f6c634300050b0040", + "balance":"0x0" + }, + "0000000000000000000000000000000000001001":{ + "code":"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806319494a17146100465780633434735f146100e15780635407ca671461012b575b600080fd5b6100c76004803603604081101561005c57600080fd5b81019080803590602001909291908035906020019064010000000081111561008357600080fd5b82018360208201111561009557600080fd5b803590602001918460018302840111640100000000831117156100b757600080fd5b9091929391929390505050610149565b604051808215151515815260200191505060405180910390f35b6100e961047a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610133610492565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061025761025285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610498565b6104c6565b905060006102788260008151811061026b57fe5b60200260200101516105a3565b905080600160005401146102f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103248360018151811061031757fe5b6020026020010151610614565b905060606103458460028151811061033857fe5b6020026020010151610637565b9050610350826106c3565b1561046f576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103aa57808201518184015260208101905061038f565b50505050905090810190601f1680156103d75780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f1965050505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104a0610943565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606104d1826106dc565b6104da57600080fd5b60006104e58361072a565b905060608160405190808252806020026020018201604052801561052357816020015b61051061095d565b8152602001906001900390816105085790505b5090506000610535856020015161079b565b8560200151019050600080600090505b848110156105965761055683610824565b915060405180604001604052808381526020018481525084828151811061057957fe5b602002602001018190525081830192508080600101915050610545565b5082945050505050919050565b60008082600001511180156105bd57506021826000015111155b6105c657600080fd5b60006105d5836020015161079b565b9050600081846000015103905060008083866020015101905080519150602083101561060857826020036101000a820491505b81945050505050919050565b6000601582600001511461062757600080fd5b610630826105a3565b9050919050565b6060600082600001511161064a57600080fd5b6000610659836020015161079b565b905060008184600001510390506060816040519080825280601f01601f19166020018201604052801561069b5781602001600182028038833980820191505090505b50905060008160200190506106b78487602001510182856108dc565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b600080826000015114156106f35760009050610725565b60008083602001519050805160001a915060c060ff168260ff16101561071e57600092505050610725565b6001925050505b919050565b600080826000015114156107415760009050610796565b60008090506000610755846020015161079b565b84602001510190506000846000015185602001510190505b8082101561078f5761077e82610824565b82019150828060010193505061076d565b8293505050505b919050565b600080825160001a9050608060ff168110156107bb57600091505061081f565b60b860ff168110806107e0575060c060ff1681101580156107df575060f860ff1681105b5b156107ef57600191505061081f565b60c060ff1681101561080f5760018060b80360ff1682030191505061081f565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561084557600191506108d2565b60b860ff16811015610862576001608060ff1682030191506108d1565b60c060ff168110156108925760b78103600185019450806020036101000a855104600182018101935050506108d0565b60f860ff168110156108af57600160c060ff1682030191506108cf565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b60008114156108ea5761093e565b5b602060ff16811061091a5782518252602060ff1683019250602060ff1682019150602060ff16810390506108eb565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a7231582083fbdacb76f32b4112d0f7db9a596937925824798a0026ba0232322390b5263764736f6c634300050b0032", + "balance":"0x0" + }, + "0000000000000000000000000000000000001010":{ + "code":"0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610e06565b005b3480156103eb57600080fd5b506103f4610f58565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f61565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061111d565b005b3480156104e857600080fd5b506104f16111ec565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b50610548611212565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611238565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b50610604611259565b005b34801561061257600080fd5b5061061b611329565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061132f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b506107586114b4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af6114dd565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de611534565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e61156d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506115aa565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b506109646115d0565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b810190808035906020019092919050505061165d565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919050505061167d565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a6561169d565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a906116a4565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb6116aa565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611737565b005b348015610b2e57600080fd5b50610b37611754565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b6000808511610c4857600080fd5b6000831480610c575750824311155b610cc9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5369676e6174757265206973206578706972656400000000000000000000000081525060200191505060405180910390fd5b6000610cd73387878761167d565b9050600015156005600083815260200190815260200160002060009054906101000a900460ff16151514610d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f536967206465616374697661746564000000000000000000000000000000000081525060200191505060405180910390fd5b60016005600083815260200190815260200160002060006101000a81548160ff021916908315150217905550610ded8189898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061132f565b9150610dfa82848861177a565b50509695505050505050565b60003390506000610e1682611238565b9050610e2d83600654611b3790919063ffffffff16565b600681905550600083118015610e4257508234145b610eb4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610f3087611238565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610f696114dd565b610f7257600080fd5b600081118015610faf5750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b611004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611e636023913960400191505060405180910390fd5b600061100f83611238565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f1935050505015801561105c573d6000803e3d6000fd5b5061107283600654611b5790919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f685856110f489611238565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611183576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611e406023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506111e882611b76565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b6112616114dd565b61126a57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b600080600080604185511461134a57600093505050506114ae565b602085015192506040850151915060ff6041860151169050601b8160ff16101561137557601b810190505b601b8160ff161415801561138d5750601c8160ff1614155b1561139e57600093505050506114ae565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156113fb573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156114aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b60008134146115bc57600090506115ca565b6115c733848461177a565b90505b92915050565b6040518060800160405280605b8152602001611ed8605b91396040516020018082805190602001908083835b6020831061161f57805182526020820191506020810190506020830392506115fc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061169361168e86868686611c6e565b611d44565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611e86605291396040516020018082805190602001908083835b602083106116f957805182526020820191506020810190506020830392506116d6565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b61173f6114dd565b61174857600080fd5b61175181611b76565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117fa57600080fd5b505afa15801561180e573d6000803e3d6000fd5b505050506040513d602081101561182457600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156118b657600080fd5b505afa1580156118ca573d6000803e3d6000fd5b505050506040513d60208110156118e057600080fd5b810190808051906020019092919050505090506118fe868686611d8e565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a0657600080fd5b505afa158015611a1a573d6000803e3d6000fd5b505050506040513d6020811015611a3057600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611abe57600080fd5b505afa158015611ad2573d6000803e3d6000fd5b505050506040513d6020811015611ae857600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b600082821115611b4657600080fd5b600082840390508091505092915050565b600080828401905083811015611b6c57600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611bb057600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000806040518060800160405280605b8152602001611ed8605b91396040516020018082805190602001908083835b60208310611cc05780518252602082019150602081019050602083039250611c9d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611dd4573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158208f81700133738d766ae3d68af591ad588b0125bd91449192179f460893f79f6b64736f6c634300050b0032", + "balance":"0x204fcd4f31349d83b6e00000" + }, + "928ed6a3e94437bbd316ccad78479f1d163a6a8c":{ + "balance":"0x3635c9adc5dea00000" + }, + "be188d6641e8b680743a4815dfa0f6208038960f":{ + "balance":"0x3635c9adc5dea00000" + }, + "c26880a0af2ea0c7e8130e6ec47af756465452e8":{ + "balance":"0x3635c9adc5dea00000" + }, + "c275dc8be39f50d12f66b6a63629c39da5bae5bd":{ + "balance":"0x3635c9adc5dea00000" + }, + "f903ba9e006193c1527bfbe65fe2123704ea3f99":{ + "balance":"0x3635c9adc5dea00000" + } + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":null + }, + "Bootnodes":[ + "enode://320553cda00dfc003f499a3ce9598029f364fbb3ed1222fdc20a94d97dcc4d8ba0cd0bfa996579dcc6d17a534741fb0a5da303a90579431259150de66b597251@54.147.31.250:30303", + "enode://f0f48a8781629f95ff02606081e6e43e4aebd503f3d07fc931fad7dd5ca1ba52bd849a6f6c3be0e375cf13c9ae04d859c4a9ae3546dc8ed4f10aa5dbb47d4998@34.226.134.117:30303" + ], + "NetworkId":80001, + "DNS":null + } From 98b71173dfbcaa41e0c401363415201e060cfa32 Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Mon, 24 Jan 2022 14:00:09 +0530 Subject: [PATCH 09/80] Rename chain test case --- internal/cli/server/chains/chain_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/server/chains/chain_test.go b/internal/cli/server/chains/chain_test.go index d9bc638af2..0f309b2919 100644 --- a/internal/cli/server/chains/chain_test.go +++ b/internal/cli/server/chains/chain_test.go @@ -4,7 +4,7 @@ import ( "testing" ) -func TestImportFromFile(t *testing.T) { +func TestChain_ImportFromFile(t *testing.T) { type args struct { filename string } From 4e6d323382c9d6bd0768b6a98b07ad7733210a33 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Tue, 15 Feb 2022 20:24:55 +0530 Subject: [PATCH 10/80] Added GetSnapshotProposerSequence --- consensus/bor/api.go | 50 +++++++++++++++++++++++++++++++++++++ internal/web3ext/bor_ext.go | 12 +++++++++ 2 files changed, 62 insertions(+) diff --git a/consensus/bor/api.go b/consensus/bor/api.go index 12841290af..5c3496891f 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -46,6 +46,56 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) } +type BlockSigners struct { + Signers map[common.Address]uint64 + Diff int + Author common.Address +} + +// GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span +func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) { + + var difficulties = make(map[common.Address]uint64) + snap, err := api.GetSnapshot(number) + if err != nil { + return BlockSigners{}, err + } + proposer := snap.ValidatorSet.GetProposer().Address + proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer) + + signers := snap.signers() + for i := 0; i < len(signers); i++ { + tempIndex := i + if tempIndex < proposerIndex { + tempIndex = tempIndex + len(signers) + } + difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex)) + } + + author, err := api.GetAuthor(number) + if err != nil { + return BlockSigners{}, err + } + diff := int(difficulties[*author]) + blockSigners := &BlockSigners{ + Signers: difficulties, + Diff: diff, + Author: *author, + } + + return *blockSigners, nil +} + +// GetSnapshotProposer retrieves the in-turn signer at a given block. +func (api *API) GetSnapshotProposer(number *rpc.BlockNumber) (common.Address, error) { + *number -= 1 + snap, err := api.GetSnapshot(number) + if err != nil { + return common.Address{}, err + } + return snap.ValidatorSet.GetProposer().Address, nil +} + // GetAuthor retrieves the author a block. func (api *API) GetAuthor(number *rpc.BlockNumber) (*common.Address, error) { // Retrieve the requested block number (or current if none requested) diff --git a/internal/web3ext/bor_ext.go b/internal/web3ext/bor_ext.go index b7fe9b4886..fe8b01da19 100644 --- a/internal/web3ext/bor_ext.go +++ b/internal/web3ext/bor_ext.go @@ -17,6 +17,18 @@ web3._extend({ params: 1, inputFormatter: [null] }), + new web3._extend.Method({ + name: 'getSnapshotProposer', + call: 'bor_getSnapshotProposer', + params: 1, + inputFormatter: [null] + }), + new web3._extend.Method({ + name: 'getSnapshotProposerSequence', + call: 'bor_getSnapshotProposerSequence', + params: 1, + inputFormatter: [null] + }), new web3._extend.Method({ name: 'getSnapshotAtHash', call: 'bor_getSnapshotAtHash', From e496afb98c7f7ea2e3c964244d0e8c1b8f7c1933 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 16 Feb 2022 00:28:34 +0530 Subject: [PATCH 11/80] Minor Fix --- consensus/bor/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/bor/api.go b/consensus/bor/api.go index 5c3496891f..b7ffebaf66 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -54,7 +54,7 @@ type BlockSigners struct { // GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) { - + *number -= 1 var difficulties = make(map[common.Address]uint64) snap, err := api.GetSnapshot(number) if err != nil { From e0b43b011684b70b78ed718a6c6a38436521d1ea Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 16 Feb 2022 00:36:02 +0530 Subject: [PATCH 12/80] Minor fix --- consensus/bor/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/consensus/bor/api.go b/consensus/bor/api.go index b7ffebaf66..1a2d140b21 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -54,9 +54,9 @@ type BlockSigners struct { // GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) { - *number -= 1 + snapNumber := *number - 1 var difficulties = make(map[common.Address]uint64) - snap, err := api.GetSnapshot(number) + snap, err := api.GetSnapshot(&snapNumber) if err != nil { return BlockSigners{}, err } From b172ba8fbf06debf2f57bc3f0ee6a5884cffcb7e Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 16 Feb 2022 13:34:03 +0530 Subject: [PATCH 13/80] Sorted Difficulties --- consensus/bor/api.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/consensus/bor/api.go b/consensus/bor/api.go index 1a2d140b21..c6433ce092 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "math" "math/big" + "sort" "strconv" "sync" @@ -47,11 +48,29 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { } type BlockSigners struct { - Signers map[common.Address]uint64 + Signers []difficultiesKV Diff int Author common.Address } +type difficultiesKV struct { + Signer common.Address + Difficulty uint64 +} + +func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV { + + var ss []difficultiesKV + for k, v := range values { + ss = append(ss, difficultiesKV{k, v}) + } + sort.Slice(ss, func(i, j int) bool { + return ss[i].Difficulty > ss[j].Difficulty + }) + + return ss +} + // GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) { snapNumber := *number - 1 @@ -72,13 +91,15 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex)) } + difficulties2 := rankMapDifficulties(difficulties) + author, err := api.GetAuthor(number) if err != nil { return BlockSigners{}, err } diff := int(difficulties[*author]) blockSigners := &BlockSigners{ - Signers: difficulties, + Signers: difficulties2, Diff: diff, Author: *author, } From c3d180cc466956e49477dac611539aad4ce48659 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 16 Feb 2022 23:55:31 +0530 Subject: [PATCH 14/80] Minor fix --- consensus/bor/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/consensus/bor/api.go b/consensus/bor/api.go index c6433ce092..8f172e47a6 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -91,7 +91,7 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex)) } - difficulties2 := rankMapDifficulties(difficulties) + rankedDifficulties := rankMapDifficulties(difficulties) author, err := api.GetAuthor(number) if err != nil { @@ -99,7 +99,7 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne } diff := int(difficulties[*author]) blockSigners := &BlockSigners{ - Signers: difficulties2, + Signers: rankedDifficulties, Diff: diff, Author: *author, } From 5039f4fc1ea9462bdee3cf6e6cd0c513897e9577 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Fri, 21 Jan 2022 12:51:17 +0000 Subject: [PATCH 15/80] Added bor fingerprint --- internal/cli/bor_fingerprint.go | 68 +++++++++++++++++++++++++++++++++ internal/cli/command.go | 5 +++ 2 files changed, 73 insertions(+) create mode 100644 internal/cli/bor_fingerprint.go diff --git a/internal/cli/bor_fingerprint.go b/internal/cli/bor_fingerprint.go new file mode 100644 index 0000000000..de85e53074 --- /dev/null +++ b/internal/cli/bor_fingerprint.go @@ -0,0 +1,68 @@ +package cli + +import ( + "fmt" + "math" + + "github.com/ethereum/go-ethereum/params" + "github.com/mitchellh/cli" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/disk" + "github.com/shirou/gopsutil/host" + "github.com/shirou/gopsutil/mem" +) + +// VersionCommand is the command to show the version of the agent +type FingerprintCommand struct { + UI cli.Ui +} + +// Help implements the cli.Command interface +func (c *FingerprintCommand) Help() string { + return `Usage: bor fingerprint + + Display the system fingerprint` +} + +// Synopsis implements the cli.Command interface +func (c *FingerprintCommand) Synopsis() string { + return "Display the system fingerprint" +} + +func getCoresCount(cp []cpu.InfoStat) int { + cores := 0 + for i := 0; i < len(cp); i++ { + cores += int(cp[i].Cores) + } + return cores +} + +// Run implements the cli.Command interface +func (c *FingerprintCommand) Run(args []string) int { + v, _ := mem.VirtualMemory() + h, _ := host.Info() + cp, _ := cpu.Info() + d, _ := disk.Usage("/") + + osName := h.OS + osVer := h.Platform + " - " + h.PlatformVersion + " - " + h.KernelArch + totalMem := math.Floor(float64(v.Total)/(1024*1024*1024)*100) / 100 + availableMem := math.Floor(float64(v.Available)/(1024*1024*1024)*100) / 100 + usedMem := math.Floor(float64(v.Used)/(1024*1024*1024)*100) / 100 + totalDisk := math.Floor(float64(d.Total)/(1024*1024*1024)*100) / 100 + availableDisk := math.Floor(float64(d.Free)/(1024*1024*1024)*100) / 100 + usedDisk := math.Floor(float64(d.Used)/(1024*1024*1024)*100) / 100 + + borDetails := fmt.Sprintf("Bor Version : %s", params.VersionWithMeta) + cpuDetails := fmt.Sprintf("CPU : %d cores", getCoresCount(cp)) + osDetails := fmt.Sprintf("OS : %s %s ", osName, osVer) + memDetails := fmt.Sprintf("RAM :: total : %v GB, free : %v GB, used : %v GB", totalMem, availableMem, usedMem) + diskDetails := fmt.Sprintf("STORAGE :: total : %v GB, free : %v GB, used : %v GB", totalDisk, availableDisk, usedDisk) + + c.UI.Output(borDetails) + c.UI.Output(cpuDetails) + c.UI.Output(osDetails) + c.UI.Output(memDetails) + c.UI.Output(diskDetails) + return 0 +} diff --git a/internal/cli/command.go b/internal/cli/command.go index d164791f80..131fe504c4 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -125,6 +125,11 @@ func commands() map[string]cli.CommandFactory { Meta2: meta2, }, nil }, + "fingerprint": func() (cli.Command, error) { + return &FingerprintCommand{ + UI: ui, + }, nil + }, } } From d50341053e3c468ed22e1bd76145c7fe503be68c Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Mon, 24 Jan 2022 08:24:00 +0000 Subject: [PATCH 16/80] code refactor --- internal/cli/bor_fingerprint.go | 106 ++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 25 deletions(-) diff --git a/internal/cli/bor_fingerprint.go b/internal/cli/bor_fingerprint.go index de85e53074..bb7e3de7f0 100644 --- a/internal/cli/bor_fingerprint.go +++ b/internal/cli/bor_fingerprint.go @@ -37,32 +37,88 @@ func getCoresCount(cp []cpu.InfoStat) int { return cores } +type MemoryDetails struct { + TotalMem float64 `json:"totalMem"` + FreeMem float64 `json:"freeMem"` + UsedMem float64 `json:"usedMem"` +} + +type DiskDetails struct { + TotalDisk float64 `json:"totalDisk"` + FreeDisk float64 `json:"freeDisk"` + UsedDisk float64 `json:"usedDisk"` +} + +type BorFingerprint struct { + CoresCount int `json:"coresCount"` + OsName string `json:"osName"` + OsVer string `json:"osVer"` + DiskDetails *DiskDetails `json:"diskDetails"` + MemoryDetails *MemoryDetails `json:"memoryDetails"` +} + +func formatFingerprint(borFingerprint *BorFingerprint) string { + base := formatKV([]string{ + fmt.Sprintf("Bor Version : %s", params.VersionWithMeta), + fmt.Sprintf("CPU : %d cores", borFingerprint.CoresCount), + fmt.Sprintf("OS : %s %s ", borFingerprint.OsName, borFingerprint.OsVer), + fmt.Sprintf("RAM :: total : %v GB, free : %v GB, used : %v GB", borFingerprint.MemoryDetails.TotalMem, borFingerprint.MemoryDetails.FreeMem, borFingerprint.MemoryDetails.UsedMem), + fmt.Sprintf("STORAGE :: total : %v GB, free : %v GB, used : %v GB", borFingerprint.DiskDetails.TotalDisk, borFingerprint.DiskDetails.FreeDisk, borFingerprint.DiskDetails.UsedDisk), + }) + return base +} + +func convertBytesToGB(bytesValue uint64) float64 { + return math.Floor(float64(bytesValue)/(1024*1024*1024)*100) / 100 +} + // Run implements the cli.Command interface func (c *FingerprintCommand) Run(args []string) int { - v, _ := mem.VirtualMemory() - h, _ := host.Info() - cp, _ := cpu.Info() - d, _ := disk.Usage("/") - - osName := h.OS - osVer := h.Platform + " - " + h.PlatformVersion + " - " + h.KernelArch - totalMem := math.Floor(float64(v.Total)/(1024*1024*1024)*100) / 100 - availableMem := math.Floor(float64(v.Available)/(1024*1024*1024)*100) / 100 - usedMem := math.Floor(float64(v.Used)/(1024*1024*1024)*100) / 100 - totalDisk := math.Floor(float64(d.Total)/(1024*1024*1024)*100) / 100 - availableDisk := math.Floor(float64(d.Free)/(1024*1024*1024)*100) / 100 - usedDisk := math.Floor(float64(d.Used)/(1024*1024*1024)*100) / 100 - - borDetails := fmt.Sprintf("Bor Version : %s", params.VersionWithMeta) - cpuDetails := fmt.Sprintf("CPU : %d cores", getCoresCount(cp)) - osDetails := fmt.Sprintf("OS : %s %s ", osName, osVer) - memDetails := fmt.Sprintf("RAM :: total : %v GB, free : %v GB, used : %v GB", totalMem, availableMem, usedMem) - diskDetails := fmt.Sprintf("STORAGE :: total : %v GB, free : %v GB, used : %v GB", totalDisk, availableDisk, usedDisk) - - c.UI.Output(borDetails) - c.UI.Output(cpuDetails) - c.UI.Output(osDetails) - c.UI.Output(memDetails) - c.UI.Output(diskDetails) + + v, err := mem.VirtualMemory() + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + h, err := host.Info() + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + cp, err := cpu.Info() + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + d, err := disk.Usage("/") + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + diskDetails := &DiskDetails{ + TotalDisk: convertBytesToGB(d.Total), + FreeDisk: convertBytesToGB(d.Free), + UsedDisk: convertBytesToGB(d.Used), + } + + memoryDetails := &MemoryDetails{ + TotalMem: convertBytesToGB(v.Total), + FreeMem: convertBytesToGB(v.Available), + UsedMem: convertBytesToGB(v.Used), + } + + borFingerprint := &BorFingerprint{ + CoresCount: getCoresCount(cp), + OsName: h.OS, + OsVer: h.Platform + " - " + h.PlatformVersion + " - " + h.KernelArch, + DiskDetails: diskDetails, + MemoryDetails: memoryDetails, + } + + c.UI.Output(formatFingerprint(borFingerprint)) return 0 } From be2463b95899d258c5ee0f911a8feef0693a4049 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Mon, 31 Jan 2022 13:59:03 +0000 Subject: [PATCH 17/80] read/write IOPS added --- internal/cli/bor_fingerprint.go | 67 +++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/internal/cli/bor_fingerprint.go b/internal/cli/bor_fingerprint.go index bb7e3de7f0..8e2fd8b0dd 100644 --- a/internal/cli/bor_fingerprint.go +++ b/internal/cli/bor_fingerprint.go @@ -3,6 +3,7 @@ package cli import ( "fmt" "math" + "os/exec" "github.com/ethereum/go-ethereum/params" "github.com/mitchellh/cli" @@ -72,6 +73,63 @@ func convertBytesToGB(bytesValue uint64) float64 { return math.Floor(float64(bytesValue)/(1024*1024*1024)*100) / 100 } +// Install fio on the node if it does not exist +func (c *FingerprintCommand) installFio() error { + + cmd := exec.Command("/bin/sh", "-c", "fio -v") + + _, err := cmd.CombinedOutput() + if err != nil { + c.UI.Output("fio not installed\nInstalling Fio...") + + cmd := exec.Command("/bin/sh", "-c", "sudo apt-get update && sudo apt-get install fio -y") + _, err := cmd.CombinedOutput() + if err == nil { + return nil + } + + cmd = exec.Command("/bin/sh", "-c", "sudo yum install fio -y") + _, err = cmd.CombinedOutput() + if err == nil { + return nil + } + + cmd = exec.Command("/bin/sh", "-c", "sudo dnf install fio -y") + _, err = cmd.CombinedOutput() + if err == nil { + return nil + } + + c.UI.Output("Unable to install fio") + return err + } + + return nil +} + +// Run the IOPS benchmark for the node +func (c *FingerprintCommand) benchmark() error { + var b []byte + err := c.installFio() + if err != nil { + return err + } + + c.UI.Output("\nRunning a 10 second test...\n") + + cmd := exec.Command("/bin/sh", "-c", "sudo fio --filename=/file --size=2GB --direct=1 --rw=randrw --bs=64k --ioengine=libaio --iodepth=64 --runtime=10 --numjobs=4 --time_based --group_reporting --name=throughput-test-job --eta-newline=1 | grep -e 'read:' -e 'write:' | awk '{print $1,$2}' ") + + b, err = cmd.CombinedOutput() + if err != nil { + return err + } + + out := string(b) + c.UI.Output(out) + + return nil +} + // Run implements the cli.Command interface func (c *FingerprintCommand) Run(args []string) int { @@ -120,5 +178,14 @@ func (c *FingerprintCommand) Run(args []string) int { } c.UI.Output(formatFingerprint(borFingerprint)) + + if borFingerprint.OsName == "linux" { + err = c.benchmark() + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + } + return 0 } From 55aa9af2094570c53996f7d7f421fdf6f393b2d6 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 16 Feb 2022 09:41:26 +0000 Subject: [PATCH 18/80] Removed Fio installation process --- internal/cli/bor_fingerprint.go | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/internal/cli/bor_fingerprint.go b/internal/cli/bor_fingerprint.go index 8e2fd8b0dd..5c5a8f47bd 100644 --- a/internal/cli/bor_fingerprint.go +++ b/internal/cli/bor_fingerprint.go @@ -73,34 +73,15 @@ func convertBytesToGB(bytesValue uint64) float64 { return math.Floor(float64(bytesValue)/(1024*1024*1024)*100) / 100 } -// Install fio on the node if it does not exist -func (c *FingerprintCommand) installFio() error { +// Checks if fio exists on the node +func (c *FingerprintCommand) checkFio() error { cmd := exec.Command("/bin/sh", "-c", "fio -v") _, err := cmd.CombinedOutput() if err != nil { - c.UI.Output("fio not installed\nInstalling Fio...") - - cmd := exec.Command("/bin/sh", "-c", "sudo apt-get update && sudo apt-get install fio -y") - _, err := cmd.CombinedOutput() - if err == nil { - return nil - } - - cmd = exec.Command("/bin/sh", "-c", "sudo yum install fio -y") - _, err = cmd.CombinedOutput() - if err == nil { - return nil - } - - cmd = exec.Command("/bin/sh", "-c", "sudo dnf install fio -y") - _, err = cmd.CombinedOutput() - if err == nil { - return nil - } - - c.UI.Output("Unable to install fio") + message := "\nFio package not installed. Install Fio for IOPS Benchmarking :\n\nDebianOS : 'sudo apt-get update && sudo apt-get install fio -y'\nAWS AMI/CentOS : 'sudo yum install fio -y'\nOracle LinuxOS : 'sudo dnf install fio -y'\n" + c.UI.Output(message) return err } @@ -110,9 +91,9 @@ func (c *FingerprintCommand) installFio() error { // Run the IOPS benchmark for the node func (c *FingerprintCommand) benchmark() error { var b []byte - err := c.installFio() + err := c.checkFio() if err != nil { - return err + return nil } c.UI.Output("\nRunning a 10 second test...\n") From 7f5469997af7eeb432faea1dd6b617587ff63d3d Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 16 Mar 2022 20:06:00 +0530 Subject: [PATCH 19/80] Initial Work Setup --- internal/cli/attach.go | 103 ++++++++++++++++++++++++++++++++++++++++ internal/cli/command.go | 7 +++ 2 files changed, 110 insertions(+) create mode 100644 internal/cli/attach.go diff --git a/internal/cli/attach.go b/internal/cli/attach.go new file mode 100644 index 0000000000..4bf2f628bc --- /dev/null +++ b/internal/cli/attach.go @@ -0,0 +1,103 @@ +package cli + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/ethereum/go-ethereum/rpc" + + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/console" + "github.com/ethereum/go-ethereum/node" + "github.com/mitchellh/cli" +) + +// VersionCommand is the command to show the version of the agent +type AttachCommand struct { + UI cli.Ui + Meta *Meta + Meta2 *Meta2 +} + +// Help implements the cli.Command interface +func (c *AttachCommand) Help() string { + return `Usage: bor attach + + Connect to Bor IPC console.` +} + +// Synopsis implements the cli.Command interface +func (c *AttachCommand) Synopsis() string { + return "Connect to Bor via IPC" +} + +// Run implements the cli.Command interface +func (c *AttachCommand) Run(args []string) int { + + c.remoteConsole(args) + + return 0 +} + +// remoteConsole will connect to a remote geth instance, attaching a JavaScript +// console to it. +func (c *AttachCommand) remoteConsole(args []string) error { + // Attach to a remotely running geth instance and start the JavaScript console + endpoint := args[0] + path := node.DefaultDataDir() + + if endpoint == "" { + if c.Meta.dataDir != "" { + path = c.Meta.dataDir + } + if path != "" { + homeDir, _ := os.UserHomeDir() + path = filepath.Join(homeDir, "/.bor/data") + } + endpoint = fmt.Sprintf("%s/geth.ipc", path) + } + client, err := dialRPC(endpoint) + if err != nil { + utils.Fatalf("Unable to attach to remote geth: %v", err) + } + config := console.Config{ + DataDir: path, + DocRoot: utils.JSpathFlag.Name, + Client: client, + } + + console, err := console.New(config) + if err != nil { + utils.Fatalf("Failed to start the JavaScript console: %v", err) + } + defer console.Stop(false) + + if len(args) > 1 { + if script := args[1]; script == "exec" { + console.Evaluate(args[2]) + return nil + } + } + + // Otherwise print the welcome screen and enter interactive mode + console.Welcome() + console.Interactive() + + return nil +} + +// dialRPC returns a RPC client which connects to the given endpoint. +// The check for empty endpoint implements the defaulting logic +// for "geth attach" with no argument. +func dialRPC(endpoint string) (*rpc.Client, error) { + if endpoint == "" { + endpoint = node.DefaultIPCEndpoint("bor") + } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { + // Backwards compatibility with geth < 1.5 which required + // these prefixes. + endpoint = endpoint[4:] + } + return rpc.Dial(endpoint) +} diff --git a/internal/cli/command.go b/internal/cli/command.go index 131fe504c4..9e373a65cd 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -130,6 +130,13 @@ func commands() map[string]cli.CommandFactory { UI: ui, }, nil }, + "attach": func() (cli.Command, error) { + return &AttachCommand{ + UI: ui, + Meta: meta, + Meta2: meta2, + }, nil + }, } } From 15304529f2eb64b1fe4dcb6578e507840576edb4 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Thu, 17 Mar 2022 17:44:37 +0530 Subject: [PATCH 20/80] minor fixes --- internal/cli/attach.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/cli/attach.go b/internal/cli/attach.go index 4bf2f628bc..4daaf2cf17 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -41,10 +41,15 @@ func (c *AttachCommand) Run(args []string) int { return 0 } -// remoteConsole will connect to a remote geth instance, attaching a JavaScript +// remoteConsole will connect to a remote bor instance, attaching a JavaScript // console to it. func (c *AttachCommand) remoteConsole(args []string) error { // Attach to a remotely running geth instance and start the JavaScript console + + if len(args) < 1 { + args = append(args, "") + } + endpoint := args[0] path := node.DefaultDataDir() @@ -56,7 +61,7 @@ func (c *AttachCommand) remoteConsole(args []string) error { homeDir, _ := os.UserHomeDir() path = filepath.Join(homeDir, "/.bor/data") } - endpoint = fmt.Sprintf("%s/geth.ipc", path) + endpoint = fmt.Sprintf("%s/bor.ipc", path) } client, err := dialRPC(endpoint) if err != nil { From 065556d21a2d0122151db11b0cacf9ff9faad5e5 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Thu, 17 Mar 2022 17:58:46 +0530 Subject: [PATCH 21/80] Minor Fixes --- internal/cli/attach.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/attach.go b/internal/cli/attach.go index 4daaf2cf17..75c88d002f 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -80,7 +80,7 @@ func (c *AttachCommand) remoteConsole(args []string) error { defer console.Stop(false) if len(args) > 1 { - if script := args[1]; script == "exec" { + if script := args[1]; script == "--exec" { console.Evaluate(args[2]) return nil } From 0736fdef5264b1c92a0dfd71142931c713d541f7 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Tue, 22 Mar 2022 16:17:45 +0530 Subject: [PATCH 22/80] Added console + attach refactor --- internal/cli/attach.go | 102 ++++-- internal/cli/command.go | 5 + internal/cli/server/command_flags.go | 504 +++++++++++++++++++++++++++ internal/cli/server/console.go | 163 +++++++++ 4 files changed, 752 insertions(+), 22 deletions(-) create mode 100644 internal/cli/server/command_flags.go create mode 100644 internal/cli/server/console.go diff --git a/internal/cli/attach.go b/internal/cli/attach.go index 75c88d002f..b48bc5518b 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strings" + "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/cmd/utils" @@ -14,18 +15,22 @@ import ( "github.com/mitchellh/cli" ) -// VersionCommand is the command to show the version of the agent +// AttachCommand is the command to Connect to remote Bor IPC console type AttachCommand struct { - UI cli.Ui - Meta *Meta - Meta2 *Meta2 + UI cli.Ui + Meta *Meta + Meta2 *Meta2 + ExecCMD string + Endpoint string + PreloadJSFlag string + JSpathFlag string } // Help implements the cli.Command interface func (c *AttachCommand) Help() string { return `Usage: bor attach - Connect to Bor IPC console.` + Connect to remote Bor IPC console.` } // Synopsis implements the cli.Command interface @@ -33,27 +38,65 @@ func (c *AttachCommand) Synopsis() string { return "Connect to Bor via IPC" } +func (c *AttachCommand) Flags() *flagset.Flagset { + + f := flagset.NewFlagSet("attach") + + f.StringFlag(&flagset.StringFlag{ + Name: "exec", + Usage: "Command to run in remote console", + Value: &c.ExecCMD, + }) + + f.StringFlag(&flagset.StringFlag{ + Name: "preload", + Usage: "Comma separated list of JavaScript files to preload into the console", + Value: &c.PreloadJSFlag, + }) + + f.StringFlag(&flagset.StringFlag{ + Name: "jspath", + Usage: "JavaScript root path for `loadScript`", + Value: &c.JSpathFlag, + }) + + return f +} + // Run implements the cli.Command interface func (c *AttachCommand) Run(args []string) int { - c.remoteConsole(args) + flags := c.Flags() + + //check if first arg is flag or IPC location + if len(args) == 0 { + args = append(args, "") + } + if args[0] != "" && string(args[0][0:2]) == "--" { + if err := flags.Parse(args); err != nil { + c.UI.Error(err.Error()) + return 1 + } + } else { + c.Endpoint = args[0] + if err := flags.Parse(args[1:]); err != nil { + c.UI.Error(err.Error()) + return 1 + } + } + c.remoteConsole() return 0 } // remoteConsole will connect to a remote bor instance, attaching a JavaScript // console to it. -func (c *AttachCommand) remoteConsole(args []string) error { +func (c *AttachCommand) remoteConsole() error { // Attach to a remotely running geth instance and start the JavaScript console - if len(args) < 1 { - args = append(args, "") - } - - endpoint := args[0] path := node.DefaultDataDir() - if endpoint == "" { + if c.Endpoint == "" { if c.Meta.dataDir != "" { path = c.Meta.dataDir } @@ -61,16 +104,17 @@ func (c *AttachCommand) remoteConsole(args []string) error { homeDir, _ := os.UserHomeDir() path = filepath.Join(homeDir, "/.bor/data") } - endpoint = fmt.Sprintf("%s/bor.ipc", path) + c.Endpoint = fmt.Sprintf("%s/bor.ipc", path) } - client, err := dialRPC(endpoint) + client, err := dialRPC(c.Endpoint) if err != nil { - utils.Fatalf("Unable to attach to remote geth: %v", err) + utils.Fatalf("Unable to attach to remote bor: %v", err) } config := console.Config{ DataDir: path, - DocRoot: utils.JSpathFlag.Name, + DocRoot: c.JSpathFlag, Client: client, + Preload: c.MakeConsolePreloads(), } console, err := console.New(config) @@ -79,11 +123,9 @@ func (c *AttachCommand) remoteConsole(args []string) error { } defer console.Stop(false) - if len(args) > 1 { - if script := args[1]; script == "--exec" { - console.Evaluate(args[2]) - return nil - } + if c.ExecCMD != "" { + console.Evaluate(c.ExecCMD) + return nil } // Otherwise print the welcome screen and enter interactive mode @@ -106,3 +148,19 @@ func dialRPC(endpoint string) (*rpc.Client, error) { } return rpc.Dial(endpoint) } + +// MakeConsolePreloads retrieves the absolute paths for the console JavaScript +// scripts to preload before starting. +func (c *AttachCommand) MakeConsolePreloads() []string { + // Skip preloading if there's nothing to preload + if c.PreloadJSFlag == "" { + return nil + } + // Otherwise resolve absolute paths and return them + var preloads []string + + for _, file := range strings.Split(c.PreloadJSFlag, ",") { + preloads = append(preloads, strings.TrimSpace(file)) + } + return preloads +} diff --git a/internal/cli/command.go b/internal/cli/command.go index 9e373a65cd..baa09368b6 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -137,6 +137,11 @@ func commands() map[string]cli.CommandFactory { Meta2: meta2, }, nil }, + "console": func() (cli.Command, error) { + return &server.ConsoleCommand{ + UI: ui, + }, nil + }, } } diff --git a/internal/cli/server/command_flags.go b/internal/cli/server/command_flags.go new file mode 100644 index 0000000000..f43535a459 --- /dev/null +++ b/internal/cli/server/command_flags.go @@ -0,0 +1,504 @@ +package server + +import ( + "github.com/ethereum/go-ethereum/internal/cli/flagset" +) + +func (c *ConsoleCommand) Flags() *flagset.Flagset { + c.cliConfig = DefaultConfig() + + f := flagset.NewFlagSet("console") + + // console flags + f.StringFlag(&flagset.StringFlag{ + Name: "exec", + Usage: "Command to run in remote console", + Value: &c.ExecCMD, + }) + + f.StringFlag(&flagset.StringFlag{ + Name: "preload", + Usage: "Comma separated list of JavaScript files to preload into the console", + Value: &c.PreloadJSFlag, + }) + + f.StringFlag(&flagset.StringFlag{ + Name: "jspath", + Usage: "JavaScript root path for `loadScript`", + Value: &c.JSpathFlag, + }) + + // server flags + f.StringFlag(&flagset.StringFlag{ + Name: "chain", + Usage: "Name of the chain to sync", + Value: &c.cliConfig.Chain, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "name", + Usage: "Name/Identity of the node", + Value: &c.cliConfig.Name, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "log-level", + Usage: "Set log level for the server", + Value: &c.cliConfig.LogLevel, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "datadir", + Usage: "Path of the data directory to store information", + Value: &c.cliConfig.DataDir, + }) + f.SliceStringFlag(&flagset.SliceStringFlag{ + Name: "config", + Usage: "File for the config file", + Value: &c.configFile, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "syncmode", + Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`, + Value: &c.cliConfig.SyncMode, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "gcmode", + Usage: `Blockchain garbage collection mode ("full", "archive")`, + Value: &c.cliConfig.GcMode, + }) + f.MapStringFlag(&flagset.MapStringFlag{ + Name: "whitelist", + Usage: "Comma separated block number-to-hash mappings to enforce (=)", + Value: &c.cliConfig.Whitelist, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "snapshot", + Usage: `Enables snapshot-database mode (default = enable)`, + Value: &c.cliConfig.Snapshot, + }) + + // heimdall + f.StringFlag(&flagset.StringFlag{ + Name: "bor.heimdall", + Usage: "URL of Heimdall service", + Value: &c.cliConfig.Heimdall.URL, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "bor.withoutheimdall", + Usage: "Run without Heimdall service (for testing purpose)", + Value: &c.cliConfig.Heimdall.Without, + }) + + // txpool options + f.SliceStringFlag(&flagset.SliceStringFlag{ + Name: "txpool.locals", + Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", + Value: &c.cliConfig.TxPool.Locals, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "txpool.nolocals", + Usage: "Disables price exemptions for locally submitted transactions", + Value: &c.cliConfig.TxPool.NoLocals, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "txpool.journal", + Usage: "Disk journal for local transaction to survive node restarts", + Value: &c.cliConfig.TxPool.Journal, + }) + f.DurationFlag(&flagset.DurationFlag{ + Name: "txpool.rejournal", + Usage: "Time interval to regenerate the local transaction journal", + Value: &c.cliConfig.TxPool.Rejournal, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "txpool.pricelimit", + Usage: "Minimum gas price limit to enforce for acceptance into the pool", + Value: &c.cliConfig.TxPool.PriceLimit, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "txpool.pricebump", + Usage: "Price bump percentage to replace an already existing transaction", + Value: &c.cliConfig.TxPool.PriceBump, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "txpool.accountslots", + Usage: "Minimum number of executable transaction slots guaranteed per account", + Value: &c.cliConfig.TxPool.AccountSlots, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "txpool.globalslots", + Usage: "Maximum number of executable transaction slots for all accounts", + Value: &c.cliConfig.TxPool.GlobalSlots, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "txpool.accountqueue", + Usage: "Maximum number of non-executable transaction slots permitted per account", + Value: &c.cliConfig.TxPool.AccountQueue, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "txpool.globalqueue", + Usage: "Maximum number of non-executable transaction slots for all accounts", + Value: &c.cliConfig.TxPool.GlobalQueue, + }) + f.DurationFlag(&flagset.DurationFlag{ + Name: "txpool.lifetime", + Usage: "Maximum amount of time non-executable transaction are queued", + Value: &c.cliConfig.TxPool.LifeTime, + }) + + // sealer options + f.BoolFlag(&flagset.BoolFlag{ + Name: "mine", + Usage: "Enable mining", + Value: &c.cliConfig.Sealer.Enabled, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "miner.etherbase", + Usage: "Public address for block mining rewards (default = first account)", + Value: &c.cliConfig.Sealer.Etherbase, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "miner.extradata", + Usage: "Block extra data set by the miner (default = client version)", + Value: &c.cliConfig.Sealer.ExtraData, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "miner.gaslimit", + Usage: "Target gas ceiling for mined blocks", + Value: &c.cliConfig.Sealer.GasCeil, + }) + f.BigIntFlag(&flagset.BigIntFlag{ + Name: "miner.gasprice", + Usage: "Minimum gas price for mining a transaction", + Value: c.cliConfig.Sealer.GasPrice, + }) + + // ethstats + f.StringFlag(&flagset.StringFlag{ + Name: "ethstats", + Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", + Value: &c.cliConfig.Ethstats, + }) + + // gas price oracle + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "gpo.blocks", + Usage: "Number of recent blocks to check for gas prices", + Value: &c.cliConfig.Gpo.Blocks, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "gpo.percentile", + Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", + Value: &c.cliConfig.Gpo.Percentile, + }) + f.BigIntFlag(&flagset.BigIntFlag{ + Name: "gpo.maxprice", + Usage: "Maximum gas price will be recommended by gpo", + Value: c.cliConfig.Gpo.MaxPrice, + }) + f.BigIntFlag(&flagset.BigIntFlag{ + Name: "gpo.ignoreprice", + Usage: "Gas price below which gpo will ignore transactions", + Value: c.cliConfig.Gpo.IgnorePrice, + }) + + // cache options + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "cache", + Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)", + Value: &c.cliConfig.Cache.Cache, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "cache.database", + Usage: "Percentage of cache memory allowance to use for database io", + Value: &c.cliConfig.Cache.PercDatabase, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "cache.trie", + Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", + Value: &c.cliConfig.Cache.PercTrie, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "cache.trie.journal", + Usage: "Disk journal directory for trie cache to survive node restarts", + Value: &c.cliConfig.Cache.Journal, + }) + f.DurationFlag(&flagset.DurationFlag{ + Name: "cache.trie.rejournal", + Usage: "Time interval to regenerate the trie cache journal", + Value: &c.cliConfig.Cache.Rejournal, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "cache.gc", + Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", + Value: &c.cliConfig.Cache.PercGc, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "cache.snapshot", + Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", + Value: &c.cliConfig.Cache.PercSnapshot, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "cache.noprefetch", + Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", + Value: &c.cliConfig.Cache.NoPrefetch, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "cache.preimages", + Usage: "Enable recording the SHA3/keccak preimages of trie keys", + Value: &c.cliConfig.Cache.Preimages, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "txlookuplimit", + Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)", + Value: &c.cliConfig.Cache.TxLookupLimit, + }) + + // rpc options + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "rpc.gascap", + Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", + Value: &c.cliConfig.JsonRPC.GasCap, + }) + f.Float64Flag(&flagset.Float64Flag{ + Name: "rpc.txfeecap", + Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", + Value: &c.cliConfig.JsonRPC.TxFeeCap, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "ipcdisable", + Usage: "Disable the IPC-RPC server", + Value: &c.cliConfig.JsonRPC.IPCDisable, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "ipcpath", + Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", + Value: &c.cliConfig.JsonRPC.IPCPath, + }) + f.SliceStringFlag(&flagset.SliceStringFlag{ + Name: "jsonrpc.corsdomain", + Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", + Value: &c.cliConfig.JsonRPC.Cors, + }) + f.SliceStringFlag(&flagset.SliceStringFlag{ + Name: "jsonrpc.vhosts", + Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", + Value: &c.cliConfig.JsonRPC.VHost, + }) + + // http options + f.BoolFlag(&flagset.BoolFlag{ + Name: "http", + Usage: "Enable the HTTP-RPC server", + Value: &c.cliConfig.JsonRPC.Http.Enabled, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "http.addr", + Usage: "HTTP-RPC server listening interface", + Value: &c.cliConfig.JsonRPC.Http.Host, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "http.port", + Usage: "HTTP-RPC server listening port", + Value: &c.cliConfig.JsonRPC.Http.Port, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "http.rpcprefix", + Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", + Value: &c.cliConfig.JsonRPC.Http.Prefix, + }) + f.SliceStringFlag(&flagset.SliceStringFlag{ + Name: "http.modules", + Usage: "API's offered over the HTTP-RPC interface", + Value: &c.cliConfig.JsonRPC.Http.Modules, + }) + + // ws options + f.BoolFlag(&flagset.BoolFlag{ + Name: "ws", + Usage: "Enable the WS-RPC server", + Value: &c.cliConfig.JsonRPC.Ws.Enabled, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "ws.addr", + Usage: "WS-RPC server listening interface", + Value: &c.cliConfig.JsonRPC.Ws.Host, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "ws.port", + Usage: "WS-RPC server listening port", + Value: &c.cliConfig.JsonRPC.Ws.Port, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "ws.rpcprefix", + Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", + Value: &c.cliConfig.JsonRPC.Ws.Prefix, + }) + f.SliceStringFlag(&flagset.SliceStringFlag{ + Name: "ws.modules", + Usage: "API's offered over the WS-RPC interface", + Value: &c.cliConfig.JsonRPC.Ws.Modules, + }) + + // graphql options + f.BoolFlag(&flagset.BoolFlag{ + Name: "graphql", + Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.", + Value: &c.cliConfig.JsonRPC.Graphql.Enabled, + }) + + // p2p options + f.StringFlag(&flagset.StringFlag{ + Name: "bind", + Usage: "Network binding address", + Value: &c.cliConfig.P2P.Bind, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "port", + Usage: "Network listening port", + Value: &c.cliConfig.P2P.Port, + }) + f.SliceStringFlag(&flagset.SliceStringFlag{ + Name: "bootnodes", + Usage: "Comma separated enode URLs for P2P discovery bootstrap", + Value: &c.cliConfig.P2P.Discovery.Bootnodes, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "maxpeers", + Usage: "Maximum number of network peers (network disabled if set to 0)", + Value: &c.cliConfig.P2P.MaxPeers, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "maxpendpeers", + Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", + Value: &c.cliConfig.P2P.MaxPendPeers, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "nat", + Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", + Value: &c.cliConfig.P2P.NAT, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "nodiscover", + Usage: "Disables the peer discovery mechanism (manual peer addition)", + Value: &c.cliConfig.P2P.NoDiscover, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "v5disc", + Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", + Value: &c.cliConfig.P2P.Discovery.V5Enabled, + }) + + // metrics + f.BoolFlag(&flagset.BoolFlag{ + Name: "metrics", + Usage: "Enable metrics collection and reporting", + Value: &c.cliConfig.Telemetry.Enabled, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "metrics.expensive", + Usage: "Enable expensive metrics collection and reporting", + Value: &c.cliConfig.Telemetry.Expensive, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "metrics.influxdb", + Usage: "Enable metrics export/push to an external InfluxDB database (v1)", + Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.influxdb.endpoint", + Usage: "InfluxDB API endpoint to report metrics to", + Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.influxdb.database", + Usage: "InfluxDB database name to push reported metrics to", + Value: &c.cliConfig.Telemetry.InfluxDB.Database, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.influxdb.username", + Usage: "Username to authorize access to the database", + Value: &c.cliConfig.Telemetry.InfluxDB.Username, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.influxdb.password", + Usage: "Password to authorize access to the database", + Value: &c.cliConfig.Telemetry.InfluxDB.Password, + }) + f.MapStringFlag(&flagset.MapStringFlag{ + Name: "metrics.influxdb.tags", + Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", + Value: &c.cliConfig.Telemetry.InfluxDB.Tags, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.prometheus-addr", + Usage: "Address for Prometheus Server", + Value: &c.cliConfig.Telemetry.PrometheusAddr, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.opencollector-endpoint", + Usage: "OpenCollector Endpoint (host:port)", + Value: &c.cliConfig.Telemetry.OpenCollectorEndpoint, + }) + // influx db v2 + f.BoolFlag(&flagset.BoolFlag{ + Name: "metrics.influxdbv2", + Usage: "Enable metrics export/push to an external InfluxDB v2 database", + Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.influxdb.token", + Usage: "Token to authorize access to the database (v2 only)", + Value: &c.cliConfig.Telemetry.InfluxDB.Token, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.influxdb.bucket", + Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", + Value: &c.cliConfig.Telemetry.InfluxDB.Bucket, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "metrics.influxdb.organization", + Usage: "InfluxDB organization name (v2 only)", + Value: &c.cliConfig.Telemetry.InfluxDB.Organization, + }) + + // account + f.SliceStringFlag(&flagset.SliceStringFlag{ + Name: "unlock", + Usage: "Comma separated list of accounts to unlock", + Value: &c.cliConfig.Accounts.Unlock, + }) + f.StringFlag(&flagset.StringFlag{ + Name: "password", + Usage: "Password file to use for non-interactive password input", + Value: &c.cliConfig.Accounts.PasswordFile, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "allow-insecure-unlock", + Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", + Value: &c.cliConfig.Accounts.AllowInsecureUnlock, + }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "lightkdf", + Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", + Value: &c.cliConfig.Accounts.UseLightweightKDF, + }) + + // grpc + f.StringFlag(&flagset.StringFlag{ + Name: "grpc.addr", + Usage: "Address and port to bind the GRPC server", + Value: &c.cliConfig.GRPC.Addr, + }) + + // developer + f.BoolFlag(&flagset.BoolFlag{ + Name: "dev", + Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled", + Value: &c.cliConfig.Developer.Enabled, + }) + f.Uint64Flag(&flagset.Uint64Flag{ + Name: "dev.period", + Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", + Value: &c.cliConfig.Developer.Period, + }) + return f +} diff --git a/internal/cli/server/console.go b/internal/cli/server/console.go new file mode 100644 index 0000000000..05b333111c --- /dev/null +++ b/internal/cli/server/console.go @@ -0,0 +1,163 @@ +package server + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/console" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" + "github.com/mitchellh/cli" +) + +// ConsoleCommand is the command to Connect to remote Bor IPC console +type ConsoleCommand struct { + // cli configuration + cliConfig *Config + + // final configuration + config *Config + + configFile []string + UI cli.Ui + ExecCMD string + Endpoint string + PreloadJSFlag string + JSpathFlag string + srv *Server +} + +// Help implements the cli.Command interface +func (c *ConsoleCommand) Help() string { + return `Usage: bor console + + Connect to local Bor IPC console.` +} + +// Synopsis implements the cli.Command interface +func (c *ConsoleCommand) Synopsis() string { + return "Connect to Bor console" +} + +// Run implements the cli.Command interface +func (c *ConsoleCommand) Run(args []string) int { + flags := c.Flags() + if err := flags.Parse(args); err != nil { + c.UI.Error(err.Error()) + return 1 + } + + // read config file + config := DefaultConfig() + for _, configFile := range c.configFile { + cfg, err := readConfigFile(configFile) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + if err := config.Merge(cfg); err != nil { + c.UI.Error(err.Error()) + return 1 + } + } + if err := config.Merge(c.cliConfig); err != nil { + c.UI.Error(err.Error()) + return 1 + } + c.config = config + + srv, err := NewServer(config) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + c.srv = srv + + c.localConsole() + + return 0 +} + +// localConsole starts a new geth node, attaching a JavaScript console to it at the +// same time. +func (c *ConsoleCommand) localConsole() error { + // Create and start the node based on the CLI flags + stack := c.srv.node + stack.Start() + defer stack.Close() + + path := node.DefaultDataDir() + + if c.Endpoint == "" { + if c.config.DataDir != "" { + path = c.config.DataDir + } + if path != "" { + homeDir, _ := os.UserHomeDir() + path = filepath.Join(homeDir, "/.bor/data") + } + c.Endpoint = fmt.Sprintf("%s/bor.ipc", path) + } + + // Attach to the newly started node and start the JavaScript console + client, err := stack.Attach() + if err != nil { + utils.Fatalf("Failed to attach to the inproc geth: %v", err) + } + config := console.Config{ + DataDir: path, + DocRoot: c.JSpathFlag, + Client: client, + Preload: c.MakeConsolePreloads(), + } + + console, err := console.New(config) + if err != nil { + utils.Fatalf("Failed to start the JavaScript console: %v", err) + } + defer console.Stop(false) + + // If only a short execution was requested, evaluate and return + if script := c.ExecCMD; script != "" { + console.Evaluate(script) + return nil + } + // Otherwise print the welcome screen and enter interactive mode + console.Welcome() + console.Interactive() + + return nil +} + +// dialRPC returns a RPC client which connects to the given endpoint. +// The check for empty endpoint implements the defaulting logic +// for "geth attach" with no argument. +func dialRPC(endpoint string) (*rpc.Client, error) { + if endpoint == "" { + endpoint = node.DefaultIPCEndpoint("bor") + } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { + // Backwards compatibility with geth < 1.5 which required + // these prefixes. + endpoint = endpoint[4:] + } + return rpc.Dial(endpoint) +} + +// MakeConsolePreloads retrieves the absolute paths for the console JavaScript +// scripts to preload before starting. +func (c *ConsoleCommand) MakeConsolePreloads() []string { + // Skip preloading if there's nothing to preload + if c.PreloadJSFlag == "" { + return nil + } + // Otherwise resolve absolute paths and return them + var preloads []string + + for _, file := range strings.Split(c.PreloadJSFlag, ",") { + preloads = append(preloads, strings.TrimSpace(file)) + } + return preloads +} From 00e51a99c0fe552e7d3e202e74915a17e2e91c4e Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 23 Mar 2022 16:49:56 +0530 Subject: [PATCH 23/80] Removed console command --- internal/cli/attach.go | 4 +- internal/cli/command.go | 5 - internal/cli/server/command_flags.go | 504 --------------------------- internal/cli/server/console.go | 163 --------- 4 files changed, 2 insertions(+), 674 deletions(-) delete mode 100644 internal/cli/server/command_flags.go delete mode 100644 internal/cli/server/console.go diff --git a/internal/cli/attach.go b/internal/cli/attach.go index b48bc5518b..e6454a1b22 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -114,7 +114,7 @@ func (c *AttachCommand) remoteConsole() error { DataDir: path, DocRoot: c.JSpathFlag, Client: client, - Preload: c.MakeConsolePreloads(), + Preload: c.makeConsolePreloads(), } console, err := console.New(config) @@ -151,7 +151,7 @@ func dialRPC(endpoint string) (*rpc.Client, error) { // MakeConsolePreloads retrieves the absolute paths for the console JavaScript // scripts to preload before starting. -func (c *AttachCommand) MakeConsolePreloads() []string { +func (c *AttachCommand) makeConsolePreloads() []string { // Skip preloading if there's nothing to preload if c.PreloadJSFlag == "" { return nil diff --git a/internal/cli/command.go b/internal/cli/command.go index baa09368b6..9e373a65cd 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -137,11 +137,6 @@ func commands() map[string]cli.CommandFactory { Meta2: meta2, }, nil }, - "console": func() (cli.Command, error) { - return &server.ConsoleCommand{ - UI: ui, - }, nil - }, } } diff --git a/internal/cli/server/command_flags.go b/internal/cli/server/command_flags.go deleted file mode 100644 index f43535a459..0000000000 --- a/internal/cli/server/command_flags.go +++ /dev/null @@ -1,504 +0,0 @@ -package server - -import ( - "github.com/ethereum/go-ethereum/internal/cli/flagset" -) - -func (c *ConsoleCommand) Flags() *flagset.Flagset { - c.cliConfig = DefaultConfig() - - f := flagset.NewFlagSet("console") - - // console flags - f.StringFlag(&flagset.StringFlag{ - Name: "exec", - Usage: "Command to run in remote console", - Value: &c.ExecCMD, - }) - - f.StringFlag(&flagset.StringFlag{ - Name: "preload", - Usage: "Comma separated list of JavaScript files to preload into the console", - Value: &c.PreloadJSFlag, - }) - - f.StringFlag(&flagset.StringFlag{ - Name: "jspath", - Usage: "JavaScript root path for `loadScript`", - Value: &c.JSpathFlag, - }) - - // server flags - f.StringFlag(&flagset.StringFlag{ - Name: "chain", - Usage: "Name of the chain to sync", - Value: &c.cliConfig.Chain, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "name", - Usage: "Name/Identity of the node", - Value: &c.cliConfig.Name, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "log-level", - Usage: "Set log level for the server", - Value: &c.cliConfig.LogLevel, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "datadir", - Usage: "Path of the data directory to store information", - Value: &c.cliConfig.DataDir, - }) - f.SliceStringFlag(&flagset.SliceStringFlag{ - Name: "config", - Usage: "File for the config file", - Value: &c.configFile, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "syncmode", - Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`, - Value: &c.cliConfig.SyncMode, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "gcmode", - Usage: `Blockchain garbage collection mode ("full", "archive")`, - Value: &c.cliConfig.GcMode, - }) - f.MapStringFlag(&flagset.MapStringFlag{ - Name: "whitelist", - Usage: "Comma separated block number-to-hash mappings to enforce (=)", - Value: &c.cliConfig.Whitelist, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "snapshot", - Usage: `Enables snapshot-database mode (default = enable)`, - Value: &c.cliConfig.Snapshot, - }) - - // heimdall - f.StringFlag(&flagset.StringFlag{ - Name: "bor.heimdall", - Usage: "URL of Heimdall service", - Value: &c.cliConfig.Heimdall.URL, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "bor.withoutheimdall", - Usage: "Run without Heimdall service (for testing purpose)", - Value: &c.cliConfig.Heimdall.Without, - }) - - // txpool options - f.SliceStringFlag(&flagset.SliceStringFlag{ - Name: "txpool.locals", - Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", - Value: &c.cliConfig.TxPool.Locals, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "txpool.nolocals", - Usage: "Disables price exemptions for locally submitted transactions", - Value: &c.cliConfig.TxPool.NoLocals, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "txpool.journal", - Usage: "Disk journal for local transaction to survive node restarts", - Value: &c.cliConfig.TxPool.Journal, - }) - f.DurationFlag(&flagset.DurationFlag{ - Name: "txpool.rejournal", - Usage: "Time interval to regenerate the local transaction journal", - Value: &c.cliConfig.TxPool.Rejournal, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.pricelimit", - Usage: "Minimum gas price limit to enforce for acceptance into the pool", - Value: &c.cliConfig.TxPool.PriceLimit, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.pricebump", - Usage: "Price bump percentage to replace an already existing transaction", - Value: &c.cliConfig.TxPool.PriceBump, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.accountslots", - Usage: "Minimum number of executable transaction slots guaranteed per account", - Value: &c.cliConfig.TxPool.AccountSlots, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.globalslots", - Usage: "Maximum number of executable transaction slots for all accounts", - Value: &c.cliConfig.TxPool.GlobalSlots, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.accountqueue", - Usage: "Maximum number of non-executable transaction slots permitted per account", - Value: &c.cliConfig.TxPool.AccountQueue, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.globalqueue", - Usage: "Maximum number of non-executable transaction slots for all accounts", - Value: &c.cliConfig.TxPool.GlobalQueue, - }) - f.DurationFlag(&flagset.DurationFlag{ - Name: "txpool.lifetime", - Usage: "Maximum amount of time non-executable transaction are queued", - Value: &c.cliConfig.TxPool.LifeTime, - }) - - // sealer options - f.BoolFlag(&flagset.BoolFlag{ - Name: "mine", - Usage: "Enable mining", - Value: &c.cliConfig.Sealer.Enabled, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "miner.etherbase", - Usage: "Public address for block mining rewards (default = first account)", - Value: &c.cliConfig.Sealer.Etherbase, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "miner.extradata", - Usage: "Block extra data set by the miner (default = client version)", - Value: &c.cliConfig.Sealer.ExtraData, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "miner.gaslimit", - Usage: "Target gas ceiling for mined blocks", - Value: &c.cliConfig.Sealer.GasCeil, - }) - f.BigIntFlag(&flagset.BigIntFlag{ - Name: "miner.gasprice", - Usage: "Minimum gas price for mining a transaction", - Value: c.cliConfig.Sealer.GasPrice, - }) - - // ethstats - f.StringFlag(&flagset.StringFlag{ - Name: "ethstats", - Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", - Value: &c.cliConfig.Ethstats, - }) - - // gas price oracle - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "gpo.blocks", - Usage: "Number of recent blocks to check for gas prices", - Value: &c.cliConfig.Gpo.Blocks, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "gpo.percentile", - Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", - Value: &c.cliConfig.Gpo.Percentile, - }) - f.BigIntFlag(&flagset.BigIntFlag{ - Name: "gpo.maxprice", - Usage: "Maximum gas price will be recommended by gpo", - Value: c.cliConfig.Gpo.MaxPrice, - }) - f.BigIntFlag(&flagset.BigIntFlag{ - Name: "gpo.ignoreprice", - Usage: "Gas price below which gpo will ignore transactions", - Value: c.cliConfig.Gpo.IgnorePrice, - }) - - // cache options - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache", - Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)", - Value: &c.cliConfig.Cache.Cache, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache.database", - Usage: "Percentage of cache memory allowance to use for database io", - Value: &c.cliConfig.Cache.PercDatabase, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache.trie", - Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", - Value: &c.cliConfig.Cache.PercTrie, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "cache.trie.journal", - Usage: "Disk journal directory for trie cache to survive node restarts", - Value: &c.cliConfig.Cache.Journal, - }) - f.DurationFlag(&flagset.DurationFlag{ - Name: "cache.trie.rejournal", - Usage: "Time interval to regenerate the trie cache journal", - Value: &c.cliConfig.Cache.Rejournal, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache.gc", - Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", - Value: &c.cliConfig.Cache.PercGc, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache.snapshot", - Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", - Value: &c.cliConfig.Cache.PercSnapshot, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "cache.noprefetch", - Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", - Value: &c.cliConfig.Cache.NoPrefetch, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "cache.preimages", - Usage: "Enable recording the SHA3/keccak preimages of trie keys", - Value: &c.cliConfig.Cache.Preimages, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txlookuplimit", - Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)", - Value: &c.cliConfig.Cache.TxLookupLimit, - }) - - // rpc options - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "rpc.gascap", - Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", - Value: &c.cliConfig.JsonRPC.GasCap, - }) - f.Float64Flag(&flagset.Float64Flag{ - Name: "rpc.txfeecap", - Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", - Value: &c.cliConfig.JsonRPC.TxFeeCap, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "ipcdisable", - Usage: "Disable the IPC-RPC server", - Value: &c.cliConfig.JsonRPC.IPCDisable, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "ipcpath", - Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", - Value: &c.cliConfig.JsonRPC.IPCPath, - }) - f.SliceStringFlag(&flagset.SliceStringFlag{ - Name: "jsonrpc.corsdomain", - Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", - Value: &c.cliConfig.JsonRPC.Cors, - }) - f.SliceStringFlag(&flagset.SliceStringFlag{ - Name: "jsonrpc.vhosts", - Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", - Value: &c.cliConfig.JsonRPC.VHost, - }) - - // http options - f.BoolFlag(&flagset.BoolFlag{ - Name: "http", - Usage: "Enable the HTTP-RPC server", - Value: &c.cliConfig.JsonRPC.Http.Enabled, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "http.addr", - Usage: "HTTP-RPC server listening interface", - Value: &c.cliConfig.JsonRPC.Http.Host, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "http.port", - Usage: "HTTP-RPC server listening port", - Value: &c.cliConfig.JsonRPC.Http.Port, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "http.rpcprefix", - Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", - Value: &c.cliConfig.JsonRPC.Http.Prefix, - }) - f.SliceStringFlag(&flagset.SliceStringFlag{ - Name: "http.modules", - Usage: "API's offered over the HTTP-RPC interface", - Value: &c.cliConfig.JsonRPC.Http.Modules, - }) - - // ws options - f.BoolFlag(&flagset.BoolFlag{ - Name: "ws", - Usage: "Enable the WS-RPC server", - Value: &c.cliConfig.JsonRPC.Ws.Enabled, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "ws.addr", - Usage: "WS-RPC server listening interface", - Value: &c.cliConfig.JsonRPC.Ws.Host, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "ws.port", - Usage: "WS-RPC server listening port", - Value: &c.cliConfig.JsonRPC.Ws.Port, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "ws.rpcprefix", - Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", - Value: &c.cliConfig.JsonRPC.Ws.Prefix, - }) - f.SliceStringFlag(&flagset.SliceStringFlag{ - Name: "ws.modules", - Usage: "API's offered over the WS-RPC interface", - Value: &c.cliConfig.JsonRPC.Ws.Modules, - }) - - // graphql options - f.BoolFlag(&flagset.BoolFlag{ - Name: "graphql", - Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.", - Value: &c.cliConfig.JsonRPC.Graphql.Enabled, - }) - - // p2p options - f.StringFlag(&flagset.StringFlag{ - Name: "bind", - Usage: "Network binding address", - Value: &c.cliConfig.P2P.Bind, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "port", - Usage: "Network listening port", - Value: &c.cliConfig.P2P.Port, - }) - f.SliceStringFlag(&flagset.SliceStringFlag{ - Name: "bootnodes", - Usage: "Comma separated enode URLs for P2P discovery bootstrap", - Value: &c.cliConfig.P2P.Discovery.Bootnodes, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "maxpeers", - Usage: "Maximum number of network peers (network disabled if set to 0)", - Value: &c.cliConfig.P2P.MaxPeers, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "maxpendpeers", - Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", - Value: &c.cliConfig.P2P.MaxPendPeers, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "nat", - Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", - Value: &c.cliConfig.P2P.NAT, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "nodiscover", - Usage: "Disables the peer discovery mechanism (manual peer addition)", - Value: &c.cliConfig.P2P.NoDiscover, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "v5disc", - Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", - Value: &c.cliConfig.P2P.Discovery.V5Enabled, - }) - - // metrics - f.BoolFlag(&flagset.BoolFlag{ - Name: "metrics", - Usage: "Enable metrics collection and reporting", - Value: &c.cliConfig.Telemetry.Enabled, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "metrics.expensive", - Usage: "Enable expensive metrics collection and reporting", - Value: &c.cliConfig.Telemetry.Expensive, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "metrics.influxdb", - Usage: "Enable metrics export/push to an external InfluxDB database (v1)", - Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.endpoint", - Usage: "InfluxDB API endpoint to report metrics to", - Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.database", - Usage: "InfluxDB database name to push reported metrics to", - Value: &c.cliConfig.Telemetry.InfluxDB.Database, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.username", - Usage: "Username to authorize access to the database", - Value: &c.cliConfig.Telemetry.InfluxDB.Username, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.password", - Usage: "Password to authorize access to the database", - Value: &c.cliConfig.Telemetry.InfluxDB.Password, - }) - f.MapStringFlag(&flagset.MapStringFlag{ - Name: "metrics.influxdb.tags", - Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", - Value: &c.cliConfig.Telemetry.InfluxDB.Tags, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.prometheus-addr", - Usage: "Address for Prometheus Server", - Value: &c.cliConfig.Telemetry.PrometheusAddr, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.opencollector-endpoint", - Usage: "OpenCollector Endpoint (host:port)", - Value: &c.cliConfig.Telemetry.OpenCollectorEndpoint, - }) - // influx db v2 - f.BoolFlag(&flagset.BoolFlag{ - Name: "metrics.influxdbv2", - Usage: "Enable metrics export/push to an external InfluxDB v2 database", - Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.token", - Usage: "Token to authorize access to the database (v2 only)", - Value: &c.cliConfig.Telemetry.InfluxDB.Token, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.bucket", - Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", - Value: &c.cliConfig.Telemetry.InfluxDB.Bucket, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.organization", - Usage: "InfluxDB organization name (v2 only)", - Value: &c.cliConfig.Telemetry.InfluxDB.Organization, - }) - - // account - f.SliceStringFlag(&flagset.SliceStringFlag{ - Name: "unlock", - Usage: "Comma separated list of accounts to unlock", - Value: &c.cliConfig.Accounts.Unlock, - }) - f.StringFlag(&flagset.StringFlag{ - Name: "password", - Usage: "Password file to use for non-interactive password input", - Value: &c.cliConfig.Accounts.PasswordFile, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "allow-insecure-unlock", - Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", - Value: &c.cliConfig.Accounts.AllowInsecureUnlock, - }) - f.BoolFlag(&flagset.BoolFlag{ - Name: "lightkdf", - Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", - Value: &c.cliConfig.Accounts.UseLightweightKDF, - }) - - // grpc - f.StringFlag(&flagset.StringFlag{ - Name: "grpc.addr", - Usage: "Address and port to bind the GRPC server", - Value: &c.cliConfig.GRPC.Addr, - }) - - // developer - f.BoolFlag(&flagset.BoolFlag{ - Name: "dev", - Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled", - Value: &c.cliConfig.Developer.Enabled, - }) - f.Uint64Flag(&flagset.Uint64Flag{ - Name: "dev.period", - Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", - Value: &c.cliConfig.Developer.Period, - }) - return f -} diff --git a/internal/cli/server/console.go b/internal/cli/server/console.go deleted file mode 100644 index 05b333111c..0000000000 --- a/internal/cli/server/console.go +++ /dev/null @@ -1,163 +0,0 @@ -package server - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/console" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/rpc" - "github.com/mitchellh/cli" -) - -// ConsoleCommand is the command to Connect to remote Bor IPC console -type ConsoleCommand struct { - // cli configuration - cliConfig *Config - - // final configuration - config *Config - - configFile []string - UI cli.Ui - ExecCMD string - Endpoint string - PreloadJSFlag string - JSpathFlag string - srv *Server -} - -// Help implements the cli.Command interface -func (c *ConsoleCommand) Help() string { - return `Usage: bor console - - Connect to local Bor IPC console.` -} - -// Synopsis implements the cli.Command interface -func (c *ConsoleCommand) Synopsis() string { - return "Connect to Bor console" -} - -// Run implements the cli.Command interface -func (c *ConsoleCommand) Run(args []string) int { - flags := c.Flags() - if err := flags.Parse(args); err != nil { - c.UI.Error(err.Error()) - return 1 - } - - // read config file - config := DefaultConfig() - for _, configFile := range c.configFile { - cfg, err := readConfigFile(configFile) - if err != nil { - c.UI.Error(err.Error()) - return 1 - } - if err := config.Merge(cfg); err != nil { - c.UI.Error(err.Error()) - return 1 - } - } - if err := config.Merge(c.cliConfig); err != nil { - c.UI.Error(err.Error()) - return 1 - } - c.config = config - - srv, err := NewServer(config) - if err != nil { - c.UI.Error(err.Error()) - return 1 - } - c.srv = srv - - c.localConsole() - - return 0 -} - -// localConsole starts a new geth node, attaching a JavaScript console to it at the -// same time. -func (c *ConsoleCommand) localConsole() error { - // Create and start the node based on the CLI flags - stack := c.srv.node - stack.Start() - defer stack.Close() - - path := node.DefaultDataDir() - - if c.Endpoint == "" { - if c.config.DataDir != "" { - path = c.config.DataDir - } - if path != "" { - homeDir, _ := os.UserHomeDir() - path = filepath.Join(homeDir, "/.bor/data") - } - c.Endpoint = fmt.Sprintf("%s/bor.ipc", path) - } - - // Attach to the newly started node and start the JavaScript console - client, err := stack.Attach() - if err != nil { - utils.Fatalf("Failed to attach to the inproc geth: %v", err) - } - config := console.Config{ - DataDir: path, - DocRoot: c.JSpathFlag, - Client: client, - Preload: c.MakeConsolePreloads(), - } - - console, err := console.New(config) - if err != nil { - utils.Fatalf("Failed to start the JavaScript console: %v", err) - } - defer console.Stop(false) - - // If only a short execution was requested, evaluate and return - if script := c.ExecCMD; script != "" { - console.Evaluate(script) - return nil - } - // Otherwise print the welcome screen and enter interactive mode - console.Welcome() - console.Interactive() - - return nil -} - -// dialRPC returns a RPC client which connects to the given endpoint. -// The check for empty endpoint implements the defaulting logic -// for "geth attach" with no argument. -func dialRPC(endpoint string) (*rpc.Client, error) { - if endpoint == "" { - endpoint = node.DefaultIPCEndpoint("bor") - } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { - // Backwards compatibility with geth < 1.5 which required - // these prefixes. - endpoint = endpoint[4:] - } - return rpc.Dial(endpoint) -} - -// MakeConsolePreloads retrieves the absolute paths for the console JavaScript -// scripts to preload before starting. -func (c *ConsoleCommand) MakeConsolePreloads() []string { - // Skip preloading if there's nothing to preload - if c.PreloadJSFlag == "" { - return nil - } - // Otherwise resolve absolute paths and return them - var preloads []string - - for _, file := range strings.Split(c.PreloadJSFlag, ",") { - preloads = append(preloads, strings.TrimSpace(file)) - } - return preloads -} From 388b68cd05addf9ebddcc300546f3e0ec12ecb64 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 20 Apr 2022 17:22:55 +0530 Subject: [PATCH 24/80] Minor Fixes --- internal/cli/attach.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/cli/attach.go b/internal/cli/attach.go index e6454a1b22..eec8a28ed3 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -72,7 +72,7 @@ func (c *AttachCommand) Run(args []string) int { if len(args) == 0 { args = append(args, "") } - if args[0] != "" && string(args[0][0:2]) == "--" { + if args[0] != "" && strings.HasPrefix(args[0], "--") { if err := flags.Parse(args); err != nil { c.UI.Error(err.Error()) return 1 @@ -84,7 +84,10 @@ func (c *AttachCommand) Run(args []string) int { return 1 } } - c.remoteConsole() + if err := c.remoteConsole(); err != nil { + c.UI.Error(err.Error()) + return 1 + } return 0 } From 597037df3021c124556135a8bdfdcd308d919de4 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 26 Apr 2022 13:50:53 +0530 Subject: [PATCH 25/80] Update default cli config (#323) * update the default cli config * fix: handle maxpeers flag override, added tests * add: no-snapshot flag, handle snapshot disable * fix: update default flags * add: update the sealer.GasPrice default to 30 gewi * fix: remove snapshot flag, rely on no-snapshot only --- internal/cli/server/config.go | 35 +++++++++++++++++++----------- internal/cli/server/config_test.go | 30 +++++++++++++++++++++---- internal/cli/server/flags.go | 6 ++--- 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 29cb8ffa21..a5e255ad48 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -58,8 +58,8 @@ type Config struct { // GcMode selects the garbage collection mode for the trie GcMode string `hcl:"gc-mode,optional"` - // XXX - Snapshot bool `hcl:"snapshot,optional"` + // NoSnapshot disbales the snapshot database mode + NoSnapshot bool `hcl:"no-snapshot,optional"` // Ethstats is the address of the ethstats server to send telemetry Ethstats string `hcl:"ethstats,optional"` @@ -406,27 +406,27 @@ func DefaultConfig() *Config { URL: "http://localhost:1317", Without: false, }, - SyncMode: "full", - GcMode: "full", - Snapshot: true, + SyncMode: "full", + GcMode: "full", + NoSnapshot: false, TxPool: &TxPoolConfig{ Locals: []string{}, NoLocals: false, Journal: "", Rejournal: time.Duration(1 * time.Hour), - PriceLimit: 1, + PriceLimit: 30000000000, PriceBump: 10, AccountSlots: 16, - GlobalSlots: 4096, - AccountQueue: 64, - GlobalQueue: 1024, + GlobalSlots: 32768, + AccountQueue: 16, + GlobalQueue: 32768, LifeTime: time.Duration(3 * time.Hour), }, Sealer: &SealerConfig{ Enabled: false, Etherbase: "", GasCeil: 8000000, - GasPrice: big.NewInt(params.GWei), + GasPrice: big.NewInt(30 * params.GWei), ExtraData: "", }, Gpo: &GpoConfig{ @@ -443,11 +443,11 @@ func DefaultConfig() *Config { GasCap: ethconfig.Defaults.RPCGasCap, TxFeeCap: ethconfig.Defaults.RPCTxFeeCap, Http: &APIConfig{ - Enabled: true, + Enabled: false, Port: 8545, Prefix: "", Host: "localhost", - Modules: []string{"eth", "web3", "net"}, + Modules: []string{"eth", "net", "web3", "txpool", "bor"}, }, Ws: &APIConfig{ Enabled: false, @@ -805,7 +805,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) { } // snapshot disable check - if c.Snapshot { + if c.NoSnapshot { if n.SyncMode == downloader.SnapSync { log.Info("Snap sync requested, enabling --snapshot") } else { @@ -867,6 +867,10 @@ func (c *Config) buildNode() (*node.Config, error) { cfg.P2P.ListenAddr = "" cfg.P2P.NoDial = true cfg.P2P.DiscoveryV5 = false + + // enable JsonRPC HTTP API + c.JsonRPC.Http.Enabled = true + cfg.HTTPModules = []string{"admin", "debug", "eth", "miner", "net", "personal", "txpool", "web3", "bor"} } // enable jsonrpc endpoints @@ -922,6 +926,11 @@ func (c *Config) Merge(cc ...*Config) error { if err := mergo.Merge(c, elem, mergo.WithOverride, mergo.WithAppendSlice); err != nil { return fmt.Errorf("failed to merge configurations: %v", err) } + + // override max peers + if elem.P2P.MaxPeers == 0 { + c.P2P.MaxPeers = 0 + } } return nil } diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go index 62296d82a4..6f5f9ff97d 100644 --- a/internal/cli/server/config_test.go +++ b/internal/cli/server/config_test.go @@ -22,8 +22,8 @@ func TestConfigDefault(t *testing.T) { func TestConfigMerge(t *testing.T) { c0 := &Config{ - Chain: "0", - Snapshot: true, + Chain: "0", + NoSnapshot: true, Whitelist: map[string]string{ "a": "b", }, @@ -53,8 +53,8 @@ func TestConfigMerge(t *testing.T) { }, } expected := &Config{ - Chain: "1", - Snapshot: true, + Chain: "1", + NoSnapshot: true, Whitelist: map[string]string{ "a": "b", "b": "c", @@ -76,6 +76,28 @@ func TestConfigMerge(t *testing.T) { assert.Equal(t, c0, expected) } +func TestDefaultDatatypeOverride(t *testing.T) { + // This test is specific to `maxpeers` flag (for now) to check + // if default datatype value (0 in case of uint64) is overridden. + c0 := &Config{ + P2P: &P2PConfig{ + MaxPeers: 30, + }, + } + c1 := &Config{ + P2P: &P2PConfig{ + MaxPeers: 0, + }, + } + expected := &Config{ + P2P: &P2PConfig{ + MaxPeers: 0, + }, + } + assert.NoError(t, c0.Merge(c1)) + assert.Equal(t, c0, expected) +} + func TestConfigLoadFile(t *testing.T) { readFile := func(path string) { config, err := readConfigFile(path) diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index b8f6003420..edc7276a8b 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -50,9 +50,9 @@ func (c *Command) Flags() *flagset.Flagset { Value: &c.cliConfig.Whitelist, }) f.BoolFlag(&flagset.BoolFlag{ - Name: "snapshot", - Usage: `Enables snapshot-database mode (default = enable)`, - Value: &c.cliConfig.Snapshot, + Name: "no-snapshot", + Usage: `Disables the snapshot-database mode (default = false)`, + Value: &c.cliConfig.NoSnapshot, }) // heimdall From a131e427f64bd56839c432ac93fb64dd3d471087 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 22 Apr 2022 11:44:35 -0700 Subject: [PATCH 26/80] Automatically generate markdown pages from bor CLI Adding a script that can automatically generate markdown pages from bor CLI, so we can avoid copy-pasting helper strings whenever a flag is created, deleted, or modified. CLI docs could be generated with command `make docs`. --- Makefile | 9 +- cmd/clidoc/main.go | 71 ++++++++++++ docs/cli/README.md | 25 ++-- docs/cli/account.md | 3 +- docs/cli/account_import.md | 7 +- docs/cli/account_list.md | 9 +- docs/cli/account_new.md | 9 +- docs/cli/attach.md | 11 ++ docs/cli/chain.md | 3 +- docs/cli/chain_sethead.md | 5 +- docs/cli/chain_watch.md | 2 +- docs/cli/debug.md | 13 ++- docs/cli/fingerprint.md | 3 + docs/cli/peers.md | 3 +- docs/cli/peers_add.md | 7 +- docs/cli/peers_list.md | 7 +- docs/cli/peers_remove.md | 7 +- docs/cli/peers_status.md | 5 +- docs/cli/server.md | 195 ++++++++++++++++---------------- docs/cli/status.md | 3 +- docs/cli/version.md | 3 +- internal/cli/account.go | 18 ++- internal/cli/account_import.go | 11 ++ internal/cli/account_list.go | 11 ++ internal/cli/account_new.go | 11 ++ internal/cli/attach.go | 10 ++ internal/cli/bor_fingerprint.go | 10 ++ internal/cli/chain.go | 13 +++ internal/cli/chain_sethead.go | 13 +++ internal/cli/chain_watch.go | 10 ++ internal/cli/command.go | 60 ++++++---- internal/cli/debug.go | 27 +++++ internal/cli/flagset/flagset.go | 54 +++++++++ internal/cli/markdown.go | 14 +++ internal/cli/markdown_test.go | 19 ++++ internal/cli/peers.go | 15 +++ internal/cli/peers_add.go | 11 ++ internal/cli/peers_list.go | 10 ++ internal/cli/peers_remove.go | 11 ++ internal/cli/peers_status.go | 10 ++ internal/cli/server/command.go | 11 ++ internal/cli/server/flags.go | 71 +++++++++++- internal/cli/status.go | 9 ++ internal/cli/version.go | 20 ++++ 44 files changed, 686 insertions(+), 163 deletions(-) create mode 100644 cmd/clidoc/main.go create mode 100644 docs/cli/attach.md create mode 100644 docs/cli/fingerprint.md create mode 100644 internal/cli/markdown.go create mode 100644 internal/cli/markdown_test.go diff --git a/Makefile b/Makefile index 678af31c46..9ee575aab4 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,11 @@ # with Go source code. If you know what GOPATH is then you probably # don't need to bother with make. -.PHONY: geth android ios evm all test clean +.PHONY: geth android ios geth-cross evm all test clean docs +.PHONY: geth-linux geth-linux-386 geth-linux-amd64 geth-linux-mips64 geth-linux-mips64le +.PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64 +.PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64 +.PHONY: geth-windows geth-windows-386 geth-windows-amd64 GOBIN = ./build/bin GO ?= latest @@ -43,6 +47,9 @@ test: lint: ## Run linters. $(GORUN) build/ci.go lint +docs: + $(GORUN) cmd/clidoc/main.go -d ./docs/cli + clean: env GO111MODULE=on go clean -cache rm -fr build/_workspace/pkg/ $(GOBIN)/* diff --git a/cmd/clidoc/main.go b/cmd/clidoc/main.go new file mode 100644 index 0000000000..70ad35501b --- /dev/null +++ b/cmd/clidoc/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "flag" + "log" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/ethereum/go-ethereum/internal/cli" +) + +const ( + DefaultDir string = "./docs/cli" + DefaultMainPage string = "README.md" +) + +func main() { + + commands := cli.Commands() + + dest := flag.String("d", DefaultDir, "Destination directory where the docs will be generated") + flag.Parse() + + dirPath := filepath.Join(".", *dest) + if err := os.MkdirAll(dirPath, os.ModePerm); err != nil { + log.Fatalln("Failed to create directory.", err) + } + + mainPage := []string{ + "# Bor command line interface", + "## Commands", + } + + keys := make([]string, len(commands)) + i := 0 + for k := range commands { + keys[i] = k + i++ + } + sort.Strings(keys) + + for _, name := range keys { + cmd, err := commands[name]() + if err != nil { + log.Fatalf("Error occurred when inspecting bor command %s: %s", name, err) + } + + fileName := strings.ReplaceAll(name, " ", "_") + ".md" + + overwriteFile(filepath.Join(dirPath, fileName), cmd.MarkDown()) + mainPage = append(mainPage, "- [```"+name+"```](./"+fileName+")") + } + + overwriteFile(filepath.Join(dirPath, DefaultMainPage), strings.Join(mainPage, "\n\n")) + + os.Exit(0) +} + +func overwriteFile(filePath string, text string) { + log.Printf("Writing to page: %s\n", filePath) + f, err := os.Create(filePath) + if err != nil { + log.Fatalln(err) + } + f.WriteString(text) + if err := f.Close(); err != nil { + log.Fatalln(err) + } +} diff --git a/docs/cli/README.md b/docs/cli/README.md index ed8a3f5977..c10c8bf9c2 100644 --- a/docs/cli/README.md +++ b/docs/cli/README.md @@ -1,24 +1,27 @@ - -# Command line interface +# Bor command line interface ## Commands -- [```server```](./server.md) - -- [```debug```](./debug.md) - - [```account```](./account.md) -- [```account new```](./account_new.md) +- [```account import```](./account_import.md) - [```account list```](./account_list.md) -- [```account import```](./account_import.md) +- [```account new```](./account_new.md) + +- [```attach```](./attach.md) - [```chain```](./chain.md) - [```chain sethead```](./chain_sethead.md) +- [```chain watch```](./chain_watch.md) + +- [```debug```](./debug.md) + +- [```fingerprint```](./fingerprint.md) + - [```peers```](./peers.md) - [```peers add```](./peers_add.md) @@ -29,8 +32,8 @@ - [```peers status```](./peers_status.md) -- [```status```](./status.md) +- [```server```](./server.md) -- [```chain watch```](./chain_watch.md) +- [```status```](./status.md) -- [```version```](./version.md) +- [```version```](./version.md) \ No newline at end of file diff --git a/docs/cli/account.md b/docs/cli/account.md index 00fd6cbe65..b3659952f6 100644 --- a/docs/cli/account.md +++ b/docs/cli/account.md @@ -1,4 +1,3 @@ - # Account The ```account``` command groups actions to interact with accounts: @@ -7,4 +6,4 @@ The ```account``` command groups actions to interact with accounts: - [```account list```](./account_list.md): List the wallets in the Bor client. -- [```account import```](./account_import.md): Import an account to the Bor client. +- [```account import```](./account_import.md): Import an account to the Bor client. \ No newline at end of file diff --git a/docs/cli/account_import.md b/docs/cli/account_import.md index 2a515866cf..d7b02195bc 100644 --- a/docs/cli/account_import.md +++ b/docs/cli/account_import.md @@ -1,4 +1,9 @@ - # Account import The ```account import``` command imports an account in Json format to the Bor data directory. + +## Options + +- ```datadir```: Path of the data directory to store information + +- ```keystore```: Path of the data directory to store information \ No newline at end of file diff --git a/docs/cli/account_list.md b/docs/cli/account_list.md index 4a2d28de92..61ebf9e776 100644 --- a/docs/cli/account_list.md +++ b/docs/cli/account_list.md @@ -1,4 +1,9 @@ - # Account list -The ```account list``` command lists all the accounts in the Bor data directory. +The `account list` command lists all the accounts in the Bor data directory. + +## Options + +- ```datadir```: Path of the data directory to store information + +- ```keystore```: Path of the data directory to store information \ No newline at end of file diff --git a/docs/cli/account_new.md b/docs/cli/account_new.md index 41e53767a1..dd62061ba0 100644 --- a/docs/cli/account_new.md +++ b/docs/cli/account_new.md @@ -1,4 +1,9 @@ - # Account new -The ```account new``` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command. +The `account new` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command. + +## Options + +- ```datadir```: Path of the data directory to store information + +- ```keystore```: Path of the data directory to store information \ No newline at end of file diff --git a/docs/cli/attach.md b/docs/cli/attach.md new file mode 100644 index 0000000000..6e323b8d18 --- /dev/null +++ b/docs/cli/attach.md @@ -0,0 +1,11 @@ +# Attach + +Connect to remote Bor IPC console. + +## Options + +- ```exec```: Command to run in remote console + +- ```preload```: Comma separated list of JavaScript files to preload into the console + +- ```jspath```: JavaScript root path for `loadScript` \ No newline at end of file diff --git a/docs/cli/chain.md b/docs/cli/chain.md index e55a90f122..8412588e37 100644 --- a/docs/cli/chain.md +++ b/docs/cli/chain.md @@ -1,6 +1,7 @@ - # Chain The ```chain``` command groups actions to interact with the blockchain in the client: - [```chain sethead```](./chain_sethead.md): Set the current chain to a certain block. + +- [```chain watch```](./chain_watch.md): Watch the chainHead, reorg and fork events in real-time. \ No newline at end of file diff --git a/docs/cli/chain_sethead.md b/docs/cli/chain_sethead.md index 985383988f..bf97990e62 100644 --- a/docs/cli/chain_sethead.md +++ b/docs/cli/chain_sethead.md @@ -1,4 +1,3 @@ - # Chain sethead The ```chain sethead ``` command sets the current chain to a certain block. @@ -9,4 +8,6 @@ The ```chain sethead ``` command sets the current chain to a certain blo ## Options -- ```yes```: Force set head. +- ```address```: Address of the grpc endpoint + +- ```yes```: Force set head \ No newline at end of file diff --git a/docs/cli/chain_watch.md b/docs/cli/chain_watch.md index 4844bb7618..252ac02531 100644 --- a/docs/cli/chain_watch.md +++ b/docs/cli/chain_watch.md @@ -1,3 +1,3 @@ # Chain watch -The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time. +The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time. \ No newline at end of file diff --git a/docs/cli/debug.md b/docs/cli/debug.md index c75ae79e49..eecc6c6ef0 100644 --- a/docs/cli/debug.md +++ b/docs/cli/debug.md @@ -1,13 +1,14 @@ - # Debug The ```bor debug``` command takes a debug dump of the running client. ## Options -- ```seconds```: Number of seconds to trace cpu and traces. +- ```address```: Address of the grpc endpoint + +- ```seconds```: seconds to trace -- ```output```: Output directory for the data dump. +- ```output```: Output directory ## Examples @@ -15,8 +16,8 @@ By default it creates a tar.gz file with the output: ``` $ bor debug -Starting debugger... - +Starting debugger... + Created debug archive: bor-debug-2021-10-26-073819Z.tar.gz ``` @@ -27,4 +28,4 @@ $ bor debug --output data Starting debugger... Created debug directory: data/bor-debug-2021-10-26-075437Z -``` +``` \ No newline at end of file diff --git a/docs/cli/fingerprint.md b/docs/cli/fingerprint.md new file mode 100644 index 0000000000..8bb7cb1542 --- /dev/null +++ b/docs/cli/fingerprint.md @@ -0,0 +1,3 @@ +# Fingerprint + +Display the system fingerprint \ No newline at end of file diff --git a/docs/cli/peers.md b/docs/cli/peers.md index 57b4889a00..ac6dfd676e 100644 --- a/docs/cli/peers.md +++ b/docs/cli/peers.md @@ -1,4 +1,3 @@ - # Peers The ```peers``` command groups actions to interact with peers: @@ -9,4 +8,4 @@ The ```peers``` command groups actions to interact with peers: - [```peers remove```](./peers_remove.md): Disconnects the local client from a connected peer if exists. -- [```peers status```](./peers_status.md): Display the status of a peer by its id. +- [```peers status```](./peers_status.md): Display the status of a peer by its id. \ No newline at end of file diff --git a/docs/cli/peers_add.md b/docs/cli/peers_add.md index 35e5ece450..5bc4ed1448 100644 --- a/docs/cli/peers_add.md +++ b/docs/cli/peers_add.md @@ -1,8 +1,9 @@ - # Peers add The ```peers add ``` command joins the local client to another remote peer. -## Arguments +## Options + +- ```address```: Address of the grpc endpoint -- ```trusted```: Whether the peer is added as a trusted peer. +- ```trusted```: Add the peer as a trusted \ No newline at end of file diff --git a/docs/cli/peers_list.md b/docs/cli/peers_list.md index cb1ef2f599..41f398b764 100644 --- a/docs/cli/peers_list.md +++ b/docs/cli/peers_list.md @@ -1,4 +1,7 @@ - -# Peers list +# Peers add The ```peers list``` command lists the connected peers. + +## Options + +- ```address```: Address of the grpc endpoint \ No newline at end of file diff --git a/docs/cli/peers_remove.md b/docs/cli/peers_remove.md index e2fa0a71df..2cac1e7656 100644 --- a/docs/cli/peers_remove.md +++ b/docs/cli/peers_remove.md @@ -1,4 +1,9 @@ - # Peers remove The ```peers remove ``` command disconnects the local client from a connected peer if exists. + +## Options + +- ```address```: Address of the grpc endpoint + +- ```trusted```: Add the peer as a trusted \ No newline at end of file diff --git a/docs/cli/peers_status.md b/docs/cli/peers_status.md index 56343c8d6b..65a0fe9d8f 100644 --- a/docs/cli/peers_status.md +++ b/docs/cli/peers_status.md @@ -1,4 +1,7 @@ - # Peers status The ```peers status ``` command displays the status of a peer by its id. + +## Options + +- ```address```: Address of the grpc endpoint \ No newline at end of file diff --git a/docs/cli/server.md b/docs/cli/server.md index 5a3e7e1052..ba6f3389c5 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -1,133 +1,112 @@ - # Server The ```bor server``` command runs the Bor client. -## General Options - -- ```chain```: Name of the chain to sync (mainnet or mumbai). - -- ```log-level```: Set log level for the server (info, warn, debug, trace). - -- ```datadir```: Path of the data directory to store information (defaults to $HOME). +## Options -- ```config```: List of files that contain the configuration. +- ```chain```: Name of the chain to sync -- ```syncmode```: Blockchain sync mode ("fast", "full", "snap" or "light"). +- ```name```: Name/Identity of the node -- ```gcmode```: Blockchain garbage collection mode ("full", "archive"). +- ```log-level```: Set log level for the server -- ```whitelist```: Comma separated block number-to-hash mappings to enforce (=). +- ```datadir```: Path of the data directory to store information -- ```snapshot```: Enables snapshot-database mode (default = enable). +- ```config```: File for the config file -- ```bor.heimdall```: URL of Heimdall service. +- ```syncmode```: Blockchain sync mode ("fast", "full", or "snap") -- ```bor.withoutheimdall```: Run without Heimdall service (for testing purpose). +- ```gcmode```: Blockchain garbage collection mode ("full", "archive") -- ```ethstats```: Reporting URL of a ethstats service (nodename:secret@host:port). +- ```whitelist```: Comma separated block number-to-hash mappings to enforce (=) -- ```gpo.blocks```: Number of recent blocks to check for gas prices. +- ```no-snapshot```: Disables the snapshot-database mode (default = false) -- ```gpo.percentile```: Suggested gas price is the given percentile of a set of recent transaction gas prices. +- ```bor.heimdall```: URL of Heimdall service -- ```gpo.maxprice```: Maximum gas price will be recommended by gpo. +- ```bor.withoutheimdall```: Run without Heimdall service (for testing purpose) -- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions. - -- ```grpc.addr```: Address and port to bind the GRPC server. - -### Transaction Pool Options +- ```ethstats```: Reporting URL of a ethstats service (nodename:secret@host:port) -- ```txpool.locals```: Comma separated accounts to treat as locals (no flush, priority inclusion). +- ```gpo.blocks```: Number of recent blocks to check for gas prices -- ```txpool.nolocals```: Disables price exemptions for locally submitted transactions +- ```gpo.percentile```: Suggested gas price is the given percentile of a set of recent transaction gas prices -- ```txpool.journal```: Disk journal for local transaction to survive node restarts +- ```gpo.maxprice```: Maximum gas price will be recommended by gpo -- ```txpool.rejournal```: Time interval to regenerate the local transaction journal +- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions -- ```txpool.pricelimit```: Minimum gas price limit to enforce for acceptance into the pool +- ```grpc.addr```: Address and port to bind the GRPC server -- ```txpool.pricebump```: Price bump percentage to replace an already existing transaction +- ```dev```: Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled -- ```txpool.accountslots```: Minimum number of executable transaction slots guaranteed per account +- ```dev.period```: Block period to use in developer mode (0 = mine only if transaction pending) -- ```txpool.globalslots```: Maximum number of executable transaction slots for all accounts - -- ```txpool.accountqueue```: Maximum number of non-executable transaction slots permitted per account - -- ```txpool.globalqueue```: Maximum number of non-executable transaction slots for all accounts - -- ```txpool.lifetime```: Maximum amount of time non-executable transaction are queued - -### Sealer Options - -- ```mine```: Enable sealing. +### Account Management Options -- ```miner.etherbase```: Public address for block mining rewards (default = first account) +- ```unlock```: Comma separated list of accounts to unlock -- ```miner.extradata```: Block extra data set by the miner (default = client version). +- ```password```: Password file to use for non-interactive password input -- ```miner.gaslimit```: Target gas ceiling for mined blocks. +- ```allow-insecure-unlock```: Allow insecure account unlocking when account-related RPCs are exposed by http -- ```miner.gasprice```: Minimum gas price for mining a transaction. +- ```lightkdf```: Reduce key-derivation RAM & CPU usage at some expense of KDF strength ### Cache Options -- ```cache```: Megabytes of memory allocated to internal caching (default = 4096 mainnet full node). +- ```cache```: Megabytes of memory allocated to internal caching (default = 4096 mainnet full node) -- ```cache.database```: Percentage of cache memory allowance to use for database io. +- ```cache.database```: Percentage of cache memory allowance to use for database io -- ```cache.trie```: Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode). +- ```cache.trie```: Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode) -- ```cache.trie.journal```: Disk journal directory for trie cache to survive node restarts. +- ```cache.trie.journal```: Disk journal directory for trie cache to survive node restarts -- ```cache.trie.rejournal```: Time interval to regenerate the trie cache journal. +- ```cache.trie.rejournal```: Time interval to regenerate the trie cache journal -- ```cache.gc```: Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode). +- ```cache.gc```: Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode) -- ```cache.snapshot```: Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode). +- ```cache.snapshot```: Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode) -- ```cache.noprefetch```: Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data). +- ```cache.noprefetch```: Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data) -- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys. +- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys -- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain). +- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain) ### JsonRPC Options -- ```rpc.gascap```: Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite). +- ```rpc.gascap```: Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite) -- ```rpc.txfeecap```: Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap). +- ```rpc.txfeecap```: Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap) -- ```ipcdisable```: Disable the IPC-RPC server. +- ```ipcdisable```: Disable the IPC-RPC server -- ```ipcpath```: Filename for IPC socket/pipe within the datadir (explicit paths escape it). +- ```ipcpath```: Filename for IPC socket/pipe within the datadir (explicit paths escape it) -- ```jsonrpc.corsdomain```: Comma separated list of domains from which to accept cross. +- ```jsonrpc.corsdomain```: Comma separated list of domains from which to accept cross origin requests (browser enforced) - ```jsonrpc.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard. -- ```http```: Enable the HTTP-RPC server. +- ```http```: Enable the HTTP-RPC server + +- ```http.addr```: HTTP-RPC server listening interface + +- ```http.port```: HTTP-RPC server listening port -- ```http.addr```: HTTP-RPC server listening interface. - -- ```http.port```: HTTP-RPC server listening port. - - ```http.rpcprefix```: HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths. -- ```http.modules```: API's offered over the HTTP-RPC interface. +- ```http.modules```: API's offered over the HTTP-RPC interface -- ```ws```: Enable the WS-RPC server. +- ```ws```: Enable the WS-RPC server -- ```ws.addr```: WS-RPC server listening interface. +- ```ws.addr```: WS-RPC server listening interface -- ```ws.port```: WS-RPC server listening port. +- ```ws.port```: WS-RPC server listening port - ```ws.rpcprefix```: HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths. -- ```ws.modules```: API's offered over the WS-RPC interface. +- ```ws.modules```: API's offered over the WS-RPC interface - ```graphql```: Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well. @@ -139,56 +118,78 @@ The ```bor server``` command runs the Bor client. - ```bootnodes```: Comma separated enode URLs for P2P discovery bootstrap -- ```maxpeers```: "Maximum number of network peers (network disabled if set to 0) +- ```maxpeers```: Maximum number of network peers (network disabled if set to 0) - ```maxpendpeers```: Maximum number of pending connection attempts (defaults used if set to 0) -- ```nat```: "NAT port mapping mechanism (any|none|upnp|pmp|extip:) +- ```nat```: NAT port mapping mechanism (any|none|upnp|pmp|extip:) -- ```nodiscover```: "Disables the peer discovery mechanism (manual peer addition) +- ```nodiscover```: Disables the peer discovery mechanism (manual peer addition) -- ```v5disc```: "Enables the experimental RLPx V5 (Topic Discovery) mechanism +- ```v5disc```: Enables the experimental RLPx V5 (Topic Discovery) mechanism + +### Sealer Options + +- ```mine```: Enable mining + +- ```miner.etherbase```: Public address for block mining rewards (default = first account) + +- ```miner.extradata```: Block extra data set by the miner (default = client version) + +- ```miner.gaslimit```: Target gas ceiling for mined blocks + +- ```miner.gasprice```: Minimum gas price for mining a transaction ### Telemetry Options -- ```metrics```: Enable metrics collection and reporting. +- ```metrics```: Enable metrics collection and reporting -- ```metrics.expensive```: Enable expensive metrics collection and reporting. +- ```metrics.expensive```: Enable expensive metrics collection and reporting -- ```metrics.influxdb```: Enable metrics export/push to an external InfluxDB database (v1). +- ```metrics.influxdb```: Enable metrics export/push to an external InfluxDB database (v1) -- ```metrics.influxdb.endpoint```: InfluxDB API endpoint to report metrics to. +- ```metrics.influxdb.endpoint```: InfluxDB API endpoint to report metrics to -- ```metrics.influxdb.database```: InfluxDB database name to push reported metrics to. +- ```metrics.influxdb.database```: InfluxDB database name to push reported metrics to -- ```metrics.influxdb.username```: Username to authorize access to the database. +- ```metrics.influxdb.username```: Username to authorize access to the database -- ```metrics.influxdb.password```: Password to authorize access to the database. +- ```metrics.influxdb.password```: Password to authorize access to the database -- ```metrics.influxdb.tags```: Comma-separated InfluxDB tags (key/values) attached to all measurements. +- ```metrics.influxdb.tags```: Comma-separated InfluxDB tags (key/values) attached to all measurements -- ```metrics.influxdbv2```: Enable metrics export/push to an external InfluxDB v2 database. +- ```metrics.prometheus-addr```: Address for Prometheus Server -- ```metrics.influxdb.token```: Token to authorize access to the database (v2 only). +- ```metrics.opencollector-endpoint```: OpenCollector Endpoint (host:port) -- ```metrics.influxdb.bucket```: InfluxDB bucket name to push reported metrics to (v2 only). +- ```metrics.influxdbv2```: Enable metrics export/push to an external InfluxDB v2 database -- ```metrics.influxdb.organization```: InfluxDB organization name (v2 only). +- ```metrics.influxdb.token```: Token to authorize access to the database (v2 only) -### Account Management Options +- ```metrics.influxdb.bucket```: InfluxDB bucket name to push reported metrics to (v2 only) + +- ```metrics.influxdb.organization```: InfluxDB organization name (v2 only) + +### Transaction Pool Options + +- ```txpool.locals```: Comma separated accounts to treat as locals (no flush, priority inclusion) -- ```unlock```: "Comma separated list of accounts to unlock. +- ```txpool.nolocals```: Disables price exemptions for locally submitted transactions -- ```password```: Password file to use for non-interactive password input. +- ```txpool.journal```: Disk journal for local transaction to survive node restarts -- ```allow-insecure-unlock```: Allow insecure account unlocking when account-related RPCs are exposed by http. +- ```txpool.rejournal```: Time interval to regenerate the local transaction journal -- ```lightkdf```: Reduce key-derivation RAM & CPU usage at some expense of KDF strength. +- ```txpool.pricelimit```: Minimum gas price limit to enforce for acceptance into the pool -## Usage +- ```txpool.pricebump```: Price bump percentage to replace an already existing transaction -Use multiple files to configure the client: +- ```txpool.accountslots```: Minimum number of executable transaction slots guaranteed per account -``` -$ bor server --config ./legacy-config.toml --config ./config2.hcl -``` +- ```txpool.globalslots```: Maximum number of executable transaction slots for all accounts + +- ```txpool.accountqueue```: Maximum number of non-executable transaction slots permitted per account + +- ```txpool.globalqueue```: Maximum number of non-executable transaction slots for all accounts + +- ```txpool.lifetime```: Maximum amount of time non-executable transaction are queued diff --git a/docs/cli/status.md b/docs/cli/status.md index fb7bddb182..9fa8e25905 100644 --- a/docs/cli/status.md +++ b/docs/cli/status.md @@ -1,4 +1,3 @@ - # Status -The ```status``` command outputs the status of the client. +The ```status``` command outputs the status of the client. \ No newline at end of file diff --git a/docs/cli/version.md b/docs/cli/version.md index 156bdf607c..87e7cf44a8 100644 --- a/docs/cli/version.md +++ b/docs/cli/version.md @@ -1,4 +1,3 @@ - # Version The ```bor version``` command outputs the version of the binary. @@ -8,4 +7,4 @@ The ```bor version``` command outputs the version of the binary. ``` $ bor version 0.2.9-stable -``` +``` \ No newline at end of file diff --git a/internal/cli/account.go b/internal/cli/account.go index b8661821d0..7ce6c09b63 100644 --- a/internal/cli/account.go +++ b/internal/cli/account.go @@ -1,11 +1,27 @@ package cli -import "github.com/mitchellh/cli" +import ( + "strings" + + "github.com/mitchellh/cli" +) type Account struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (a *Account) MarkDown() string { + items := []string{ + "# Account", + "The ```account``` command groups actions to interact with accounts:", + "- [```account new```](./account_new.md): Create a new account in the Bor client.", + "- [```account list```](./account_list.md): List the wallets in the Bor client.", + "- [```account import```](./account_import.md): Import an account to the Bor client.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (a *Account) Help() string { return `Usage: bor account diff --git a/internal/cli/account_import.go b/internal/cli/account_import.go index 8c9ff40e58..d7ab14601a 100644 --- a/internal/cli/account_import.go +++ b/internal/cli/account_import.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "strings" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/crypto" @@ -12,6 +13,16 @@ type AccountImportCommand struct { *Meta } +// MarkDown implements cli.MarkDown interface +func (a *AccountImportCommand) MarkDown() string { + items := []string{ + "# Account import", + "The ```account import``` command imports an account in Json format to the Bor data directory.", + a.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (a *AccountImportCommand) Help() string { return `Usage: bor account import diff --git a/internal/cli/account_list.go b/internal/cli/account_list.go index 360d41b558..db77158b8e 100644 --- a/internal/cli/account_list.go +++ b/internal/cli/account_list.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "strings" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/internal/cli/flagset" @@ -11,6 +12,16 @@ type AccountListCommand struct { *Meta } +// MarkDown implements cli.MarkDown interface +func (a *AccountListCommand) MarkDown() string { + items := []string{ + "# Account list", + "The `account list` command lists all the accounts in the Bor data directory.", + a.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (a *AccountListCommand) Help() string { return `Usage: bor account list diff --git a/internal/cli/account_new.go b/internal/cli/account_new.go index 3334384cb0..f6591fc53b 100644 --- a/internal/cli/account_new.go +++ b/internal/cli/account_new.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "strings" "github.com/ethereum/go-ethereum/internal/cli/flagset" ) @@ -10,6 +11,16 @@ type AccountNewCommand struct { *Meta } +// MarkDown implements cli.MarkDown interface +func (a *AccountNewCommand) MarkDown() string { + items := []string{ + "# Account new", + "The `account new` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command.", + a.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (a *AccountNewCommand) Help() string { return `Usage: bor account new diff --git a/internal/cli/attach.go b/internal/cli/attach.go index eec8a28ed3..df1c76ff3d 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -26,6 +26,16 @@ type AttachCommand struct { JSpathFlag string } +// MarkDown implements cli.MarkDown interface +func (c *AttachCommand) MarkDown() string { + items := []string{ + "# Attach", + "Connect to remote Bor IPC console.", + c.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *AttachCommand) Help() string { return `Usage: bor attach diff --git a/internal/cli/bor_fingerprint.go b/internal/cli/bor_fingerprint.go index 5c5a8f47bd..e9f4e70398 100644 --- a/internal/cli/bor_fingerprint.go +++ b/internal/cli/bor_fingerprint.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "os/exec" + "strings" "github.com/ethereum/go-ethereum/params" "github.com/mitchellh/cli" @@ -18,6 +19,15 @@ type FingerprintCommand struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (c *FingerprintCommand) MarkDown() string { + items := []string{ + "# Fingerprint", + "Display the system fingerprint", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *FingerprintCommand) Help() string { return `Usage: bor fingerprint diff --git a/internal/cli/chain.go b/internal/cli/chain.go index b43f22f999..896ce42cc4 100644 --- a/internal/cli/chain.go +++ b/internal/cli/chain.go @@ -1,6 +1,8 @@ package cli import ( + "strings" + "github.com/mitchellh/cli" ) @@ -9,6 +11,17 @@ type ChainCommand struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (c *ChainCommand) MarkDown() string { + items := []string{ + "# Chain", + "The ```chain``` command groups actions to interact with the blockchain in the client:", + "- [```chain sethead```](./chain_sethead.md): Set the current chain to a certain block.", + "- [```chain watch```](./chain_watch.md): Watch the chainHead, reorg and fork events in real-time.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *ChainCommand) Help() string { return `Usage: bor chain diff --git a/internal/cli/chain_sethead.go b/internal/cli/chain_sethead.go index 127ac38f15..4d34479e0b 100644 --- a/internal/cli/chain_sethead.go +++ b/internal/cli/chain_sethead.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/server/proto" @@ -16,6 +17,18 @@ type ChainSetHeadCommand struct { yes bool } +// MarkDown implements cli.MarkDown interface +func (a *ChainSetHeadCommand) MarkDown() string { + items := []string{ + "# Chain sethead", + "The ```chain sethead ``` command sets the current chain to a certain block.", + "## Arguments", + "- ```number```: The block number to roll back.", + a.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *ChainSetHeadCommand) Help() string { return `Usage: bor chain sethead [--yes] diff --git a/internal/cli/chain_watch.go b/internal/cli/chain_watch.go index 9469c1df00..72bd21b85d 100644 --- a/internal/cli/chain_watch.go +++ b/internal/cli/chain_watch.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "os/signal" + "strings" "syscall" "github.com/ethereum/go-ethereum/core" @@ -17,6 +18,15 @@ type ChainWatchCommand struct { *Meta2 } +// MarkDown implements cli.MarkDown interface +func (c *ChainWatchCommand) MarkDown() string { + items := []string{ + "# Chain watch", + "The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *ChainWatchCommand) Help() string { return `Usage: bor chain watch diff --git a/internal/cli/command.go b/internal/cli/command.go index 9e373a65cd..4cb089b9ff 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -14,13 +14,29 @@ import ( "google.golang.org/grpc" ) +type MarkDownCommand interface { + MarkDown + cli.Command +} + +type MarkDownCommandFactory func() (MarkDownCommand, error) + func Run(args []string) int { - commands := commands() + commands := Commands() + + mappedCommands := make(map[string]cli.CommandFactory) + + for k, v := range commands { + mappedCommands[k] = func() (cli.Command, error) { + cmd, err := v() + return cmd.(cli.Command), err + } + } cli := &cli.CLI{ Name: "bor", Args: args, - Commands: commands, + Commands: mappedCommands, } exitCode, err := cli.Run() @@ -31,7 +47,7 @@ func Run(args []string) int { return exitCode } -func commands() map[string]cli.CommandFactory { +func Commands() map[string]MarkDownCommandFactory { ui := &cli.BasicUi{ Reader: os.Stdin, Writer: os.Stdout, @@ -44,93 +60,93 @@ func commands() map[string]cli.CommandFactory { meta := &Meta{ UI: ui, } - return map[string]cli.CommandFactory{ - "server": func() (cli.Command, error) { + return map[string]MarkDownCommandFactory{ + "server": func() (MarkDownCommand, error) { return &server.Command{ UI: ui, }, nil }, - "version": func() (cli.Command, error) { + "version": func() (MarkDownCommand, error) { return &VersionCommand{ UI: ui, }, nil }, - "debug": func() (cli.Command, error) { + "debug": func() (MarkDownCommand, error) { return &DebugCommand{ Meta2: meta2, }, nil }, - "chain": func() (cli.Command, error) { + "chain": func() (MarkDownCommand, error) { return &ChainCommand{ UI: ui, }, nil }, - "chain watch": func() (cli.Command, error) { + "chain watch": func() (MarkDownCommand, error) { return &ChainWatchCommand{ Meta2: meta2, }, nil }, - "chain sethead": func() (cli.Command, error) { + "chain sethead": func() (MarkDownCommand, error) { return &ChainSetHeadCommand{ Meta2: meta2, }, nil }, - "account": func() (cli.Command, error) { + "account": func() (MarkDownCommand, error) { return &Account{ UI: ui, }, nil }, - "account new": func() (cli.Command, error) { + "account new": func() (MarkDownCommand, error) { return &AccountNewCommand{ Meta: meta, }, nil }, - "account import": func() (cli.Command, error) { + "account import": func() (MarkDownCommand, error) { return &AccountImportCommand{ Meta: meta, }, nil }, - "account list": func() (cli.Command, error) { + "account list": func() (MarkDownCommand, error) { return &AccountListCommand{ Meta: meta, }, nil }, - "peers": func() (cli.Command, error) { + "peers": func() (MarkDownCommand, error) { return &PeersCommand{ UI: ui, }, nil }, - "peers add": func() (cli.Command, error) { + "peers add": func() (MarkDownCommand, error) { return &PeersAddCommand{ Meta2: meta2, }, nil }, - "peers remove": func() (cli.Command, error) { + "peers remove": func() (MarkDownCommand, error) { return &PeersRemoveCommand{ Meta2: meta2, }, nil }, - "peers list": func() (cli.Command, error) { + "peers list": func() (MarkDownCommand, error) { return &PeersListCommand{ Meta2: meta2, }, nil }, - "peers status": func() (cli.Command, error) { + "peers status": func() (MarkDownCommand, error) { return &PeersStatusCommand{ Meta2: meta2, }, nil }, - "status": func() (cli.Command, error) { + "status": func() (MarkDownCommand, error) { return &StatusCommand{ Meta2: meta2, }, nil }, - "fingerprint": func() (cli.Command, error) { + "fingerprint": func() (MarkDownCommand, error) { return &FingerprintCommand{ UI: ui, }, nil }, - "attach": func() (cli.Command, error) { + "attach": func() (MarkDownCommand, error) { return &AttachCommand{ UI: ui, Meta: meta, diff --git a/internal/cli/debug.go b/internal/cli/debug.go index a6b6ff7973..66e936995c 100644 --- a/internal/cli/debug.go +++ b/internal/cli/debug.go @@ -31,6 +31,33 @@ type DebugCommand struct { output string } +// MarkDown implements cli.MarkDown interface +func (d *DebugCommand) MarkDown() string { + examples := []string{ + "## Examples", + "By default it creates a tar.gz file with the output:", + CodeBlock([]string{ + "$ bor debug", + "Starting debugger...\n", + "Created debug archive: bor-debug-2021-10-26-073819Z.tar.gz", + }), + "Send the output to a specific directory:", + CodeBlock([]string{ + "$ bor debug --output data", + "Starting debugger...\n", + "Created debug directory: data/bor-debug-2021-10-26-075437Z", + }), + } + + items := []string{ + "# Debug", + "The ```bor debug``` command takes a debug dump of the running client.", + d.Flags().MarkDown(), + } + items = append(items, examples...) + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (d *DebugCommand) Help() string { return `Usage: bor debug diff --git a/internal/cli/flagset/flagset.go b/internal/cli/flagset/flagset.go index 4388dd03fc..e04f452c1e 100644 --- a/internal/cli/flagset/flagset.go +++ b/internal/cli/flagset/flagset.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "math/big" + "sort" "strings" "time" ) @@ -24,6 +25,7 @@ func NewFlagSet(name string) *Flagset { type FlagVar struct { Name string Usage string + Group string } func (f *Flagset) addFlag(fl *FlagVar) { @@ -39,6 +41,40 @@ func (f *Flagset) Help() string { return str + strings.Join(items, "\n\n") } +// MarkDown implements cli.MarkDown interface +func (f *Flagset) MarkDown() string { + if len(f.flags) == 0 { + return "" + } + + groups := make(map[string][]*FlagVar) + + for _, item := range f.flags { + groups[item.Group] = append(groups[item.Group], item) + } + + keys := make([]string, len(groups)) + i := 0 + for k := range groups { + keys[i] = k + i++ + } + sort.Strings(keys) + + items := []string{} + for _, k := range keys { + if k == "" { + items = append(items, fmt.Sprintf("## Options")) + } else { + items = append(items, fmt.Sprintf("### %s Options", k)) + } + for _, item := range groups[k] { + items = append(items, fmt.Sprintf("- ```%s```: %s", item.Name, item.Usage)) + } + } + return strings.Join(items, "\n\n") +} + func (f *Flagset) Parse(args []string) error { return f.set.Parse(args) } @@ -52,12 +88,14 @@ type BoolFlag struct { Usage string Default bool Value *bool + Group string } func (f *Flagset) BoolFlag(b *BoolFlag) { f.addFlag(&FlagVar{ Name: b.Name, Usage: b.Usage, + Group: b.Group, }) f.set.BoolVar(b.Value, b.Name, b.Default, b.Usage) } @@ -67,12 +105,14 @@ type StringFlag struct { Usage string Default string Value *string + Group string } func (f *Flagset) StringFlag(b *StringFlag) { f.addFlag(&FlagVar{ Name: b.Name, Usage: b.Usage, + Group: b.Group, }) f.set.StringVar(b.Value, b.Name, b.Default, b.Usage) } @@ -82,12 +122,14 @@ type IntFlag struct { Usage string Value *int Default int + Group string } func (f *Flagset) IntFlag(i *IntFlag) { f.addFlag(&FlagVar{ Name: i.Name, Usage: i.Usage, + Group: i.Group, }) f.set.IntVar(i.Value, i.Name, i.Default, i.Usage) } @@ -97,12 +139,14 @@ type Uint64Flag struct { Usage string Value *uint64 Default uint64 + Group string } func (f *Flagset) Uint64Flag(i *Uint64Flag) { f.addFlag(&FlagVar{ Name: i.Name, Usage: i.Usage, + Group: i.Group, }) f.set.Uint64Var(i.Value, i.Name, i.Default, i.Usage) } @@ -111,6 +155,7 @@ type BigIntFlag struct { Name string Usage string Value *big.Int + Group string } func (b *BigIntFlag) String() string { @@ -140,6 +185,7 @@ func (f *Flagset) BigIntFlag(b *BigIntFlag) { f.addFlag(&FlagVar{ Name: b.Name, Usage: b.Usage, + Group: b.Group, }) f.set.Var(b, b.Name, b.Usage) } @@ -148,6 +194,7 @@ type SliceStringFlag struct { Name string Usage string Value *[]string + Group string } func (i *SliceStringFlag) String() string { @@ -166,6 +213,7 @@ func (f *Flagset) SliceStringFlag(s *SliceStringFlag) { f.addFlag(&FlagVar{ Name: s.Name, Usage: s.Usage, + Group: s.Group, }) f.set.Var(s, s.Name, s.Usage) } @@ -175,12 +223,14 @@ type DurationFlag struct { Usage string Value *time.Duration Default time.Duration + Group string } func (f *Flagset) DurationFlag(d *DurationFlag) { f.addFlag(&FlagVar{ Name: d.Name, Usage: d.Usage, + Group: d.Group, }) f.set.DurationVar(d.Value, d.Name, d.Default, "") } @@ -189,6 +239,7 @@ type MapStringFlag struct { Name string Usage string Value *map[string]string + Group string } func (m *MapStringFlag) String() string { @@ -222,6 +273,7 @@ func (f *Flagset) MapStringFlag(m *MapStringFlag) { f.addFlag(&FlagVar{ Name: m.Name, Usage: m.Usage, + Group: m.Group, }) f.set.Var(m, m.Name, m.Usage) } @@ -231,12 +283,14 @@ type Float64Flag struct { Usage string Value *float64 Default float64 + Group string } func (f *Flagset) Float64Flag(i *Float64Flag) { f.addFlag(&FlagVar{ Name: i.Name, Usage: i.Usage, + Group: i.Group, }) f.set.Float64Var(i.Value, i.Name, i.Default, "") } diff --git a/internal/cli/markdown.go b/internal/cli/markdown.go new file mode 100644 index 0000000000..652c98e56b --- /dev/null +++ b/internal/cli/markdown.go @@ -0,0 +1,14 @@ +package cli + +import ( + "strings" +) + +type MarkDown interface { + MarkDown() string +} + +// Create a Markdown code block from a slice of string, where each string is a line of code +func CodeBlock(lines []string) string { + return "```\n" + strings.Join(lines, "\n") + "\n```" +} diff --git a/internal/cli/markdown_test.go b/internal/cli/markdown_test.go new file mode 100644 index 0000000000..13a5c4ece3 --- /dev/null +++ b/internal/cli/markdown_test.go @@ -0,0 +1,19 @@ +package cli + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCodeBlock(t *testing.T) { + assert := assert.New(t) + + lines := []string{ + "abc", + "bcd", + } + + expected := "```\n" + "abc\n" + "bcd\n" + "```" + assert.Equal(expected, CodeBlock(lines)) +} diff --git a/internal/cli/peers.go b/internal/cli/peers.go index b591366222..ee70a747b8 100644 --- a/internal/cli/peers.go +++ b/internal/cli/peers.go @@ -1,6 +1,8 @@ package cli import ( + "strings" + "github.com/mitchellh/cli" ) @@ -9,6 +11,19 @@ type PeersCommand struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (a *PeersCommand) MarkDown() string { + items := []string{ + "# Peers", + "The ```peers``` command groups actions to interact with peers:", + "- [```peers add```](./peers_add.md): Joins the local client to another remote peer.", + "- [```peers list```](./peers_list.md): Lists the connected peers to the Bor client.", + "- [```peers remove```](./peers_remove.md): Disconnects the local client from a connected peer if exists.", + "- [```peers status```](./peers_status.md): Display the status of a peer by its id.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *PeersCommand) Help() string { return `Usage: bor peers diff --git a/internal/cli/peers_add.go b/internal/cli/peers_add.go index 2b2fe127e0..ae84f4e0c1 100644 --- a/internal/cli/peers_add.go +++ b/internal/cli/peers_add.go @@ -2,6 +2,7 @@ package cli import ( "context" + "strings" "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/server/proto" @@ -14,6 +15,16 @@ type PeersAddCommand struct { trusted bool } +// MarkDown implements cli.MarkDown interface +func (p *PeersAddCommand) MarkDown() string { + items := []string{ + "# Peers add", + "The ```peers add ``` command joins the local client to another remote peer.", + p.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *PeersAddCommand) Help() string { return `Usage: bor peers add diff --git a/internal/cli/peers_list.go b/internal/cli/peers_list.go index a42e0011a5..56dfdc317d 100644 --- a/internal/cli/peers_list.go +++ b/internal/cli/peers_list.go @@ -14,6 +14,16 @@ type PeersListCommand struct { *Meta2 } +// MarkDown implements cli.MarkDown interface +func (p *PeersListCommand) MarkDown() string { + items := []string{ + "# Peers add", + "The ```peers list``` command lists the connected peers.", + p.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *PeersListCommand) Help() string { return `Usage: bor peers list diff --git a/internal/cli/peers_remove.go b/internal/cli/peers_remove.go index 979f139251..5cd3796e3c 100644 --- a/internal/cli/peers_remove.go +++ b/internal/cli/peers_remove.go @@ -2,6 +2,7 @@ package cli import ( "context" + "strings" "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/server/proto" @@ -14,6 +15,16 @@ type PeersRemoveCommand struct { trusted bool } +// MarkDown implements cli.MarkDown interface +func (p *PeersRemoveCommand) MarkDown() string { + items := []string{ + "# Peers remove", + "The ```peers remove ``` command disconnects the local client from a connected peer if exists.", + p.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *PeersRemoveCommand) Help() string { return `Usage: bor peers remove diff --git a/internal/cli/peers_status.go b/internal/cli/peers_status.go index c1da2b2647..bb8d385291 100644 --- a/internal/cli/peers_status.go +++ b/internal/cli/peers_status.go @@ -14,6 +14,16 @@ type PeersStatusCommand struct { *Meta2 } +// MarkDown implements cli.MarkDown interface +func (p *PeersStatusCommand) MarkDown() string { + items := []string{ + "# Peers status", + "The ```peers status ``` command displays the status of a peer by its id.", + p.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *PeersStatusCommand) Help() string { return `Usage: bor peers status diff --git a/internal/cli/server/command.go b/internal/cli/server/command.go index 4b2374dc42..01ce44f5ee 100644 --- a/internal/cli/server/command.go +++ b/internal/cli/server/command.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "os/signal" + "strings" "syscall" "github.com/ethereum/go-ethereum/log" @@ -25,6 +26,16 @@ type Command struct { srv *Server } +// MarkDown implements cli.MarkDown interface +func (c *Command) MarkDown() string { + items := []string{ + "# Server", + "The ```bor server``` command runs the Bor client.", + c.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *Command) Help() string { return `Usage: bor [options] diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index edc7276a8b..ce93e8c071 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -36,7 +36,7 @@ func (c *Command) Flags() *flagset.Flagset { }) f.StringFlag(&flagset.StringFlag{ Name: "syncmode", - Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`, + Usage: `Blockchain sync mode ("fast", "full", or "snap")`, Value: &c.cliConfig.SyncMode, }) f.StringFlag(&flagset.StringFlag{ @@ -72,56 +72,67 @@ func (c *Command) Flags() *flagset.Flagset { Name: "txpool.locals", Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", Value: &c.cliConfig.TxPool.Locals, + Group: "Transaction Pool", }) f.BoolFlag(&flagset.BoolFlag{ Name: "txpool.nolocals", Usage: "Disables price exemptions for locally submitted transactions", Value: &c.cliConfig.TxPool.NoLocals, + Group: "Transaction Pool", }) f.StringFlag(&flagset.StringFlag{ Name: "txpool.journal", Usage: "Disk journal for local transaction to survive node restarts", Value: &c.cliConfig.TxPool.Journal, + Group: "Transaction Pool", }) f.DurationFlag(&flagset.DurationFlag{ Name: "txpool.rejournal", Usage: "Time interval to regenerate the local transaction journal", Value: &c.cliConfig.TxPool.Rejournal, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.pricelimit", Usage: "Minimum gas price limit to enforce for acceptance into the pool", Value: &c.cliConfig.TxPool.PriceLimit, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.pricebump", Usage: "Price bump percentage to replace an already existing transaction", Value: &c.cliConfig.TxPool.PriceBump, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.accountslots", Usage: "Minimum number of executable transaction slots guaranteed per account", Value: &c.cliConfig.TxPool.AccountSlots, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.globalslots", Usage: "Maximum number of executable transaction slots for all accounts", Value: &c.cliConfig.TxPool.GlobalSlots, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.accountqueue", Usage: "Maximum number of non-executable transaction slots permitted per account", Value: &c.cliConfig.TxPool.AccountQueue, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txpool.globalqueue", Usage: "Maximum number of non-executable transaction slots for all accounts", Value: &c.cliConfig.TxPool.GlobalQueue, + Group: "Transaction Pool", }) f.DurationFlag(&flagset.DurationFlag{ Name: "txpool.lifetime", Usage: "Maximum amount of time non-executable transaction are queued", Value: &c.cliConfig.TxPool.LifeTime, + Group: "Transaction Pool", }) // sealer options @@ -129,26 +140,31 @@ func (c *Command) Flags() *flagset.Flagset { Name: "mine", Usage: "Enable mining", Value: &c.cliConfig.Sealer.Enabled, + Group: "Sealer", }) f.StringFlag(&flagset.StringFlag{ Name: "miner.etherbase", Usage: "Public address for block mining rewards (default = first account)", Value: &c.cliConfig.Sealer.Etherbase, + Group: "Sealer", }) f.StringFlag(&flagset.StringFlag{ Name: "miner.extradata", Usage: "Block extra data set by the miner (default = client version)", Value: &c.cliConfig.Sealer.ExtraData, + Group: "Sealer", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "miner.gaslimit", Usage: "Target gas ceiling for mined blocks", Value: &c.cliConfig.Sealer.GasCeil, + Group: "Sealer", }) f.BigIntFlag(&flagset.BigIntFlag{ Name: "miner.gasprice", Usage: "Minimum gas price for mining a transaction", Value: c.cliConfig.Sealer.GasPrice, + Group: "Sealer", }) // ethstats @@ -185,51 +201,61 @@ func (c *Command) Flags() *flagset.Flagset { Name: "cache", Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)", Value: &c.cliConfig.Cache.Cache, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "cache.database", Usage: "Percentage of cache memory allowance to use for database io", Value: &c.cliConfig.Cache.PercDatabase, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "cache.trie", Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", Value: &c.cliConfig.Cache.PercTrie, + Group: "Cache", }) f.StringFlag(&flagset.StringFlag{ Name: "cache.trie.journal", Usage: "Disk journal directory for trie cache to survive node restarts", Value: &c.cliConfig.Cache.Journal, + Group: "Cache", }) f.DurationFlag(&flagset.DurationFlag{ Name: "cache.trie.rejournal", Usage: "Time interval to regenerate the trie cache journal", Value: &c.cliConfig.Cache.Rejournal, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "cache.gc", Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", Value: &c.cliConfig.Cache.PercGc, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "cache.snapshot", Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", Value: &c.cliConfig.Cache.PercSnapshot, + Group: "Cache", }) f.BoolFlag(&flagset.BoolFlag{ Name: "cache.noprefetch", Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", Value: &c.cliConfig.Cache.NoPrefetch, + Group: "Cache", }) f.BoolFlag(&flagset.BoolFlag{ Name: "cache.preimages", Usage: "Enable recording the SHA3/keccak preimages of trie keys", Value: &c.cliConfig.Cache.Preimages, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "txlookuplimit", Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)", Value: &c.cliConfig.Cache.TxLookupLimit, + Group: "Cache", }) // rpc options @@ -237,31 +263,37 @@ func (c *Command) Flags() *flagset.Flagset { Name: "rpc.gascap", Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", Value: &c.cliConfig.JsonRPC.GasCap, + Group: "JsonRPC", }) f.Float64Flag(&flagset.Float64Flag{ Name: "rpc.txfeecap", Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", Value: &c.cliConfig.JsonRPC.TxFeeCap, + Group: "JsonRPC", }) f.BoolFlag(&flagset.BoolFlag{ Name: "ipcdisable", Usage: "Disable the IPC-RPC server", Value: &c.cliConfig.JsonRPC.IPCDisable, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "ipcpath", Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", Value: &c.cliConfig.JsonRPC.IPCPath, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "jsonrpc.corsdomain", Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", Value: &c.cliConfig.JsonRPC.Cors, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "jsonrpc.vhosts", Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", Value: &c.cliConfig.JsonRPC.VHost, + Group: "JsonRPC", }) // http options @@ -269,26 +301,31 @@ func (c *Command) Flags() *flagset.Flagset { Name: "http", Usage: "Enable the HTTP-RPC server", Value: &c.cliConfig.JsonRPC.Http.Enabled, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "http.addr", Usage: "HTTP-RPC server listening interface", Value: &c.cliConfig.JsonRPC.Http.Host, + Group: "JsonRPC", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "http.port", Usage: "HTTP-RPC server listening port", Value: &c.cliConfig.JsonRPC.Http.Port, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "http.rpcprefix", Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", Value: &c.cliConfig.JsonRPC.Http.Prefix, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "http.modules", Usage: "API's offered over the HTTP-RPC interface", Value: &c.cliConfig.JsonRPC.Http.Modules, + Group: "JsonRPC", }) // ws options @@ -296,26 +333,31 @@ func (c *Command) Flags() *flagset.Flagset { Name: "ws", Usage: "Enable the WS-RPC server", Value: &c.cliConfig.JsonRPC.Ws.Enabled, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "ws.addr", Usage: "WS-RPC server listening interface", Value: &c.cliConfig.JsonRPC.Ws.Host, + Group: "JsonRPC", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "ws.port", Usage: "WS-RPC server listening port", Value: &c.cliConfig.JsonRPC.Ws.Port, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ Name: "ws.rpcprefix", Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", Value: &c.cliConfig.JsonRPC.Ws.Prefix, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "ws.modules", Usage: "API's offered over the WS-RPC interface", Value: &c.cliConfig.JsonRPC.Ws.Modules, + Group: "JsonRPC", }) // graphql options @@ -323,6 +365,7 @@ func (c *Command) Flags() *flagset.Flagset { Name: "graphql", Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.", Value: &c.cliConfig.JsonRPC.Graphql.Enabled, + Group: "JsonRPC", }) // p2p options @@ -330,41 +373,49 @@ func (c *Command) Flags() *flagset.Flagset { Name: "bind", Usage: "Network binding address", Value: &c.cliConfig.P2P.Bind, + Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "port", Usage: "Network listening port", Value: &c.cliConfig.P2P.Port, + Group: "P2P", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "bootnodes", Usage: "Comma separated enode URLs for P2P discovery bootstrap", Value: &c.cliConfig.P2P.Discovery.Bootnodes, + Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "maxpeers", Usage: "Maximum number of network peers (network disabled if set to 0)", Value: &c.cliConfig.P2P.MaxPeers, + Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ Name: "maxpendpeers", Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", Value: &c.cliConfig.P2P.MaxPendPeers, + Group: "P2P", }) f.StringFlag(&flagset.StringFlag{ Name: "nat", Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", Value: &c.cliConfig.P2P.NAT, + Group: "P2P", }) f.BoolFlag(&flagset.BoolFlag{ Name: "nodiscover", Usage: "Disables the peer discovery mechanism (manual peer addition)", Value: &c.cliConfig.P2P.NoDiscover, + Group: "P2P", }) f.BoolFlag(&flagset.BoolFlag{ Name: "v5disc", Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", Value: &c.cliConfig.P2P.Discovery.V5Enabled, + Group: "P2P", }) // metrics @@ -372,72 +423,86 @@ func (c *Command) Flags() *flagset.Flagset { Name: "metrics", Usage: "Enable metrics collection and reporting", Value: &c.cliConfig.Telemetry.Enabled, + Group: "Telemetry", }) f.BoolFlag(&flagset.BoolFlag{ Name: "metrics.expensive", Usage: "Enable expensive metrics collection and reporting", Value: &c.cliConfig.Telemetry.Expensive, + Group: "Telemetry", }) f.BoolFlag(&flagset.BoolFlag{ Name: "metrics.influxdb", Usage: "Enable metrics export/push to an external InfluxDB database (v1)", Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.endpoint", Usage: "InfluxDB API endpoint to report metrics to", Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.database", Usage: "InfluxDB database name to push reported metrics to", Value: &c.cliConfig.Telemetry.InfluxDB.Database, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.username", Usage: "Username to authorize access to the database", Value: &c.cliConfig.Telemetry.InfluxDB.Username, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.password", Usage: "Password to authorize access to the database", Value: &c.cliConfig.Telemetry.InfluxDB.Password, + Group: "Telemetry", }) f.MapStringFlag(&flagset.MapStringFlag{ Name: "metrics.influxdb.tags", Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", Value: &c.cliConfig.Telemetry.InfluxDB.Tags, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.prometheus-addr", Usage: "Address for Prometheus Server", Value: &c.cliConfig.Telemetry.PrometheusAddr, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.opencollector-endpoint", Usage: "OpenCollector Endpoint (host:port)", Value: &c.cliConfig.Telemetry.OpenCollectorEndpoint, + Group: "Telemetry", }) // influx db v2 f.BoolFlag(&flagset.BoolFlag{ Name: "metrics.influxdbv2", Usage: "Enable metrics export/push to an external InfluxDB v2 database", Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.token", Usage: "Token to authorize access to the database (v2 only)", Value: &c.cliConfig.Telemetry.InfluxDB.Token, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.bucket", Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", Value: &c.cliConfig.Telemetry.InfluxDB.Bucket, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ Name: "metrics.influxdb.organization", Usage: "InfluxDB organization name (v2 only)", Value: &c.cliConfig.Telemetry.InfluxDB.Organization, + Group: "Telemetry", }) // account @@ -445,21 +510,25 @@ func (c *Command) Flags() *flagset.Flagset { Name: "unlock", Usage: "Comma separated list of accounts to unlock", Value: &c.cliConfig.Accounts.Unlock, + Group: "Account Management", }) f.StringFlag(&flagset.StringFlag{ Name: "password", Usage: "Password file to use for non-interactive password input", Value: &c.cliConfig.Accounts.PasswordFile, + Group: "Account Management", }) f.BoolFlag(&flagset.BoolFlag{ Name: "allow-insecure-unlock", Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", Value: &c.cliConfig.Accounts.AllowInsecureUnlock, + Group: "Account Management", }) f.BoolFlag(&flagset.BoolFlag{ Name: "lightkdf", Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", Value: &c.cliConfig.Accounts.UseLightweightKDF, + Group: "Account Management", }) // grpc diff --git a/internal/cli/status.go b/internal/cli/status.go index ef0a42172b..c4165b0a2e 100644 --- a/internal/cli/status.go +++ b/internal/cli/status.go @@ -14,6 +14,15 @@ type StatusCommand struct { *Meta2 } +// MarkDown implements cli.MarkDown interface +func (p *StatusCommand) MarkDown() string { + items := []string{ + "# Status", + "The ```status``` command outputs the status of the client.", + } + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (p *StatusCommand) Help() string { return `Usage: bor status diff --git a/internal/cli/version.go b/internal/cli/version.go index 7433f208b2..080cf41221 100644 --- a/internal/cli/version.go +++ b/internal/cli/version.go @@ -1,6 +1,8 @@ package cli import ( + "strings" + "github.com/ethereum/go-ethereum/params" "github.com/mitchellh/cli" ) @@ -10,6 +12,24 @@ type VersionCommand struct { UI cli.Ui } +// MarkDown implements cli.MarkDown interface +func (d *VersionCommand) MarkDown() string { + examples := []string{ + "## Usage", + CodeBlock([]string{ + "$ bor version", + "0.2.9-stable", + }), + } + + items := []string{ + "# Version", + "The ```bor version``` command outputs the version of the binary.", + } + items = append(items, examples...) + return strings.Join(items, "\n\n") +} + // Help implements the cli.Command interface func (c *VersionCommand) Help() string { return `Usage: bor version From ad8bede955d8b5fa6b81dd9a38ad4a878a0fa91f Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 3 May 2022 14:52:15 -0700 Subject: [PATCH 27/80] Add bootnode cli --- docs/cli/README.md | 2 + docs/cli/bootnode.md | 17 +++ internal/cli/bootnode.go | 220 +++++++++++++++++++++++++++++++++++++++ internal/cli/command.go | 9 ++ 4 files changed, 248 insertions(+) create mode 100644 docs/cli/bootnode.md create mode 100644 internal/cli/bootnode.go diff --git a/docs/cli/README.md b/docs/cli/README.md index c10c8bf9c2..d5648dca7d 100644 --- a/docs/cli/README.md +++ b/docs/cli/README.md @@ -12,6 +12,8 @@ - [```attach```](./attach.md) +- [```bootnode```](./bootnode.md) + - [```chain```](./chain.md) - [```chain sethead```](./chain_sethead.md) diff --git a/docs/cli/bootnode.md b/docs/cli/bootnode.md new file mode 100644 index 0000000000..3e60252341 --- /dev/null +++ b/docs/cli/bootnode.md @@ -0,0 +1,17 @@ +# Bootnode + +## Options + +- ```listen-addr```: listening address of bootnode (:) + +- ```v5```: Enable UDP v5 + +- ```log-level```: Log level (trace|debug|info|warn|error|crit) + +- ```nat```: port mapping mechanism (any|none|upnp|pmp|extip:) + +- ```node-key```: file or hex node key + +- ```save-key```: path to save the ecdsa private key + +- ```dry-run``` \ No newline at end of file diff --git a/internal/cli/bootnode.go b/internal/cli/bootnode.go new file mode 100644 index 0000000000..f9127494a6 --- /dev/null +++ b/internal/cli/bootnode.go @@ -0,0 +1,220 @@ +package cli + +import ( + "crypto/ecdsa" + "errors" + "fmt" + "io/ioutil" + "net" + "os" + "os/signal" + "path/filepath" + "strings" + "syscall" + + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/internal/cli/flagset" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/nat" + "github.com/mitchellh/cli" +) + +type BootnodeCommand struct { + UI cli.Ui + + listenAddr string + v5 bool + logLevel string + nat string + nodeKey string + saveKey string + dryRun bool +} + +// Help implements the cli.Command interface +func (b *BootnodeCommand) Help() string { + return `Usage: bor bootnode` +} + +// MarkDown implements cli.MarkDown interface +func (c *BootnodeCommand) MarkDown() string { + items := []string{ + "# Bootnode", + c.Flags().MarkDown(), + } + return strings.Join(items, "\n\n") +} + +func (b *BootnodeCommand) Flags() *flagset.Flagset { + flags := flagset.NewFlagSet("bootnode") + + flags.StringFlag(&flagset.StringFlag{ + Name: "listen-addr", + Default: "0.0.0.0:30303", + Usage: "listening address of bootnode (:)", + Value: &b.listenAddr, + }) + flags.BoolFlag(&flagset.BoolFlag{ + Name: "v5", + Default: false, + Usage: "Enable UDP v5", + Value: &b.v5, + }) + flags.StringFlag(&flagset.StringFlag{ + Name: "log-level", + Default: "info", + Usage: "Log level (trace|debug|info|warn|error|crit)", + Value: &b.logLevel, + }) + flags.StringFlag(&flagset.StringFlag{ + Name: "nat", + Default: "none", + Usage: "port mapping mechanism (any|none|upnp|pmp|extip:)", + Value: &b.nat, + }) + flags.StringFlag(&flagset.StringFlag{ + Name: "node-key", + Default: "", + Usage: "file or hex node key", + Value: &b.nodeKey, + }) + flags.StringFlag(&flagset.StringFlag{ + Name: "save-key", + Default: "", + Usage: "path to save the ecdsa private key", + Value: &b.saveKey, + }) + flags.BoolFlag(&flagset.BoolFlag{ + Name: "dry-run", + Default: false, + Usage: "validates parameters and prints bootnode configurations, but does not start bootnode", + Value: &b.dryRun, + }) + + return flags +} + +// Synopsis implements the cli.Command interface +func (b *BootnodeCommand) Synopsis() string { + return "Start a bootnode" +} + +// Run implements the cli.Command interface +func (b *BootnodeCommand) Run(args []string) int { + flags := b.Flags() + if err := flags.Parse(args); err != nil { + b.UI.Error(err.Error()) + return 1 + } + + glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) + + lvl, err := log.LvlFromString(strings.ToLower(b.logLevel)) + if err == nil { + glogger.Verbosity(lvl) + } else { + glogger.Verbosity(log.LvlInfo) + } + log.Root().SetHandler(glogger) + + natm, err := nat.Parse(b.nat) + if err != nil { + b.UI.Error(fmt.Sprintf("failed to parse nat: %v", err)) + return 1 + } + + // create a one time key + var nodeKey *ecdsa.PrivateKey + if b.nodeKey != "" { + // try to read the key either from file or command line + if _, err := os.Stat(b.nodeKey); errors.Is(err, os.ErrNotExist) { + if nodeKey, err = crypto.HexToECDSA(b.nodeKey); err != nil { + b.UI.Error(fmt.Sprintf("failed to parse hex address: %v", err)) + return 1 + } + } else { + if nodeKey, err = crypto.LoadECDSA(b.nodeKey); err != nil { + b.UI.Error(fmt.Sprintf("failed to load node key: %v", err)) + return 1 + } + } + } else { + // generate a new temporal key + if nodeKey, err = crypto.GenerateKey(); err != nil { + b.UI.Error(fmt.Sprintf("could not generate key: %v", err)) + return 1 + } + if b.saveKey != "" { + path := b.saveKey + + // save the private key + if err = crypto.SaveECDSA(filepath.Join(path, "priv.key"), nodeKey); err != nil { + b.UI.Error(fmt.Sprintf("failed to write node priv key: %v", err)) + return 1 + } + // save the public key + pubRaw := fmt.Sprintf("%x", crypto.FromECDSAPub(&nodeKey.PublicKey)[1:]) + if err := ioutil.WriteFile(filepath.Join(path, "pub.key"), []byte(pubRaw), 0755); err != nil { + b.UI.Error(fmt.Sprintf("failed to write node pub key: %v", err)) + return 1 + } + } + } + + addr, err := net.ResolveUDPAddr("udp", b.listenAddr) + if err != nil { + b.UI.Error(fmt.Sprintf("could not resolve udp addr '%s': %v", b.listenAddr, err)) + return 1 + } + conn, err := net.ListenUDP("udp", addr) + if err != nil { + b.UI.Error(fmt.Sprintf("failed to listen udp addr '%s': %v", b.listenAddr, err)) + return 1 + } + + realaddr := conn.LocalAddr().(*net.UDPAddr) + if natm != nil { + if !realaddr.IP.IsLoopback() { + go nat.Map(natm, nil, "udp", realaddr.Port, realaddr.Port, "ethereum discovery") + } + if ext, err := natm.ExternalIP(); err == nil { + realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port} + } + } + + n := enode.NewV4(&nodeKey.PublicKey, addr.IP, addr.Port, addr.Port) + b.UI.Info(n.String()) + + if b.dryRun { + return 0 + } + + db, _ := enode.OpenDB("") + ln := enode.NewLocalNode(db, nodeKey) + cfg := discover.Config{ + PrivateKey: nodeKey, + Log: log.Root(), + } + if b.v5 { + if _, err := discover.ListenV5(conn, ln, cfg); err != nil { + utils.Fatalf("%v", err) + } + } else { + if _, err := discover.ListenUDP(conn, ln, cfg); err != nil { + utils.Fatalf("%v", err) + } + } + + signalCh := make(chan os.Signal, 4) + signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP) + + sig := <-signalCh + + b.UI.Output(fmt.Sprintf("Caught signal: %v", sig)) + b.UI.Output("Gracefully shutting down agent...") + + return 0 +} diff --git a/internal/cli/command.go b/internal/cli/command.go index 4cb089b9ff..d1851594a7 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -27,6 +27,10 @@ func Run(args []string) int { mappedCommands := make(map[string]cli.CommandFactory) for k, v := range commands { + // Declare a new v to limit the scope of v to inside the block, so the anonymous function below + // can get the "current" value of v, instead of the value of last v in the loop. + // See this post: https://stackoverflow.com/questions/10116507/go-transfer-var-into-anonymous-function for more explanation + v := v mappedCommands[k] = func() (cli.Command, error) { cmd, err := v() return cmd.(cli.Command), err @@ -153,6 +157,11 @@ func Commands() map[string]MarkDownCommandFactory { Meta2: meta2, }, nil }, + "bootnode": func() (MarkDownCommand, error) { + return &BootnodeCommand{ + UI: ui, + }, nil + }, } } From 8fc86ccb9027430ad35f558187a153c2238b4733 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 6 May 2022 13:55:00 -0700 Subject: [PATCH 28/80] Fix prometheus path and add prometheus to bor.service --- builder/files/bor.service | 6 +++++- internal/cli/server/server.go | 4 +--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/builder/files/bor.service b/builder/files/bor.service index 4f834a3cb4..6fe89a8f2d 100644 --- a/builder/files/bor.service +++ b/builder/files/bor.service @@ -10,14 +10,18 @@ -chain=mumbai \ # -chain=mainnet \ -datadir /var/lib/bor/data \ + -metrics \ + -metrics.prometheus-addr="127.0.0.1:7071" \ -bootnodes "enode://0cb82b395094ee4a2915e9714894627de9ed8498fb881cec6db7c65e8b9a5bd7f2f25cc84e71e89d0947e51c76e85d0847de848c7782b13c0255247a6758178c@44.232.55.71:30303,enode://88116f4295f5a31538ae409e4d44ad40d22e44ee9342869e7d68bdec55b0f83c1530355ce8b41fbec0928a7d75a5745d528450d30aec92066ab6ba1ee351d710@159.203.9.164:30303" # Validator params - # Uncomment and configure the following lines in case you run a validator + # Uncomment and configure the following lines in case you run a validator. Don't forget to add backslash (\) + # to previous command line. # -keystore /var/lib/bor/keystore \ # -unlock [VALIDATOR ADDRESS] \ # -password /var/lib/bor/password.txt \ # -allow-insecure-unlock \ # -nodiscover -maxpeers 1 \ + # -miner.etherbase [VALIDATOR ADDRESS] \ # -mine Type=simple User=root diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go index e882429e86..5d3d307d2a 100644 --- a/internal/cli/server/server.go +++ b/internal/cli/server/server.go @@ -175,9 +175,7 @@ func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error prometheusMux := http.NewServeMux() - prometheusMux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) { - prometheus.Handler(metrics.DefaultRegistry) - }) + prometheusMux.Handle("/debug/metrics/prometheus", prometheus.Handler(metrics.DefaultRegistry)) promServer := &http.Server{ Addr: config.PrometheusAddr, From eb76df22af662774063e9f0b4bfe1d2bc764fc59 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 10:00:31 +0300 Subject: [PATCH 29/80] better ci --- .github/workflows/ci.yml | 63 ++++++++++++++++++++++++++++++---------- Makefile | 24 +++++++++++++-- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d61e14cb42..b6e2e71305 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,20 +1,53 @@ name: CI on: [push, pull_request] jobs: - build: - runs-on: ubuntu-latest + tests: + strategy: + matrix: + os: [ ubuntu-20.04, macos-11 ] # list of os: https://github.com/actions/virtual-environments + runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: 1.17 - - name: "Build binaries" - run: make all - - name: "Run tests" - run: make test - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 - with: - file: ./cover.out + - uses: actions/checkout@v3 + - run: git submodule update --init --recursive --force + - uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Install dependencies on Linux + if: runner.os == 'Linux' + run: sudo apt update && sudo apt install build-essential + - uses: actions/cache@v3 + with: + path: | + ~/.cache/go-build + ~/Library/Caches/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + + - name: Build + run: make all + + - name: Reproducible build test + run: | + make geth + shasum -a256 ./build/bin/geth > bor1.sha256 + make geth + shasum -a256 ./build/bin/geth > bor2.sha256 + if ! cmp -s bor1.sha256 bor2.sha256; then + echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1 + fi + + - name: Lint + if: runner.os == 'Linux' + uses: golangci/golangci-lint-action@v3 + with: + version: v1.46 + skip-pkg-cache: true + skip-build-cache: true + + - name: Test + run: make test + + - name: Data race tests + run: make test-race \ No newline at end of file diff --git a/Makefile b/Makefile index 6469b8510f..d23903faac 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,21 @@ .PHONY: geth android ios evm all test clean -GOBIN = ./build/bin GO ?= latest +GOBIN = $(CURDIR)/build/bin GORUN = env GO111MODULE=on go run GOPATH = $(shell go env GOPATH) +GIT_COMMIT ?= $(shell git rev-list -1 HEAD) +GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) +GIT_TAG ?= $(shell git describe --tags `git rev-list --tags="v*" --max-count=1`) + +PACKAGE = github.com/ethereum/go-ethereum +GO_FLAGS += -trimpath -buildvcs=false +GO_FLAGS += -ldflags "-X ${PACKAGE}/params.GitCommit=${GIT_COMMIT} -X ${PACKAGE}/params.GitBranch=${GIT_BRANCH} -X ${PACKAGE}/params.GitTag=${GIT_TAG}" + +GOTEST = GODEBUG=cgocheck=0 go test $(GO_FLAGS) ./... -p 1 -shuffle=on + bor: $(GORUN) build/ci.go install ./cmd/geth mkdir -p $(GOPATH)/bin/ @@ -45,8 +55,16 @@ ios: @echo "Import \"$(GOBIN)/Geth.framework\" to use the library." test: - # Skip mobile and cmd tests since they are being deprecated - go test -v $$(go list ./... | grep -v go-ethereum/cmd/) -cover -coverprofile=cover.out + $(GOTEST) --timeout 5m -cover -coverprofile=cover.out + +test-race: + $(GOTEST) --timeout 5m -race + +test-integration: + $(GOTEST) --timeout 30m -tags integration + +escape: + cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out lint: ## Run linters. $(GORUN) build/ci.go lint From 5192fd7d8dff7a211a69d79a1d408490779edbc3 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 10:26:10 +0300 Subject: [PATCH 30/80] split units and integration. step 1 --- .github/workflows/ci.yml | 30 +++++++++++++------- .github/workflows/test-integration.yml | 39 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/test-integration.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6e2e71305..6ba2cece0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,16 @@ name: CI -on: [push, pull_request] +on: + push: + branches: + - "**" + - "!master" + pull_request: + branches: + - master + types: [opened, synchronize, closed] jobs: tests: + if: (!(github.event.action == 'closed' && github.event.pull_request.merged != true)) strategy: matrix: os: [ ubuntu-20.04, macos-11 ] # list of os: https://github.com/actions/virtual-environments @@ -28,15 +37,16 @@ jobs: - name: Build run: make all - - name: Reproducible build test - run: | - make geth - shasum -a256 ./build/bin/geth > bor1.sha256 - make geth - shasum -a256 ./build/bin/geth > bor2.sha256 - if ! cmp -s bor1.sha256 bor2.sha256; then - echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1 - fi + # TODO: make it work + # - name: Reproducible build test + # run: | + # make geth + # shasum -a256 ./build/bin/geth > bor1.sha256 + # make geth + # shasum -a256 ./build/bin/geth > bor2.sha256 + # if ! cmp -s bor1.sha256 bor2.sha256; then + # echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1 + # fi - name: Lint if: runner.os == 'Linux' diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml new file mode 100644 index 0000000000..93578062f2 --- /dev/null +++ b/.github/workflows/test-integration.yml @@ -0,0 +1,39 @@ +name: Integration tests +on: + push: + branches: + - "**" + - "!master" + pull_request: + branches: + - master + types: [opened, synchronize, closed] +jobs: + tests: + if: (!(github.event.action == 'closed' && github.event.pull_request.merged != true)) + strategy: + matrix: + os: [ ubuntu-20.04, macos-11 ] # list of os: https://github.com/actions/virtual-environments + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + - run: git submodule update --init --recursive --force + - uses: actions/setup-go@v3 + with: + go-version: 1.18.x + - name: Install dependencies on Linux + if: runner.os == 'Linux' + run: sudo apt update && sudo apt install build-essential + + - uses: actions/cache@v3 + with: + path: | + ~/.cache/go-build + ~/Library/Caches/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + + - name: test-integration + run: make test-integration From ee5b7c04aa571c158c0c2bfcac5cb5802954a5ef Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 10:31:41 +0300 Subject: [PATCH 31/80] integration tag --- tests/block_test.go | 3 +++ tests/block_test_util.go | 4 ++++ tests/bor/bor_test.go | 3 +++ tests/difficulty_test.go | 3 +++ tests/init_test.go | 3 +++ tests/state_test.go | 3 +++ tests/transaction_test.go | 3 +++ 7 files changed, 22 insertions(+) diff --git a/tests/block_test.go b/tests/block_test.go index 74c7ed8197..591bff6e07 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -14,6 +14,9 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . +//go:build integration +// +build integration + package tests import ( diff --git a/tests/block_test_util.go b/tests/block_test_util.go index bcf861e09b..fea4ee0b95 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -15,6 +15,10 @@ // along with the go-ethereum library. If not, see . // Package tests implements execution of Ethereum JSON tests. + +//go:build integration +// +build integration + package tests import ( diff --git a/tests/bor/bor_test.go b/tests/bor/bor_test.go index 7d0ca9372b..3bda2ee3f4 100644 --- a/tests/bor/bor_test.go +++ b/tests/bor/bor_test.go @@ -1,3 +1,6 @@ +//go:build integration +// +build integration + package bor import ( diff --git a/tests/difficulty_test.go b/tests/difficulty_test.go index 192dff12cc..0b030c1485 100644 --- a/tests/difficulty_test.go +++ b/tests/difficulty_test.go @@ -14,6 +14,9 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . +//go:build integration +// +build integration + package tests import ( diff --git a/tests/init_test.go b/tests/init_test.go index 7e2f3ff7f5..4ade0bfb90 100644 --- a/tests/init_test.go +++ b/tests/init_test.go @@ -14,6 +14,9 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . +//go:build integration +// +build integration + package tests import ( diff --git a/tests/state_test.go b/tests/state_test.go index d2c92b211c..8fcf35b864 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -14,6 +14,9 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . +//go:build integration +// +build integration + package tests import ( diff --git a/tests/transaction_test.go b/tests/transaction_test.go index cb0f262318..1197eebe19 100644 --- a/tests/transaction_test.go +++ b/tests/transaction_test.go @@ -14,6 +14,9 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . +//go:build integration +// +build integration + package tests import ( From 63cd7a3273615575d57dd76c4db5546597037b3a Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 10:33:44 +0300 Subject: [PATCH 32/80] move integration ci --- .github/workflows/ci.yml | 5 +++- .github/workflows/test-integration.yml | 39 -------------------------- 2 files changed, 4 insertions(+), 40 deletions(-) delete mode 100644 .github/workflows/test-integration.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ba2cece0b..36fdc12f86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,4 +60,7 @@ jobs: run: make test - name: Data race tests - run: make test-race \ No newline at end of file + run: make test-race + + - name: test-integration + run: make test-integration \ No newline at end of file diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml deleted file mode 100644 index 93578062f2..0000000000 --- a/.github/workflows/test-integration.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Integration tests -on: - push: - branches: - - "**" - - "!master" - pull_request: - branches: - - master - types: [opened, synchronize, closed] -jobs: - tests: - if: (!(github.event.action == 'closed' && github.event.pull_request.merged != true)) - strategy: - matrix: - os: [ ubuntu-20.04, macos-11 ] # list of os: https://github.com/actions/virtual-environments - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v3 - - run: git submodule update --init --recursive --force - - uses: actions/setup-go@v3 - with: - go-version: 1.18.x - - name: Install dependencies on Linux - if: runner.os == 'Linux' - run: sudo apt update && sudo apt install build-essential - - - uses: actions/cache@v3 - with: - path: | - ~/.cache/go-build - ~/Library/Caches/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: ${{ runner.os }}-go- - - - name: test-integration - run: make test-integration From b43ebd5f96a0bc21930956acc3169a15d44092f0 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 10:53:35 +0300 Subject: [PATCH 33/80] fix build --- tests/block_test_util.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/block_test_util.go b/tests/block_test_util.go index fea4ee0b95..d28f3a1237 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -16,9 +16,6 @@ // Package tests implements execution of Ethereum JSON tests. -//go:build integration -// +build integration - package tests import ( From 3c2510a5af17ac8d81c9a40381a2da5d45a7ae4d Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 11:22:17 +0300 Subject: [PATCH 34/80] move integration ci --- tests/rlp_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/rlp_test.go b/tests/rlp_test.go index 79a1683eb2..dbca73efc6 100644 --- a/tests/rlp_test.go +++ b/tests/rlp_test.go @@ -14,6 +14,9 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . +//go:build integration +// +build integration + package tests import ( From 15900477fb7e139e9a30d5efdf880749c60324dd Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 14:05:02 +0300 Subject: [PATCH 35/80] linters --- .github/workflows/ci.yml | 1 + .golangci.yml | 86 +++++++++++++++++++++++++++++++++++++++- Makefile | 12 +++++- go.mod | 11 +++-- go.sum | 68 +++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36fdc12f86..4b71b413b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,7 @@ jobs: run: make all # TODO: make it work + # - name: Reproducible build test # run: | # make geth diff --git a/.golangci.yml b/.golangci.yml index 4950b98c21..14e0654ef0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,6 +8,8 @@ run: skip-dirs-use-default: true skip-files: - core/genesis_alloc.go + - gen_.*.go + - .*_gen.go linters: disable-all: true @@ -27,9 +29,70 @@ linters: linters-settings: gofmt: simplify: true + auto-fix: false goconst: min-len: 3 # minimum length of string constant - min-occurrences: 6 # minimum number of occurrences + min-occurrences: 2 # minimum number of occurrences + + gocritic: + # Which checks should be enabled; can't be combined with 'disabled-checks'; + # See https://go-critic.github.io/overview#checks-overview + # To check which checks are enabled run `GL_DEBUG=gocritic ./build/bin/golangci-lint run` + # By default list of stable checks is used. + enabled-checks: + - badLock + - filepathJoin + - sortSlice + - sprintfQuotedString + - syncMapLoadAndDelete + - weakCond + - boolExprSimplify + - httpNoBody + - ioutilDeprecated + - nestingReduce + - preferFilepathJoin + - redundantSprint + - stringConcatSimplify + - timeExprSimplify + - typeAssertChain + - yodaStyleExpr + - truncateCmp + - equalFold + - preferDecodeRune + - preferFprint + - preferStringWriter + - preferWriteByte + - sliceClear + #- ruleguard + + # Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty + disabled-checks: + - regexpMust + - exitAfterDefer + - dupBranchBody + - singleCaseSwitch + - unlambda + - captLocal + - commentFormatting + - ifElseChain + - importShadow + - builtinShadow + + # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks. + # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". + enabled-tags: + - performance + - diagnostic + - opinionated + - style + disabled-tags: + - experimental + govet: + disable: + - deepequalerrors + - fieldalignment + - shadow + - unsafeptr issues: exclude-rules: @@ -48,3 +111,24 @@ issues: - path: cmd/faucet/ linters: - deadcode + # Exclude some linters from running on tests files. + - path: test\.go + linters: + - gosec + - unused + - deadcode + - gocritic + - path: cmd/devp2p + linters: + - gosec + - unused + - deadcode + - gocritic + - path: metrics/sample\.go + linters: + - gosec + - gocritic + - path: p2p/simulations + linters: + - gosec + - gocritic diff --git a/Makefile b/Makefile index d23903faac..9bc9ec5919 100644 --- a/Makefile +++ b/Makefile @@ -66,8 +66,16 @@ test-integration: escape: cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out -lint: ## Run linters. - $(GORUN) build/ci.go lint +lint: + @./build/bin/golangci-lint run --config ./.golangci.yml + +lintci: + @echo "--> Running linter for code" + @./build/bin/golangci-lint run --config ./.golangci.yml + +lintci-deps: + rm -f ./build/bin/golangci-lint + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ./build/bin v1.46.0 clean: env GO111MODULE=on go clean -cache diff --git a/go.mod b/go.mod index edd6d6887a..6065c1a5d2 100644 --- a/go.mod +++ b/go.mod @@ -23,10 +23,12 @@ require ( github.com/fatih/color v1.7.0 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff + github.com/go-critic/go-critic v0.6.3 // indirect github.com/go-kit/kit v0.9.0 // indirect github.com/go-logfmt/logfmt v0.5.0 // indirect github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-stack/stack v1.8.0 + github.com/go-toolsmith/astcopy v1.0.1 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 github.com/golang/protobuf v1.5.2 github.com/golang/snappy v0.0.4 @@ -59,6 +61,8 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 github.com/prometheus/tsdb v0.7.1 + github.com/quasilyte/gogrep v0.0.0-20220429205452-5e2753ee08f9 // indirect + github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 github.com/ryanuber/columnize v2.1.2+incompatible @@ -72,12 +76,13 @@ require ( go.opentelemetry.io/otel v1.2.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0 go.opentelemetry.io/otel/sdk v1.2.0 - golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 + golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 + golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 golang.org/x/text v0.3.7 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba - golang.org/x/tools v0.1.0 + golang.org/x/tools v0.1.10 + golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect google.golang.org/grpc v1.42.0 google.golang.org/protobuf v1.27.1 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce diff --git a/go.sum b/go.sum index 19a6002886..d664628dac 100644 --- a/go.sum +++ b/go.sum @@ -162,6 +162,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= +github.com/go-critic/go-critic v0.6.3 h1:abibh5XYBTASawfTQ0rA7dVtQT+6KzpGqb/J+DxRDaw= +github.com/go-critic/go-critic v0.6.3/go.mod h1:c6b3ZP1MQ7o6lPR7Rv3lEf7pYQUmAcx8ABHgdZCQt/k= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -182,6 +184,25 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astcopy v1.0.1 h1:l09oBhAPyV74kLJ3ZO31iBU8htZGTwr9LTjuMCyL8go= +github.com/go-toolsmith/astcopy v1.0.1/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= +github.com/go-toolsmith/astequal v1.0.2 h1:+XvaV8zNxua+9+Oa4AHmgmpo4RYAbwr/qjNppLfX2yM= +github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= +github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -226,10 +247,13 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -419,6 +443,21 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= +github.com/quasilyte/go-ruleguard v0.3.16-0.20220213074421-6aa060fab41a h1:sWFavxtIctGrVs5SYZ5Ml1CvrDAs8Kf5kx2PI3C41dA= +github.com/quasilyte/go-ruleguard v0.3.16-0.20220213074421-6aa060fab41a/go.mod h1:VMX+OnnSw4LicdiEGtRSD/1X8kW7GuEscjYNr4cOIT4= +github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.16/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= +github.com/quasilyte/gogrep v0.0.0-20220429205452-5e2753ee08f9 h1:mEQjyqtrQ6eB7oW9Qm+5po33faQIbhWp3qfhxGYuHKc= +github.com/quasilyte/gogrep v0.0.0-20220429205452-5e2753ee08f9/go.mod h1:MsVMK2P94jAne/7vEaLCRmjmOL0aTGAkvVOVuT+UYww= +github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= @@ -477,7 +516,9 @@ github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xsleonard/go-merkle v1.1.0 h1:fHe1fuhJjGH22ZzVTAH0jqHLhTGhOq3wQjJN+8P0jQg= github.com/xsleonard/go-merkle v1.1.0/go.mod h1:cW4z+UZ/4f2n9IJgIiyDCdYguchoDyDAPmpuOWGxdGg= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= @@ -513,6 +554,9 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/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-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8= +golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -522,7 +566,10 @@ golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxT golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299 h1:zQpM52jfKHG6II1ISZY1ZcpygvuSFZpLwfluuF89XOg= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171 h1:DZhP7zSquENyG3Yb6ZpGqNEtgE8dfXhcLcheIF9RQHY= +golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -542,6 +589,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= 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.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -560,6 +610,7 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -570,6 +621,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -581,6 +636,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -622,8 +678,13 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -667,13 +728,20 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= From 64ad2f9eb158e3d82ed16eae4d0f5d104aba8da6 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 14:40:15 +0300 Subject: [PATCH 36/80] update linter list --- .golangci.yml | 64 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 14e0654ef0..d72bb83320 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,27 +12,63 @@ run: - .*_gen.go linters: - disable-all: true enable: - - deadcode - goconst - goimports - - gosimple - - govet - - ineffassign - misspell - # - staticcheck - unconvert - # - unused - - varcheck + - bodyclose + - containedctx + - contextcheck + - decorder + - durationcheck + - errchkjson + - errname + - errorlint + - exhaustive + - exportloopref + - gocognit + - gofmt + - gomnd + - gomoddirectives + - gosec + - makezero + - nestif + - nilerr + - nilnil + - noctx + #- nosprintfhostport # TODO: do we use IPv6? + - paralleltest + - prealloc + - predeclared + #- promlinter + #- revive + - tagliatelle + - tenv + - thelper + - tparallel + - unconvert + - unparam + - wsl linters-settings: gofmt: simplify: true auto-fix: false + goconst: min-len: 3 # minimum length of string constant min-occurrences: 2 # minimum number of occurrences + numbers: true + + goimports: + local-prefixes: github.com/ethereum/go-ethereum + + nestif: + min-complexity: 3 + + prealloc: + for-loops: true gocritic: # Which checks should be enabled; can't be combined with 'disabled-checks'; @@ -93,6 +129,18 @@ linters-settings: - fieldalignment - shadow - unsafeptr + check-shadowing: true + enable-all: true + settings: + printf: + # Run `go tool vet help printf` to see available settings for `printf` analyzer. + funcs: + - (github.com/ethereum/go-ethereum/log.Logger).Trace + - (github.com/ethereum/go-ethereum/log.Logger).Debug + - (github.com/ethereum/go-ethereum/log.Logger).Info + - (github.com/ethereum/go-ethereum/log.Logger).Warn + - (github.com/ethereum/go-ethereum/log.Logger).Error + - (github.com/ethereum/go-ethereum/log.Logger).Crit issues: exclude-rules: From 834c7741b40a10467f7eb62f29525851926652e3 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 15:21:21 +0300 Subject: [PATCH 37/80] only new issues --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b71b413b9..40483cbe73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,7 @@ jobs: version: v1.46 skip-pkg-cache: true skip-build-cache: true + only-new-issues: true - name: Test run: make test From cd4b40fffd1a1df589fdd3d076e0dd16dcede89f Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 15:26:55 +0300 Subject: [PATCH 38/80] test without linters --- .github/workflows/ci.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40483cbe73..f9b383a310 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,15 +49,6 @@ jobs: # echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1 # fi - - name: Lint - if: runner.os == 'Linux' - uses: golangci/golangci-lint-action@v3 - with: - version: v1.46 - skip-pkg-cache: true - skip-build-cache: true - only-new-issues: true - - name: Test run: make test @@ -65,4 +56,13 @@ jobs: run: make test-race - name: test-integration - run: make test-integration \ No newline at end of file + run: make test-integration + + - name: Lint + if: runner.os == 'Linux' + uses: golangci/golangci-lint-action@v3 + with: + version: v1.46 + skip-pkg-cache: true + skip-build-cache: true + only-new-issues: true \ No newline at end of file From 6a598b4e93fe8bf6f5b75643f4cd26dea5543b42 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 15:27:18 +0300 Subject: [PATCH 39/80] revert --- .github/workflows/ci.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9b383a310..40483cbe73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,15 +49,6 @@ jobs: # echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1 # fi - - name: Test - run: make test - - - name: Data race tests - run: make test-race - - - name: test-integration - run: make test-integration - - name: Lint if: runner.os == 'Linux' uses: golangci/golangci-lint-action@v3 @@ -65,4 +56,13 @@ jobs: version: v1.46 skip-pkg-cache: true skip-build-cache: true - only-new-issues: true \ No newline at end of file + only-new-issues: true + + - name: Test + run: make test + + - name: Data race tests + run: make test-race + + - name: test-integration + run: make test-integration \ No newline at end of file From 348f91e9f4339a1b96863d660b539ba920371ec4 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 15:31:10 +0300 Subject: [PATCH 40/80] more time for tests for data races --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9bc9ec5919..a59d443078 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ test: $(GOTEST) --timeout 5m -cover -coverprofile=cover.out test-race: - $(GOTEST) --timeout 5m -race + $(GOTEST) --timeout 15m -race test-integration: $(GOTEST) --timeout 30m -tags integration From 5458ac01cdb150fee94a8f70677708108b132129 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 15:41:02 +0300 Subject: [PATCH 41/80] fix --- .gitignore | 2 ++ Makefile | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ad4242c519..50328c8121 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ */**/*dapps* build/_vendor/pkg +cover.out + #* .#* *# diff --git a/Makefile b/Makefile index a59d443078..55c33ada33 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ PACKAGE = github.com/ethereum/go-ethereum GO_FLAGS += -trimpath -buildvcs=false GO_FLAGS += -ldflags "-X ${PACKAGE}/params.GitCommit=${GIT_COMMIT} -X ${PACKAGE}/params.GitBranch=${GIT_BRANCH} -X ${PACKAGE}/params.GitTag=${GIT_TAG}" -GOTEST = GODEBUG=cgocheck=0 go test $(GO_FLAGS) ./... -p 1 -shuffle=on +GOTEST = GODEBUG=cgocheck=0 go test $(GO_FLAGS) -p 1 ./... -shuffle=on bor: $(GORUN) build/ci.go install ./cmd/geth From b2b327eaf4d11a72fbeff11ff1984d7dc4c19ce8 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 15:47:18 +0300 Subject: [PATCH 42/80] ignore cmd tests --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 55c33ada33..eb129ee3c7 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ PACKAGE = github.com/ethereum/go-ethereum GO_FLAGS += -trimpath -buildvcs=false GO_FLAGS += -ldflags "-X ${PACKAGE}/params.GitCommit=${GIT_COMMIT} -X ${PACKAGE}/params.GitBranch=${GIT_BRANCH} -X ${PACKAGE}/params.GitTag=${GIT_TAG}" -GOTEST = GODEBUG=cgocheck=0 go test $(GO_FLAGS) -p 1 ./... -shuffle=on +GOTEST = GODEBUG=cgocheck=0 go test $(GO_FLAGS) -p 1 $$(go list ./... | grep -v go-ethereum/cmd/) -shuffle=on bor: $(GORUN) build/ci.go install ./cmd/geth From 7c6357ecf6f47e05a41e9831eacc89d1bb2cd061 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 16:18:56 +0300 Subject: [PATCH 43/80] group concurrency --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40483cbe73..ec4063a557 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,11 @@ on: branches: - master types: [opened, synchronize, closed] + +concurrency: + group: build-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: tests: if: (!(github.event.action == 'closed' && github.event.pull_request.merged != true)) From e36a54d60021a3845ce23d58580194f1cd0d9285 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 16:43:43 +0300 Subject: [PATCH 44/80] goleak --- Makefile | 3 +++ accounts/abi/bind/backends/simulated_test.go | 5 +++++ common/leak/ignore_list.go | 13 +++++++++++++ go.mod | 1 + go.sum | 7 +++++++ 5 files changed, 29 insertions(+) create mode 100644 common/leak/ignore_list.go diff --git a/Makefile b/Makefile index eb129ee3c7..608cd52f2c 100644 --- a/Makefile +++ b/Makefile @@ -77,6 +77,9 @@ lintci-deps: rm -f ./build/bin/golangci-lint curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ./build/bin v1.46.0 +goimports: + goimports -local "$(PACKAGE)" -w . + clean: env GO111MODULE=on go clean -cache rm -fr build/_workspace/pkg/ $(GOBIN)/* diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index 8a0cbe3357..7df1a823ec 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -27,10 +27,13 @@ import ( "testing" "time" + "go.uber.org/goleak" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/leak" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -38,6 +41,8 @@ import ( ) func TestSimulatedBackend(t *testing.T) { + defer goleak.VerifyNone(t, leak.IgnoreList()...) + var gasLimit uint64 = 8000029 key, _ := crypto.GenerateKey() // nolint: gosec auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) diff --git a/common/leak/ignore_list.go b/common/leak/ignore_list.go new file mode 100644 index 0000000000..adcadce274 --- /dev/null +++ b/common/leak/ignore_list.go @@ -0,0 +1,13 @@ +package leak + +import "go.uber.org/goleak" + +func IgnoreList() []goleak.Option { + return []goleak.Option { + goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache"), + goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).dispatch"), + goleak.IgnoreTopFunction("github.com/rjeczalik/notify._Cfunc_CFRunLoopRun"), + goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/metrics.(*meterArbiter).tick"), + goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/consensus/ethash.(*remoteSealer).loop"), + } +} \ No newline at end of file diff --git a/go.mod b/go.mod index 6065c1a5d2..e9c010d388 100644 --- a/go.mod +++ b/go.mod @@ -76,6 +76,7 @@ require ( go.opentelemetry.io/otel v1.2.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0 go.opentelemetry.io/otel/sdk v1.2.0 + go.uber.org/goleak v1.1.12 // indirect golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 diff --git a/go.sum b/go.sum index d664628dac..3aba63edb5 100644 --- a/go.sum +++ b/go.sum @@ -518,6 +518,7 @@ github.com/xsleonard/go-merkle v1.1.0 h1:fHe1fuhJjGH22ZzVTAH0jqHLhTGhOq3wQjJN+8P github.com/xsleonard/go-merkle v1.1.0/go.mod h1:cW4z+UZ/4f2n9IJgIiyDCdYguchoDyDAPmpuOWGxdGg= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= @@ -540,6 +541,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.opentelemetry.io/proto/otlp v0.10.0 h1:n7brgtEbDvXEgGyKKo8SobKT1e9FewlDtXzkVP5djoE= go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -618,6 +621,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -675,9 +679,11 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/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-20210420205809-ac73e9fd8988/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-20210510120138-977fb7262007/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-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -732,6 +738,7 @@ golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= From 2bac6ce45fea9a6bcffc689a944065779e31d056 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 17:09:36 +0300 Subject: [PATCH 45/80] remove shuffle for e2e --- .github/workflows/ci.yml | 6 +++--- Makefile | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec4063a557..c23dc68bf2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,8 +66,8 @@ jobs: - name: Test run: make test - - name: Data race tests - run: make test-race + #- name: Data race tests + # run: make test-race - name: test-integration - run: make test-integration \ No newline at end of file + run: make test-integration \ No newline at end of file diff --git a/Makefile b/Makefile index 608cd52f2c..389c1f3202 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,9 @@ PACKAGE = github.com/ethereum/go-ethereum GO_FLAGS += -trimpath -buildvcs=false GO_FLAGS += -ldflags "-X ${PACKAGE}/params.GitCommit=${GIT_COMMIT} -X ${PACKAGE}/params.GitBranch=${GIT_BRANCH} -X ${PACKAGE}/params.GitTag=${GIT_TAG}" -GOTEST = GODEBUG=cgocheck=0 go test $(GO_FLAGS) -p 1 $$(go list ./... | grep -v go-ethereum/cmd/) -shuffle=on +TESTALL = $$(go list ./... | grep -v go-ethereum/cmd/) +TESTE2E = ./tests/... +GOTEST = GODEBUG=cgocheck=0 go test $(GO_FLAGS) -p 1 bor: $(GORUN) build/ci.go install ./cmd/geth @@ -55,13 +57,13 @@ ios: @echo "Import \"$(GOBIN)/Geth.framework\" to use the library." test: - $(GOTEST) --timeout 5m -cover -coverprofile=cover.out + $(GOTEST) --timeout 5m -shuffle=on -cover -coverprofile=cover.out $(TESTALL) test-race: - $(GOTEST) --timeout 15m -race + $(GOTEST) --timeout 15m -race -shuffle=on $(TESTALL) test-integration: - $(GOTEST) --timeout 30m -tags integration + $(GOTEST) --timeout 30m -tags integration -count=1 $(TESTE2E) escape: cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out From ca19e0182d53f616c17c3a4738f2885a5921dd36 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Wed, 11 May 2022 17:11:59 +0300 Subject: [PATCH 46/80] fix --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 389c1f3202..5f6287dff5 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ test-race: $(GOTEST) --timeout 15m -race -shuffle=on $(TESTALL) test-integration: - $(GOTEST) --timeout 30m -tags integration -count=1 $(TESTE2E) + $(GOTEST) --timeout 30m -tags integration $(TESTE2E) escape: cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out From 9838fefd3a23a7799773a7c6c927d24b2a059b09 Mon Sep 17 00:00:00 2001 From: Jerry Date: Wed, 11 May 2022 14:02:13 -0700 Subject: [PATCH 47/80] Set default user to ubuntu in bor.service --- builder/files/bor.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/files/bor.service b/builder/files/bor.service index 6fe89a8f2d..28fda79814 100644 --- a/builder/files/bor.service +++ b/builder/files/bor.service @@ -24,7 +24,7 @@ # -miner.etherbase [VALIDATOR ADDRESS] \ # -mine Type=simple - User=root + User=ubuntu KillSignal=SIGINT TimeoutStopSec=120 From f0f113c0fcc6ce6f360f1e63b7e80fb19ec391d2 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Thu, 12 May 2022 15:25:59 +0300 Subject: [PATCH 48/80] run versus origin/master --- .golangci.yml | 6 +++++- Makefile | 4 ---- common/leak/ignore_list.go | 4 ++-- go.mod | 1 + go.sum | 3 +++ 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d72bb83320..7dc4fc37e3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -24,7 +24,6 @@ linters: - durationcheck - errchkjson - errname - - errorlint - exhaustive - exportloopref - gocognit @@ -50,6 +49,7 @@ linters: - unconvert - unparam - wsl + #- errorlint causes stack overflow. TODO: recheck after each golangci update linters-settings: gofmt: @@ -180,3 +180,7 @@ issues: linters: - gosec - gocritic + max-issues-per-linter: 0 + max-same-issues: 0 + #new: true + new-from-rev: origin/master \ No newline at end of file diff --git a/Makefile b/Makefile index 5f6287dff5..bce03bf5ef 100644 --- a/Makefile +++ b/Makefile @@ -71,10 +71,6 @@ escape: lint: @./build/bin/golangci-lint run --config ./.golangci.yml -lintci: - @echo "--> Running linter for code" - @./build/bin/golangci-lint run --config ./.golangci.yml - lintci-deps: rm -f ./build/bin/golangci-lint curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ./build/bin v1.46.0 diff --git a/common/leak/ignore_list.go b/common/leak/ignore_list.go index adcadce274..e43e1c0393 100644 --- a/common/leak/ignore_list.go +++ b/common/leak/ignore_list.go @@ -3,11 +3,11 @@ package leak import "go.uber.org/goleak" func IgnoreList() []goleak.Option { - return []goleak.Option { + return []goleak.Option{ goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).dispatch"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify._Cfunc_CFRunLoopRun"), goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/metrics.(*meterArbiter).tick"), goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/consensus/ethash.(*remoteSealer).loop"), } -} \ No newline at end of file +} diff --git a/go.mod b/go.mod index e9c010d388..5e3a8b81e9 100644 --- a/go.mod +++ b/go.mod @@ -60,6 +60,7 @@ require ( github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 + github.com/polyfloyd/go-errorlint v0.0.0-20220510153142-36539f2bdac3 // indirect github.com/prometheus/tsdb v0.7.1 github.com/quasilyte/gogrep v0.0.0-20220429205452-5e2753ee08f9 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect diff --git a/go.sum b/go.sum index 3aba63edb5..b5278c5112 100644 --- a/go.sum +++ b/go.sum @@ -429,6 +429,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE 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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polyfloyd/go-errorlint v0.0.0-20220510153142-36539f2bdac3 h1:GhmKVnwiethXkJVYqq/kdcw3+u2TIuhPwmHhB+ehpIQ= +github.com/polyfloyd/go-errorlint v0.0.0-20220510153142-36539f2bdac3/go.mod h1:KZy4xxPJyy88/gldCe5OdW6OQRtNO3EZE7hXzmnebgA= github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -689,6 +691,7 @@ golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5 golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/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-20211216021012-1d35b9e2eb4e/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-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= From 594c9ab23f74d9f53241e4efc5a683280a9fcc2a Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Thu, 12 May 2022 18:04:04 +0300 Subject: [PATCH 49/80] vs master --- .github/workflows/ci.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c23dc68bf2..0cb5167156 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,9 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - - run: git submodule update --init --recursive --force + - run: | + git submodule update --init --recursive --force + git fetch --no-tags --prune --depth=1 origin +refs/heads/master:refs/remotes/origin/master - uses: actions/setup-go@v3 with: go-version: 1.18.x @@ -54,14 +56,13 @@ jobs: # echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1 # fi + - name: Golang-ci install + if: runner.os == 'Linux' + run: make lintci-deps + - name: Lint if: runner.os == 'Linux' - uses: golangci/golangci-lint-action@v3 - with: - version: v1.46 - skip-pkg-cache: true - skip-build-cache: true - only-new-issues: true + run: make lint - name: Test run: make test From a57d21166a8e08a6d9c6a58a69e65e6914342bd8 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Thu, 12 May 2022 18:27:03 +0300 Subject: [PATCH 50/80] leaks --- .github/workflows/ci.yml | 10 ++++++---- common/leak/ignore_list.go | 8 ++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cb5167156..6060ca77cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,13 +25,19 @@ jobs: - run: | git submodule update --init --recursive --force git fetch --no-tags --prune --depth=1 origin +refs/heads/master:refs/remotes/origin/master + - uses: actions/setup-go@v3 with: go-version: 1.18.x + - name: Install dependencies on Linux if: runner.os == 'Linux' run: sudo apt update && sudo apt install build-essential + - name: Golang-ci install + if: runner.os == 'Linux' + run: make lintci-deps + - uses: actions/cache@v3 with: path: | @@ -56,10 +62,6 @@ jobs: # echo >&2 "Reproducible build broken"; cat bor1.sha256; cat bor2.sha256; exit 1 # fi - - name: Golang-ci install - if: runner.os == 'Linux' - run: make lintci-deps - - name: Lint if: runner.os == 'Linux' run: make lint diff --git a/common/leak/ignore_list.go b/common/leak/ignore_list.go index e43e1c0393..ed61342a06 100644 --- a/common/leak/ignore_list.go +++ b/common/leak/ignore_list.go @@ -4,10 +4,18 @@ import "go.uber.org/goleak" func IgnoreList() []goleak.Option { return []goleak.Option{ + // a list of goroutne leaks that goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).dispatch"), + goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*nonrecursiveTree).dispatch"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify._Cfunc_CFRunLoopRun"), + + // todo: this leaks should be fixed goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/metrics.(*meterArbiter).tick"), goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/consensus/ethash.(*remoteSealer).loop"), + goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core.(*BlockChain).updateFutureBlocks"), + goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core/state/snapshot.(*diskLayer).generate"), + goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/accounts/abi/bind/backends.nullSubscription.func1"), + goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/eth/filters.(*EventSystem).eventLoop"), } } From b05c336a831bc1e9466d90da7c70ab4183268bfb Mon Sep 17 00:00:00 2001 From: Evgeny Danilenko <6655321@bk.ru> Date: Thu, 12 May 2022 18:52:40 +0300 Subject: [PATCH 51/80] fmt --- common/leak/ignore_list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/leak/ignore_list.go b/common/leak/ignore_list.go index ed61342a06..4f0fe62e9b 100644 --- a/common/leak/ignore_list.go +++ b/common/leak/ignore_list.go @@ -4,7 +4,7 @@ import "go.uber.org/goleak" func IgnoreList() []goleak.Option { return []goleak.Option{ - // a list of goroutne leaks that + // a list of goroutne leaks that hard to fix due to external dependencies or too big refactoring needed goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).dispatch"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*nonrecursiveTree).dispatch"), From 39d943d22e7ffa31af1ebb65334cc7dab13242af Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 09:11:17 +0300 Subject: [PATCH 52/80] stable tests --- Makefile | 2 +- common/leak/ignore_list.go | 2 ++ metrics/sample_test.go | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bce03bf5ef..313fabb134 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) GIT_TAG ?= $(shell git describe --tags `git rev-list --tags="v*" --max-count=1`) PACKAGE = github.com/ethereum/go-ethereum -GO_FLAGS += -trimpath -buildvcs=false +GO_FLAGS += -buildvcs=false GO_FLAGS += -ldflags "-X ${PACKAGE}/params.GitCommit=${GIT_COMMIT} -X ${PACKAGE}/params.GitBranch=${GIT_BRANCH} -X ${PACKAGE}/params.GitTag=${GIT_TAG}" TESTALL = $$(go list ./... | grep -v go-ethereum/cmd/) diff --git a/common/leak/ignore_list.go b/common/leak/ignore_list.go index 4f0fe62e9b..56134dcabc 100644 --- a/common/leak/ignore_list.go +++ b/common/leak/ignore_list.go @@ -7,7 +7,9 @@ func IgnoreList() []goleak.Option { // a list of goroutne leaks that hard to fix due to external dependencies or too big refactoring needed goleak.IgnoreTopFunction("github.com/ethereum/go-ethereum/core.(*txSenderCacher).cache"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).dispatch"), + goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).internal"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*nonrecursiveTree).dispatch"), + goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*nonrecursiveTree).internal"), goleak.IgnoreTopFunction("github.com/rjeczalik/notify._Cfunc_CFRunLoopRun"), // todo: this leaks should be fixed diff --git a/metrics/sample_test.go b/metrics/sample_test.go index c9168d3e82..d675862e84 100644 --- a/metrics/sample_test.go +++ b/metrics/sample_test.go @@ -244,6 +244,7 @@ func TestUniformSampleIncludesTail(t *testing.T) { } func TestUniformSampleSnapshot(t *testing.T) { + rand.Seed(1) s := NewUniformSample(100) for i := 1; i <= 10000; i++ { s.Update(int64(i)) @@ -339,6 +340,9 @@ func TestUniformSampleConcurrentUpdateCount(t *testing.T) { if testing.Short() { t.Skip("skipping in short mode") } + + rand.Seed(1) + s := NewUniformSample(100) for i := 0; i < 100; i++ { s.Update(int64(i)) From 81ede2f6d25e52e3d3e1e195625046250e885793 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 09:25:37 +0300 Subject: [PATCH 53/80] where to run --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6060ca77cf..a7e78112c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: pull_request: branches: - master - types: [opened, synchronize, closed] + types: [closed] concurrency: group: build-${{ github.event.pull_request.number || github.ref }} @@ -15,7 +15,7 @@ concurrency: jobs: tests: - if: (!(github.event.action == 'closed' && github.event.pull_request.merged != true)) + if: (github.event.action != 'closed' || github.event.pull_request.merged == true) strategy: matrix: os: [ ubuntu-20.04, macos-11 ] # list of os: https://github.com/actions/virtual-environments From 485762a28d013d5c94be6daebf5f3cb2492748c9 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 09:35:31 +0300 Subject: [PATCH 54/80] where to run --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7e78112c2..fc170c3871 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,8 +6,7 @@ on: - "!master" pull_request: branches: - - master - types: [closed] + - "**" concurrency: group: build-${{ github.event.pull_request.number || github.ref }} From 3268c143cdbc8fc51668334e9955e86028896c51 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 09:36:02 +0300 Subject: [PATCH 55/80] where to run --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc170c3871..14cf78dfc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,8 @@ on: - "!master" pull_request: branches: - - "**" + - master + types: [synchronize, closed] concurrency: group: build-${{ github.event.pull_request.number || github.ref }} From 276e82b16c8e56ebbb15d7680d045da74c2aaba8 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 09:36:40 +0300 Subject: [PATCH 56/80] where to run1 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14cf78dfc1..03037bb2e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: - "!master" pull_request: branches: - - master + - "master" types: [synchronize, closed] concurrency: From a8a9229c341bbb3e984ac0016d744d3428bedc4d Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 09:37:23 +0300 Subject: [PATCH 57/80] where to run2 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03037bb2e3..ca4e9671fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: pull_request: branches: - "master" - types: [synchronize, closed] + types: [opened, synchronize, closed] concurrency: group: build-${{ github.event.pull_request.number || github.ref }} From 5a3eb08a57c64ee41c6ede4271dcfc1f290f15ce Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 09:38:43 +0300 Subject: [PATCH 58/80] where to run3 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca4e9671fa..2015b06777 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: pull_request: branches: - "master" - types: [opened, synchronize, closed] + types: [closed] concurrency: group: build-${{ github.event.pull_request.number || github.ref }} From 95bfcdc5f4a7af6576a4c520a8f7ca3da284286e Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 10:06:11 +0300 Subject: [PATCH 59/80] macos tests --- consensus/ethash/sealer_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/ethash/sealer_test.go b/consensus/ethash/sealer_test.go index c34e76aec2..a9e96af866 100644 --- a/consensus/ethash/sealer_test.go +++ b/consensus/ethash/sealer_test.go @@ -70,7 +70,7 @@ func TestRemoteNotify(t *testing.T) { if want := common.BytesToHash(target.Bytes()).Hex(); work[2] != want { t.Errorf("work packet target mismatch: have %s, want %s", work[2], want) } - case <-time.After(3 * time.Second): + case <-time.After(5 * time.Second): t.Fatalf("notification timed out") } } From e7870978744ffd675feeb1106a8d5ef4e63b7628 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Fri, 13 May 2022 18:41:27 +0300 Subject: [PATCH 60/80] restore codecov --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2015b06777..9ee76fca61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,4 +73,9 @@ jobs: # run: make test-race - name: test-integration - run: make test-integration \ No newline at end of file + run: make test-integration + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + with: + file: ./cover.out \ No newline at end of file From 52647fcd88ec4b92b76682359dc38dbac81a485e Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Mon, 16 May 2022 10:12:09 +0300 Subject: [PATCH 61/80] run on forked branches --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ee76fca61..59fa866165 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,11 +3,10 @@ on: push: branches: - "**" - - "!master" pull_request: branches: - - "master" - types: [closed] + - "**" + types: [opened, synchronize] concurrency: group: build-${{ github.event.pull_request.number || github.ref }} From 30dd11a183e0e06c92ca0fa3b081001af5de8b45 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Mon, 16 May 2022 10:35:57 +0300 Subject: [PATCH 62/80] run on forked branches --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59fa866165..79dba640ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,10 +3,13 @@ on: push: branches: - "**" + - "!main" pull_request: branches: - "**" - types: [opened, synchronize] + types: [opened, synchronize, closed] + + workflow_dispatch: concurrency: group: build-${{ github.event.pull_request.number || github.ref }} From 91559f39556f73cadfbd6984450f579d1f941603 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Mon, 16 May 2022 10:47:33 +0300 Subject: [PATCH 63/80] run on forked branches --- .github/workflows/ci.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79dba640ca..9d51c4f67b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,13 +3,6 @@ on: push: branches: - "**" - - "!main" - pull_request: - branches: - - "**" - types: [opened, synchronize, closed] - - workflow_dispatch: concurrency: group: build-${{ github.event.pull_request.number || github.ref }} From 8de6903eeeb4ca0afc9e16daa4a097a7cd267e54 Mon Sep 17 00:00:00 2001 From: Jerry Date: Mon, 16 May 2022 14:54:35 -0700 Subject: [PATCH 64/80] Implement and enable 'unlock' flag --- internal/cli/server/config.go | 32 +++++++++++++++++++++++ internal/cli/server/config_test.go | 7 +++++ internal/cli/server/testdata/password.txt | 2 ++ 3 files changed, 41 insertions(+) create mode 100644 internal/cli/server/testdata/password.txt diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index a5e255ad48..e74964606e 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -663,6 +663,25 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) { } } + // unlock accounts + if len(c.Accounts.Unlock) > 0 { + if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() { + return nil, fmt.Errorf("Account unlock with HTTP access is forbidden!") + } + ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + passwords, err := MakePasswordListFromFile(c.Accounts.PasswordFile) + if err != nil { + return nil, err + } + if len(passwords) < len(c.Accounts.Unlock) { + return nil, fmt.Errorf("Number of passwords provided (%v) is less than number of accounts (%v) to unlock", + len(passwords), len(c.Accounts.Unlock)) + } + for i, account := range c.Accounts.Unlock { + ks.Unlock(accounts.Account{Address: common.HexToAddress(account)}, passwords[i]) + } + } + // update for developer mode if c.Developer.Enabled { // Get a keystore @@ -990,3 +1009,16 @@ func Hostname() string { } return hostname } + +func MakePasswordListFromFile(path string) ([]string, error) { + text, err := ioutil.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("Failed to read password file: %v", err) + } + lines := strings.Split(string(text), "\n") + // Sanitise DOS line endings. + for i := range lines { + lines[i] = strings.TrimRight(lines[i], "\r") + } + return lines, nil +} diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go index 6f5f9ff97d..4e6f3ef499 100644 --- a/internal/cli/server/config_test.go +++ b/internal/cli/server/config_test.go @@ -153,3 +153,10 @@ func TestConfigBootnodesDefault(t *testing.T) { assert.Len(t, cfg.P2P.BootstrapNodes, 1) }) } + +func TestMakePasswordListFromFile(t *testing.T) { + t.Run("ReadPasswordFile", func(t *testing.T) { + result, _ := MakePasswordListFromFile("./testdata/password.txt") + assert.Equal(t, []string{"test1", "test2"}, result) + }) +} diff --git a/internal/cli/server/testdata/password.txt b/internal/cli/server/testdata/password.txt new file mode 100644 index 0000000000..1827ffa521 --- /dev/null +++ b/internal/cli/server/testdata/password.txt @@ -0,0 +1,2 @@ +test1 +test2 \ No newline at end of file From 3aaf6bc13e30771ff35bfcfd04759155c2e65939 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Tue, 17 May 2022 19:25:59 +0300 Subject: [PATCH 65/80] cherry-pick from Jerry's Chen branch --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d51c4f67b..fc2445e0f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,12 @@ name: CI -on: +=on: push: + branches: + - "master" + pull_request: branches: - "**" + types: [opened, synchronize] concurrency: group: build-${{ github.event.pull_request.number || github.ref }} From 2930d04428f649d93971e1ccad6e9a2c10665a13 Mon Sep 17 00:00:00 2001 From: Evgeny Danienko <6655321@bk.ru> Date: Tue, 17 May 2022 19:28:08 +0300 Subject: [PATCH 66/80] misspell --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc2445e0f4..7db530c346 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ name: CI -=on: +on: push: branches: - "master" From c02e2cbb935429003c5ef230631fcc3ed7a3e221 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 17 May 2022 17:07:14 -0700 Subject: [PATCH 67/80] Rename whitelist to requiredblocks --- docs/cli/bootnode.md | 2 +- docs/cli/server.md | 6 +++--- internal/cli/server/config.go | 22 +++++++++++----------- internal/cli/server/config_test.go | 8 ++++---- internal/cli/server/flags.go | 4 ++-- internal/cli/server/testdata/simple.hcl | 2 +- internal/cli/server/testdata/simple.json | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/cli/bootnode.md b/docs/cli/bootnode.md index 3e60252341..48e933a934 100644 --- a/docs/cli/bootnode.md +++ b/docs/cli/bootnode.md @@ -14,4 +14,4 @@ - ```save-key```: path to save the ecdsa private key -- ```dry-run``` \ No newline at end of file +- ```dry-run```: validates parameters and prints bootnode configurations, but does not start bootnode \ No newline at end of file diff --git a/docs/cli/server.md b/docs/cli/server.md index ba6f3389c5..beca2c2fde 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -18,7 +18,7 @@ The ```bor server``` command runs the Bor client. - ```gcmode```: Blockchain garbage collection mode ("full", "archive") -- ```whitelist```: Comma separated block number-to-hash mappings to enforce (=) +- ```requiredblocks```: Comma separated block number-to-hash mappings to enforce (=) - ```no-snapshot```: Disables the snapshot-database mode (default = false) @@ -72,7 +72,7 @@ The ```bor server``` command runs the Bor client. - ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys -- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain) +- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain) ### JsonRPC Options @@ -192,4 +192,4 @@ The ```bor server``` command runs the Bor client. - ```txpool.globalqueue```: Maximum number of non-executable transaction slots for all accounts -- ```txpool.lifetime```: Maximum amount of time non-executable transaction are queued +- ```txpool.lifetime```: Maximum amount of time non-executable transaction are queued \ No newline at end of file diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index a5e255ad48..9457a8a270 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -43,8 +43,8 @@ type Config struct { // Name, or identity of the node Name string `hcl:"name,optional"` - // Whitelist is a list of required (block number, hash) pairs to accept - Whitelist map[string]string `hcl:"whitelist,optional"` + // RequiredBlocks is a list of required (block number, hash) pairs to accept + RequiredBlocks map[string]string `hcl:"requiredblocks,optional"` // LogLevel is the level of the logs to put out LogLevel string `hcl:"log-level,optional"` @@ -380,11 +380,11 @@ type DeveloperConfig struct { func DefaultConfig() *Config { return &Config{ - Chain: "mainnet", - Name: Hostname(), - Whitelist: map[string]string{}, - LogLevel: "INFO", - DataDir: defaultDataDir(), + Chain: "mainnet", + Name: Hostname(), + RequiredBlocks: map[string]string{}, + LogLevel: "INFO", + DataDir: defaultDataDir(), P2P: &P2PConfig{ MaxPeers: 30, MaxPendPeers: 50, @@ -718,17 +718,17 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) { n.SnapDiscoveryURLs = c.P2P.Discovery.DNS } - // whitelist + // RequiredBlocks { n.PeerRequiredBlocks = map[uint64]common.Hash{} - for k, v := range c.Whitelist { + for k, v := range c.RequiredBlocks { number, err := strconv.ParseUint(k, 0, 64) if err != nil { - return nil, fmt.Errorf("invalid whitelist block number %s: %v", k, err) + return nil, fmt.Errorf("invalid required block number %s: %v", k, err) } var hash common.Hash if err = hash.UnmarshalText([]byte(v)); err != nil { - return nil, fmt.Errorf("invalid whitelist hash %s: %v", v, err) + return nil, fmt.Errorf("invalid required block hash %s: %v", v, err) } n.PeerRequiredBlocks[number] = hash } diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go index 6f5f9ff97d..6fedd09109 100644 --- a/internal/cli/server/config_test.go +++ b/internal/cli/server/config_test.go @@ -24,7 +24,7 @@ func TestConfigMerge(t *testing.T) { c0 := &Config{ Chain: "0", NoSnapshot: true, - Whitelist: map[string]string{ + RequiredBlocks: map[string]string{ "a": "b", }, TxPool: &TxPoolConfig{ @@ -40,7 +40,7 @@ func TestConfigMerge(t *testing.T) { } c1 := &Config{ Chain: "1", - Whitelist: map[string]string{ + RequiredBlocks: map[string]string{ "b": "c", }, P2P: &P2PConfig{ @@ -55,7 +55,7 @@ func TestConfigMerge(t *testing.T) { expected := &Config{ Chain: "1", NoSnapshot: true, - Whitelist: map[string]string{ + RequiredBlocks: map[string]string{ "a": "b", "b": "c", }, @@ -104,7 +104,7 @@ func TestConfigLoadFile(t *testing.T) { assert.NoError(t, err) assert.Equal(t, config, &Config{ DataDir: "./data", - Whitelist: map[string]string{ + RequiredBlocks: map[string]string{ "a": "b", }, P2P: &P2PConfig{ diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index ce93e8c071..cc8f474ecd 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -45,9 +45,9 @@ func (c *Command) Flags() *flagset.Flagset { Value: &c.cliConfig.GcMode, }) f.MapStringFlag(&flagset.MapStringFlag{ - Name: "whitelist", + Name: "requiredblocks", Usage: "Comma separated block number-to-hash mappings to enforce (=)", - Value: &c.cliConfig.Whitelist, + Value: &c.cliConfig.RequiredBlocks, }) f.BoolFlag(&flagset.BoolFlag{ Name: "no-snapshot", diff --git a/internal/cli/server/testdata/simple.hcl b/internal/cli/server/testdata/simple.hcl index e276960e6d..5afc091859 100644 --- a/internal/cli/server/testdata/simple.hcl +++ b/internal/cli/server/testdata/simple.hcl @@ -1,6 +1,6 @@ data-dir = "./data" -whitelist = { +requiredblocks = { a = "b" } diff --git a/internal/cli/server/testdata/simple.json b/internal/cli/server/testdata/simple.json index 277f05d105..6270ee6d13 100644 --- a/internal/cli/server/testdata/simple.json +++ b/internal/cli/server/testdata/simple.json @@ -1,6 +1,6 @@ { "data-dir": "./data", - "whitelist": { + "requiredblocks": { "a": "b" }, "p2p": { From 1b530440550fcfeb9fac2c81f7f949667650d1d9 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Mon, 23 May 2022 14:06:51 +0530 Subject: [PATCH 68/80] internal/cli/server, eth: add option to disable personal wallet endpoints (#394) * initial disable-bor-wallet implementation * fixes and enhancements * update docs using clidoc * fixes in clique auth --- docs/cli/server.md | 2 + eth/backend.go | 53 ++++++++++------ internal/cli/server/config.go | 12 +++- internal/cli/server/flags.go | 5 ++ internal/cli/server/server.go | 114 +++++++++++++++++++++++++++------- 5 files changed, 144 insertions(+), 42 deletions(-) diff --git a/docs/cli/server.md b/docs/cli/server.md index ba6f3389c5..f730d1b5f7 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -36,6 +36,8 @@ The ```bor server``` command runs the Bor client. - ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions +- ```disable-bor-wallet```: Disable the personal wallet endpoints + - ```grpc.addr```: Address and port to bind the GRPC server - ```dev```: Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled diff --git a/eth/backend.go b/eth/backend.go index 05d6c5c927..f40e011f8d 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -82,6 +82,7 @@ type Ethereum struct { eventMux *event.TypeMux engine consensus.Engine accountManager *accounts.Manager + authorized bool // If consensus engine is authorized with keystore bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports @@ -153,6 +154,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { chainDb: chainDb, eventMux: stack.EventMux(), accountManager: stack.AccountManager(), + authorized: false, engine: nil, closeBloomHandler: make(chan struct{}), networkID: config.NetworkId, @@ -485,29 +487,34 @@ func (s *Ethereum) StartMining(threads int) error { log.Error("Cannot start mining without etherbase", "err", err) return fmt.Errorf("etherbase missing: %v", err) } - var cli *clique.Clique - if c, ok := s.engine.(*clique.Clique); ok { - cli = c - } else if cl, ok := s.engine.(*beacon.Beacon); ok { - if c, ok := cl.InnerEngine().(*clique.Clique); ok { + + // If personal endpoints are disabled, the server creating + // this Ethereum instance has already Authorized consensus. + if !s.authorized { + var cli *clique.Clique + if c, ok := s.engine.(*clique.Clique); ok { cli = c + } else if cl, ok := s.engine.(*beacon.Beacon); ok { + if c, ok := cl.InnerEngine().(*clique.Clique); ok { + cli = c + } } - } - if cli != nil { - wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) - if wallet == nil || err != nil { - log.Error("Etherbase account unavailable locally", "err", err) - return fmt.Errorf("signer missing: %v", err) + if cli != nil { + wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) + if wallet == nil || err != nil { + log.Error("Etherbase account unavailable locally", "err", err) + return fmt.Errorf("signer missing: %v", err) + } + cli.Authorize(eb, wallet.SignData) } - cli.Authorize(eb, wallet.SignData) - } - if bor, ok := s.engine.(*bor.Bor); ok { - wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) - if wallet == nil || err != nil { - log.Error("Etherbase account unavailable locally", "err", err) - return fmt.Errorf("signer missing: %v", err) + if bor, ok := s.engine.(*bor.Bor); ok { + wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) + if wallet == nil || err != nil { + log.Error("Etherbase account unavailable locally", "err", err) + return fmt.Errorf("signer missing: %v", err) + } + bor.Authorize(eb, wallet.SignData) } - bor.Authorize(eb, wallet.SignData) } // If mining is started, we can disable the transaction rejection mechanism // introduced to speed sync times. @@ -553,6 +560,14 @@ func (s *Ethereum) SyncMode() downloader.SyncMode { return mode } +// SetAuthorized sets the authorized bool variable +// denoting that consensus has been authorized while creation +func (s *Ethereum) SetAuthorized(authorized bool) { + s.lock.Lock() + s.authorized = authorized + s.lock.Unlock() +} + // Protocols returns all the currently configured // network protocols to start. func (s *Ethereum) Protocols() []p2p.Protocol { diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index e74964606e..5a0d44c115 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -368,6 +368,9 @@ type AccountsConfig struct { // UseLightweightKDF enables a faster but less secure encryption of accounts UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"` + + // DisableBorWallet disables the personal wallet endpoints + DisableBorWallet bool `hcl:"disable-bor-wallet,optional"` } type DeveloperConfig struct { @@ -496,6 +499,7 @@ func DefaultConfig() *Config { PasswordFile: "", AllowInsecureUnlock: false, UseLightweightKDF: false, + DisableBorWallet: false, }, GRPC: &GRPCConfig{ Addr: ":3131", @@ -611,7 +615,7 @@ func (c *Config) loadChain() error { return nil } -func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) { +func (c *Config) buildEth(accountManager *accounts.Manager) (*ethconfig.Config, error) { dbHandles, err := makeDatabaseHandles() if err != nil { return nil, err @@ -686,7 +690,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) { if c.Developer.Enabled { // Get a keystore var ks *keystore.KeyStore - if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { + if keystores := accountManager.Backends(keystore.KeyStoreType); len(keystores) > 0 { ks = keystores[0].(*keystore.KeyStore) } @@ -712,6 +716,10 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) { } log.Info("Using developer account", "address", developer.Address) + // Set the Etherbase + c.Sealer.Etherbase = developer.Address.Hex() + n.Miner.Etherbase = developer.Address + // get developer mode chain config c.chain = chains.GetDeveloperChain(c.Developer.Period, developer.Address) diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index ce93e8c071..62bc534dac 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -530,6 +530,11 @@ func (c *Command) Flags() *flagset.Flagset { Value: &c.cliConfig.Accounts.UseLightweightKDF, Group: "Account Management", }) + f.BoolFlag((&flagset.BoolFlag{ + Name: "disable-bor-wallet", + Usage: "Disable the personal wallet endpoints", + Value: &c.cliConfig.Accounts.DisableBorWallet, + })) // grpc f.StringFlag(&flagset.StringFlag{ diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go index 5d3d307d2a..6b4e7ed4da 100644 --- a/internal/cli/server/server.go +++ b/internal/cli/server/server.go @@ -10,7 +10,11 @@ import ( "strings" "time" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/consensus/beacon" + "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/ethstats" @@ -67,50 +71,115 @@ func NewServer(config *Config) (*Server, error) { if err != nil { return nil, err } - srv.node = stack // setup account manager (only keystore) - { - keydir := stack.KeyStoreDir() - n, p := keystore.StandardScryptN, keystore.StandardScryptP - if config.Accounts.UseLightweightKDF { - n, p = keystore.LightScryptN, keystore.LightScryptP - } - stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p)) + // create a new account manager, only for the scope of this function + accountManager := accounts.NewManager(&accounts.Config{}) + + // register backend to account manager with keystore for signing + keydir := stack.KeyStoreDir() + n, p := keystore.StandardScryptN, keystore.StandardScryptP + if config.Accounts.UseLightweightKDF { + n, p = keystore.LightScryptN, keystore.LightScryptP } - // register the ethereum backend - ethCfg, err := config.buildEth(stack) - if err != nil { - return nil, err - } + // proceed to authorize the local account manager in any case + accountManager.AddBackend(keystore.NewKeyStore(keydir, n, p)) - backend, err := eth.New(stack, ethCfg) - if err != nil { - return nil, err + // flag to set if we're authorizing consensus here + authorized := false + + // check if personal wallet endpoints are disabled or not + if !config.Accounts.DisableBorWallet { + // add keystore globally to the node's account manager if personal wallet is enabled + stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p)) + + // register the ethereum backend + ethCfg, err := config.buildEth(stack.AccountManager()) + if err != nil { + return nil, err + } + backend, err := eth.New(stack, ethCfg) + if err != nil { + return nil, err + } + srv.backend = backend + } else { + // register the ethereum backend (with temporary created account manager) + ethCfg, err := config.buildEth(accountManager) + if err != nil { + return nil, err + } + backend, err := eth.New(stack, ethCfg) + if err != nil { + return nil, err + } + srv.backend = backend + + // authorize only if mining or in developer mode + if config.Sealer.Enabled || config.Developer.Enabled { + // get the etherbase + eb, err := srv.backend.Etherbase() + if err != nil { + log.Error("Cannot start mining without etherbase", "err", err) + return nil, fmt.Errorf("etherbase missing: %v", err) + } + + // Authorize the clique consensus (if chosen) to sign using wallet signer + var cli *clique.Clique + if c, ok := srv.backend.Engine().(*clique.Clique); ok { + cli = c + } else if cl, ok := srv.backend.Engine().(*beacon.Beacon); ok { + if c, ok := cl.InnerEngine().(*clique.Clique); ok { + cli = c + } + } + if cli != nil { + wallet, err := accountManager.Find(accounts.Account{Address: eb}) + if wallet == nil || err != nil { + log.Error("Etherbase account unavailable locally", "err", err) + return nil, fmt.Errorf("signer missing: %v", err) + } + cli.Authorize(eb, wallet.SignData) + authorized = true + } + + // Authorize the bor consensus (if chosen) to sign using wallet signer + if bor, ok := srv.backend.Engine().(*bor.Bor); ok { + wallet, err := accountManager.Find(accounts.Account{Address: eb}) + if wallet == nil || err != nil { + log.Error("Etherbase account unavailable locally", "err", err) + return nil, fmt.Errorf("signer missing: %v", err) + } + bor.Authorize(eb, wallet.SignData) + authorized = true + } + } } - srv.backend = backend + + // set the auth status in backend + srv.backend.SetAuthorized(authorized) // debug tracing is enabled by default - stack.RegisterAPIs(tracers.APIs(backend.APIBackend)) + stack.RegisterAPIs(tracers.APIs(srv.backend.APIBackend)) // graphql is started from another place if config.JsonRPC.Graphql.Enabled { - if err := graphql.New(stack, backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.VHost); err != nil { + if err := graphql.New(stack, srv.backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.VHost); err != nil { return nil, fmt.Errorf("failed to register the GraphQL service: %v", err) } } // register ethash service if config.Ethstats != "" { - if err := ethstats.New(stack, backend.APIBackend, backend.Engine(), config.Ethstats); err != nil { + if err := ethstats.New(stack, srv.backend.APIBackend, srv.backend.Engine(), config.Ethstats); err != nil { return nil, err } } // sealing (if enabled) or in dev mode if config.Sealer.Enabled || config.Developer.Enabled { - if err := backend.StartMining(1); err != nil { + if err := srv.backend.StartMining(1); err != nil { return nil, err } } @@ -119,6 +188,9 @@ func NewServer(config *Config) (*Server, error) { return nil, err } + // Set the node instance + srv.node = stack + // start the node if err := srv.node.Start(); err != nil { return nil, err From 2323f2c96e5a198a24e08de5c09e3b58825e5887 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Mon, 23 May 2022 15:27:35 +0530 Subject: [PATCH 69/80] fix: modify build eth fn definition for account unlock handling (#412) --- internal/cli/server/config.go | 8 ++++---- internal/cli/server/config_test.go | 2 +- internal/cli/server/server.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 5a0d44c115..3e9a5a9c77 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -615,7 +615,7 @@ func (c *Config) loadChain() error { return nil } -func (c *Config) buildEth(accountManager *accounts.Manager) (*ethconfig.Config, error) { +func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (*ethconfig.Config, error) { dbHandles, err := makeDatabaseHandles() if err != nil { return nil, err @@ -670,15 +670,15 @@ func (c *Config) buildEth(accountManager *accounts.Manager) (*ethconfig.Config, // unlock accounts if len(c.Accounts.Unlock) > 0 { if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() { - return nil, fmt.Errorf("Account unlock with HTTP access is forbidden!") + return nil, fmt.Errorf("account unlock with HTTP access is forbidden") } - ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + ks := accountManager.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) passwords, err := MakePasswordListFromFile(c.Accounts.PasswordFile) if err != nil { return nil, err } if len(passwords) < len(c.Accounts.Unlock) { - return nil, fmt.Errorf("Number of passwords provided (%v) is less than number of accounts (%v) to unlock", + return nil, fmt.Errorf("number of passwords provided (%v) is less than number of accounts (%v) to unlock", len(passwords), len(c.Accounts.Unlock)) } for i, account := range c.Accounts.Unlock { diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go index 4e6f3ef499..d83182af88 100644 --- a/internal/cli/server/config_test.go +++ b/internal/cli/server/config_test.go @@ -16,7 +16,7 @@ func TestConfigDefault(t *testing.T) { _, err := config.buildNode() assert.NoError(t, err) - _, err = config.buildEth(nil) + _, err = config.buildEth(nil, nil) assert.NoError(t, err) } diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go index 6b4e7ed4da..371e588d02 100644 --- a/internal/cli/server/server.go +++ b/internal/cli/server/server.go @@ -95,7 +95,7 @@ func NewServer(config *Config) (*Server, error) { stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p)) // register the ethereum backend - ethCfg, err := config.buildEth(stack.AccountManager()) + ethCfg, err := config.buildEth(stack, stack.AccountManager()) if err != nil { return nil, err } @@ -106,7 +106,7 @@ func NewServer(config *Config) (*Server, error) { srv.backend = backend } else { // register the ethereum backend (with temporary created account manager) - ethCfg, err := config.buildEth(accountManager) + ethCfg, err := config.buildEth(stack, accountManager) if err != nil { return nil, err } From 12ab0f0240625f890355d4c29d523bbfeafc7478 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 19 May 2022 17:55:23 -0700 Subject: [PATCH 70/80] Lint consensus/bor module Cleanup, lint, and enable linters for consenssus/bor module. Disabled linter "gomnd" and "tagliatelle" because they are not easy to fix and the return on the time investment is very low. Disabled linter "prealloc" because it is not easy to guess and pre-allocate the slice accurately in many cases. --- .github/workflows/ci.yml | 2 +- .golangci.yml | 10 +- Makefile | 4 +- consensus/bor/api.go | 42 +++++++- consensus/bor/bor.go | 123 +++++++++++++++++----- consensus/bor/bor_test.go | 7 +- consensus/bor/clerk.go | 2 +- consensus/bor/genesis_contracts_client.go | 10 ++ consensus/bor/merkle.go | 16 +-- consensus/bor/rest.go | 14 ++- consensus/bor/snapshot.go | 24 +++-- consensus/bor/snapshot_test.go | 22 ++++ consensus/bor/validator.go | 9 ++ consensus/bor/validator_set.go | 76 ++++++++++--- 14 files changed, 291 insertions(+), 70 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7db530c346..72647b56eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: pull_request: branches: - "**" - types: [opened, synchronize] + types: [opened, synchronize, edited] concurrency: group: build-${{ github.event.pull_request.number || github.ref }} diff --git a/.golangci.yml b/.golangci.yml index 7dc4fc37e3..daea4e1e0b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -28,7 +28,7 @@ linters: - exportloopref - gocognit - gofmt - - gomnd + # - gomnd - gomoddirectives - gosec - makezero @@ -38,11 +38,11 @@ linters: - noctx #- nosprintfhostport # TODO: do we use IPv6? - paralleltest - - prealloc + # - prealloc - predeclared #- promlinter #- revive - - tagliatelle + # - tagliatelle - tenv - thelper - tparallel @@ -65,7 +65,7 @@ linters-settings: local-prefixes: github.com/ethereum/go-ethereum nestif: - min-complexity: 3 + min-complexity: 5 prealloc: for-loops: true @@ -183,4 +183,4 @@ issues: max-issues-per-linter: 0 max-same-issues: 0 #new: true - new-from-rev: origin/master \ No newline at end of file + # new-from-rev: origin/master \ No newline at end of file diff --git a/Makefile b/Makefile index b82757e7fb..53b3cd9fdb 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,9 @@ escape: cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out lint: - @./build/bin/golangci-lint run --config ./.golangci.yml + @./build/bin/golangci-lint run --config ./.golangci.yml \ + internal/cli \ + consensus/bor lintci-deps: rm -f ./build/bin/golangci-lint diff --git a/consensus/bor/api.go b/consensus/bor/api.go index 8f172e47a6..361e439bf7 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" + lru "github.com/hashicorp/golang-lru" "github.com/xsleonard/go-merkle" "golang.org/x/crypto/sha3" @@ -44,6 +45,7 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { if header == nil { return nil, errUnknownBlock } + return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) } @@ -59,11 +61,11 @@ type difficultiesKV struct { } func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV { - var ss []difficultiesKV for k, v := range values { ss = append(ss, difficultiesKV{k, v}) } + sort.Slice(ss, func(i, j int) bool { return ss[i].Difficulty > ss[j].Difficulty }) @@ -74,11 +76,15 @@ func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV { // GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) { snapNumber := *number - 1 + var difficulties = make(map[common.Address]uint64) + snap, err := api.GetSnapshot(&snapNumber) + if err != nil { return BlockSigners{}, err } + proposer := snap.ValidatorSet.GetProposer().Address proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer) @@ -88,6 +94,7 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne if tempIndex < proposerIndex { tempIndex = tempIndex + len(signers) } + difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex)) } @@ -97,6 +104,7 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne if err != nil { return BlockSigners{}, err } + diff := int(difficulties[*author]) blockSigners := &BlockSigners{ Signers: rankedDifficulties, @@ -111,9 +119,11 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne func (api *API) GetSnapshotProposer(number *rpc.BlockNumber) (common.Address, error) { *number -= 1 snap, err := api.GetSnapshot(number) + if err != nil { return common.Address{}, err } + return snap.ValidatorSet.GetProposer().Address, nil } @@ -130,7 +140,9 @@ func (api *API) GetAuthor(number *rpc.BlockNumber) (*common.Address, error) { if header == nil { return nil, errUnknownBlock } + author, err := api.bor.Author(header) + return &author, err } @@ -140,6 +152,7 @@ func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) { if header == nil { return nil, errUnknownBlock } + return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) } @@ -156,10 +169,13 @@ func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) { if header == nil { return nil, errUnknownBlock } + snap, err := api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) + if err != nil { return nil, err } + return snap.signers(), nil } @@ -169,10 +185,13 @@ func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) { if header == nil { return nil, errUnknownBlock } + snap, err := api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) + if err != nil { return nil, err } + return snap.signers(), nil } @@ -182,6 +201,7 @@ func (api *API) GetCurrentProposer() (common.Address, error) { if err != nil { return common.Address{}, err } + return snap.ValidatorSet.GetProposer().Address, nil } @@ -191,6 +211,7 @@ func (api *API) GetCurrentValidators() ([]*Validator, error) { if err != nil { return make([]*Validator, 0), err } + return snap.ValidatorSet.Validators, nil } @@ -199,26 +220,36 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) { if err := api.initializeRootHashCache(); err != nil { return "", err } + key := getRootHashKey(start, end) + if root, known := api.rootHashCache.Get(key); known { return root.(string), nil } - length := uint64(end - start + 1) + + length := end - start + 1 + if length > MaxCheckpointLength { return "", &MaxCheckpointLengthExceededError{start, end} } + currentHeaderNumber := api.chain.CurrentHeader().Number.Uint64() + if start > end || end > currentHeaderNumber { return "", &InvalidStartEndBlockError{start, end, currentHeaderNumber} } + blockHeaders := make([]*types.Header, end-start+1) wg := new(sync.WaitGroup) concurrent := make(chan bool, 20) + for i := start; i <= end; i++ { wg.Add(1) concurrent <- true + go func(number uint64) { - blockHeaders[number-start] = api.chain.GetHeaderByNumber(uint64(number)) + blockHeaders[number-start] = api.chain.GetHeaderByNumber(number) + <-concurrent wg.Done() }(i) @@ -227,6 +258,7 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) { close(concurrent) headers := make([][32]byte, nextPowerOfTwo(length)) + for i := 0; i < len(blockHeaders); i++ { blockHeader := blockHeaders[i] header := crypto.Keccak256(appendBytes32( @@ -237,6 +269,7 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) { )) var arr [32]byte + copy(arr[:], header) headers[i] = arr } @@ -245,8 +278,10 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) { if err := tree.Generate(convert(headers), sha3.NewLegacyKeccak256()); err != nil { return "", err } + root := hex.EncodeToString(tree.Root().Hash) api.rootHashCache.Add(key, root) + return root, nil } @@ -255,6 +290,7 @@ func (api *API) initializeRootHashCache() error { if api.rootHashCache == nil { api.rootHashCache, err = lru.NewARC(10) } + return err } diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 2623011d79..ada601f838 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -32,7 +32,6 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -56,9 +55,6 @@ var ( uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. - diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures - diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures - validatorHeaderBytesLength = common.AddressLength + 20 // address + power systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") ) @@ -72,18 +68,6 @@ var ( // that is not part of the local blockchain. errUnknownBlock = errors.New("unknown block") - // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition - // block has a beneficiary set to non-zeroes. - errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero") - - // errInvalidVote is returned if a nonce value is something else that the two - // allowed constants of 0x00..0 or 0xff..f. - errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f") - - // errInvalidCheckpointVote is returned if a checkpoint/epoch transition block - // has a vote nonce set to non-zeroes. - errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero") - // errMissingVanity is returned if a block's extra-data section is shorter than // 32 bytes, which is required to store the signer vanity. errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") @@ -136,6 +120,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache, c *params.BorConfig if len(header.Extra) < extraSeal { return common.Address{}, errMissingSignature } + signature := header.Extra[len(header.Extra)-extraSeal:] // Recover the public key and the Ethereum address @@ -143,10 +128,13 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache, c *params.BorConfig if err != nil { return common.Address{}, err } + var signer common.Address + copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) sigcache.Add(hash, signer) + return signer, nil } @@ -155,6 +143,7 @@ func SealHash(header *types.Header, c *params.BorConfig) (hash common.Hash) { hasher := sha3.NewLegacyKeccak256() encodeSigHeader(hasher, header, c) hasher.Sum(hash[:0]) + return hash } @@ -176,11 +165,13 @@ func encodeSigHeader(w io.Writer, header *types.Header, c *params.BorConfig) { header.MixDigest, header.Nonce, } + if c.IsJaipur(header.Number.Uint64()) { if header.BaseFee != nil { enc = append(enc, header.BaseFee) } } + if err := rlp.Encode(w, enc); err != nil { panic("can't encode: " + err.Error()) } @@ -194,9 +185,11 @@ func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint6 if number%c.Sprint == 0 { delay = c.ProducerDelay } + if succession > 0 { delay += uint64(succession) * c.CalculateBackupMultiplier(number) } + return delay } @@ -210,6 +203,7 @@ func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint6 func BorRLP(header *types.Header, c *params.BorConfig) []byte { b := new(bytes.Buffer) encodeSigHeader(b, header, c) + return b.Bytes() } @@ -233,7 +227,6 @@ type Bor struct { HeimdallClient IHeimdallClient WithoutHeimdall bool - scope event.SubscriptionScope // The fields below are for testing only fakeDiff bool // Skip difficulty verifications } @@ -314,6 +307,7 @@ func (c *Bor) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types. } } }() + return abort, results } @@ -325,6 +319,7 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head if header.Number == nil { return errUnknownBlock } + number := header.Number.Uint64() // Don't waste time checking blocks from the future @@ -344,32 +339,40 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head if !isSprintEnd && signersBytes != 0 { return errExtraValidators } + if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 { return errInvalidSpanValidators } + // Ensure that the mix digest is zero as we don't have fork protection currently if header.MixDigest != (common.Hash{}) { return errInvalidMixDigest } + // Ensure that the block doesn't contain any uncles which are meaningless in PoA if header.UncleHash != uncleHash { return errInvalidUncleHash } + // Ensure that the block's difficulty is meaningful (may not be correct at this point) if number > 0 { if header.Difficulty == nil { return errInvalidDifficulty } } + // Verify that the gas limit is <= 2^63-1 - cap := uint64(0x7fffffffffffffff) - if header.GasLimit > cap { - return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap) + gasCap := uint64(0x7fffffffffffffff) + + if header.GasLimit > gasCap { + return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, gasCap) } + // If all checks passed, validate any special fields for hard forks if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil { return err } + // All basic checks passed, verify cascading fields return c.verifyCascadingFields(chain, header, parents) } @@ -380,9 +383,11 @@ func validateHeaderExtraField(extraBytes []byte) error { if len(extraBytes) < extraVanity { return errMissingVanity } + if len(extraBytes) < extraVanity+extraSeal { return errMissingSignature } + return nil } @@ -393,12 +398,14 @@ func validateHeaderExtraField(extraBytes []byte) error { func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { // The genesis block is the always valid dead-end number := header.Number.Uint64() + if number == 0 { return nil } // Ensure that the block's timestamp isn't too close to it's parent var parent *types.Header + if len(parents) > 0 { parent = parents[len(parents)-1] } else { @@ -413,11 +420,13 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t if header.GasUsed > header.GasLimit { return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) } + if !chain.Config().IsLondon(header.Number) { // Verify BaseFee not present before EIP-1559 fork. if header.BaseFee != nil { return fmt.Errorf("invalid baseFee before fork: have %d, want ", header.BaseFee) } + if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { return err } @@ -432,6 +441,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t // Retrieve the snapshot needed to verify this header and cache it snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) + if err != nil { return err } @@ -444,6 +454,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t currentValidators := snap.ValidatorSet.Copy().Validators // sort validator by address sort.Sort(ValidatorsByAddress(currentValidators)) + for i, validator := range currentValidators { copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes()) } @@ -458,6 +469,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t } // snapshot retrieves the authorization snapshot at a given point in time. +// nolint: gocognit func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { // Search for a snapshot in memory or on disk for checkpoints var ( @@ -465,10 +477,12 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co snap *Snapshot ) + //nolint:govet for snap == nil { // If an in-memory snapshot was found, use that if s, ok := c.recents.Get(hash); ok { snap = s.(*Snapshot) + break } @@ -476,7 +490,9 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co if number%checkpointInterval == 0 { if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil { log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) + snap = s + break } } @@ -486,6 +502,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co // up more headers than allowed to be reorged (chain reinit from a freezer), // consider the checkpoint trusted and snapshot it. // TODO fix this + // nolint:nestif if number == 0 { checkpoint := chain.GetHeaderByNumber(number) if checkpoint != nil { @@ -503,7 +520,9 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co if err := snap.store(c.db); err != nil { return nil, err } + log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) + break } } @@ -516,6 +535,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co if header.Hash() != hash || header.Number.Uint64() != number { return nil, consensus.ErrUnknownAncestor } + parents = parents[:len(parents)-1] } else { // No explicit parents (or no more left), reach out to the database @@ -524,6 +544,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co return nil, consensus.ErrUnknownAncestor } } + headers = append(headers, header) number, hash = number-1, header.ParentHash } @@ -542,6 +563,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co if err != nil { return nil, err } + c.recents.Add(snap.Hash, snap) // If we've generated a new checkpoint snapshot, save to disk @@ -549,8 +571,10 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co if err = snap.store(c.db); err != nil { return nil, err } + log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash) } + return snap, err } @@ -560,6 +584,7 @@ func (c *Bor) VerifyUncles(chain consensus.ChainReader, block *types.Block) erro if len(block.Uncles()) > 0 { return errors.New("uncles not allowed") } + return nil } @@ -590,6 +615,7 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header if err != nil { return err } + if !snap.ValidatorSet.HasAddress(signer.Bytes()) { // Check the UnauthorizedSignerError.Error() msg to see why we pass number-1 return &UnauthorizedSignerError{number - 1, signer.Bytes()} @@ -643,6 +669,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e if len(header.Extra) < extraVanity { header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) } + header.Extra = header.Extra[:extraVanity] // get validator set if number @@ -654,6 +681,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e // sort validator by address sort.Sort(ValidatorsByAddress(newValidators)) + for _, validator := range newValidators { header.Extra = append(header.Extra, validator.HeaderBytes()...) } @@ -673,7 +701,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e var succession int // if signer is not empty - if bytes.Compare(c.signer.Bytes(), common.Address{}.Bytes()) != 0 { + if !bytes.Equal(c.signer.Bytes(), common.Address{}.Bytes()) { succession, err = snap.GetSignerSuccessionNumber(c.signer) if err != nil { return err @@ -684,6 +712,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e if header.Time < uint64(time.Now().Unix()) { header.Time = uint64(time.Now().Unix()) } + return nil } @@ -693,7 +722,9 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, stateSyncData := []*types.StateSyncData{} var err error + headerNumber := header.Number.Uint64() + if headerNumber%c.config.Sprint == 0 { cx := chainContext{Chain: chain, Bor: c} // check and commit span @@ -728,13 +759,17 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, func decodeGenesisAlloc(i interface{}) (core.GenesisAlloc, error) { var alloc core.GenesisAlloc + b, err := json.Marshal(i) + if err != nil { return nil, err } + if err := json.Unmarshal(b, &alloc); err != nil { return nil, err } + return alloc, nil } @@ -745,12 +780,14 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.State if err != nil { return fmt.Errorf("failed to decode genesis alloc: %v", err) } + for addr, account := range allocs { log.Info("change contract code", "address", addr) state.SetCode(addr, account.Code) } } } + return nil } @@ -856,10 +893,12 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result if err != nil { return err } + copy(header.Extra[len(header.Extra)-extraSeal:], sighash) // Wait until sealing is terminated or delay timeout. log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) + go func() { select { case <-stop: @@ -874,6 +913,7 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result "in-turn-signer", snap.ValidatorSet.GetProposer().Address.Hex(), ) } + log.Info( "Sealing successful", "number", number, @@ -887,6 +927,7 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result log.Warn("Sealing result was not read by miner", "number", number, "sealhash", SealHash(header, c.config)) } }() + return nil } @@ -898,6 +939,7 @@ func (c *Bor) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, par if err != nil { return nil } + return new(big.Int).SetUint64(snap.Difficulty(c.signer)) } @@ -948,6 +990,7 @@ func (c *Bor) GetCurrentSpan(headerHash common.Hash) (*Span, error) { To: &toAddress, Data: &msgData, }, blockNr, nil) + if err != nil { return nil, err } @@ -998,15 +1041,16 @@ func (c *Bor) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ( To: &toAddress, Data: &msgData, }, blockNr, nil) + if err != nil { panic(err) - // return nil, err } var ( ret0 = new([]common.Address) ret1 = new([]*big.Int) ) + out := &[]interface{}{ ret0, ret1, @@ -1034,13 +1078,16 @@ func (c *Bor) checkAndCommitSpan( ) error { headerNumber := header.Number.Uint64() span, err := c.GetCurrentSpan(header.ParentHash) + if err != nil { return err } + if c.needToCommitSpan(span, headerNumber) { err := c.fetchAndCommitSpan(span.ID+1, state, header, chain) return err } + return nil } @@ -1072,10 +1119,11 @@ func (c *Bor) fetchAndCommitSpan( var heimdallSpan HeimdallSpan if c.WithoutHeimdall { - s, err := c.getNextHeimdallSpanForTest(newSpanID, state, header, chain) + s, err := c.getNextHeimdallSpanForTest(newSpanID, header, chain) if err != nil { return err } + heimdallSpan = *s } else { response, err := c.HeimdallClient.FetchWithRetry(fmt.Sprintf("bor/span/%d", newSpanID), "") @@ -1102,7 +1150,9 @@ func (c *Bor) fetchAndCommitSpan( for _, val := range heimdallSpan.ValidatorSet.Validators { validators = append(validators, val.MinimalVal()) } + validatorBytes, err := rlp.EncodeToBytes(validators) + if err != nil { return err } @@ -1112,13 +1162,16 @@ func (c *Bor) fetchAndCommitSpan( for _, val := range heimdallSpan.SelectedProducers { producers = append(producers, val.MinimalVal()) } + producerBytes, err := rlp.EncodeToBytes(producers) + if err != nil { return err } // method method := "commitSpan" + log.Info("✅ Committing new span", "id", heimdallSpan.ID, "startBlock", heimdallSpan.StartBlock, @@ -1156,6 +1209,7 @@ func (c *Bor) CommitStates( stateSyncs := make([]*types.StateSyncData, 0) number := header.Number.Uint64() _lastStateID, err := c.GenesisContractsClient.LastStateId(number - 1) + if err != nil { return nil, err } @@ -1166,7 +1220,13 @@ func (c *Bor) CommitStates( "Fetching state updates from Heimdall", "fromID", lastStateID+1, "to", to.Format(time.RFC3339)) + eventRecords, err := c.HeimdallClient.FetchStateSyncEvents(lastStateID+1, to.Unix()) + + if err != nil { + log.Error("Error occurred when fetching state sync events", err) + } + if c.config.OverrideStateSyncRecords != nil { if val, ok := c.config.OverrideStateSyncRecords[strconv.FormatUint(number, 10)]; ok { eventRecords = eventRecords[0:val] @@ -1174,10 +1234,12 @@ func (c *Bor) CommitStates( } chainID := c.chainConfig.ChainID.String() + for _, eventRecord := range eventRecords { if eventRecord.ID <= lastStateID { continue } + if err := validateEventRecord(eventRecord, number, to, lastStateID, chainID); err != nil { log.Error(err.Error()) break @@ -1196,6 +1258,7 @@ func (c *Bor) CommitStates( } lastStateID++ } + return stateSyncs, nil } @@ -1204,6 +1267,7 @@ func validateEventRecord(eventRecord *EventRecordWithTime, number uint64, to tim if lastStateID+1 != eventRecord.ID || eventRecord.ChainID != chainID || !eventRecord.Time.Before(to) { return &InvalidStateReceivedError{number, lastStateID, &to, eventRecord} } + return nil } @@ -1217,12 +1281,12 @@ func (c *Bor) SetHeimdallClient(h IHeimdallClient) { func (c *Bor) getNextHeimdallSpanForTest( newSpanID uint64, - state *state.StateDB, header *types.Header, chain core.ChainContext, ) (*HeimdallSpan, error) { headerNumber := header.Number.Uint64() span, err := c.GetCurrentSpan(header.ParentHash) + if err != nil { return nil, err } @@ -1242,12 +1306,14 @@ func (c *Bor) getNextHeimdallSpanForTest( } else { span.StartBlock = span.EndBlock + 1 } + span.EndBlock = span.StartBlock + (100 * c.config.Sprint) - 1 selectedProducers := make([]Validator, len(snap.ValidatorSet.Validators)) for i, v := range snap.ValidatorSet.Validators { selectedProducers[i] = *v } + heimdallSpan := &HeimdallSpan{ Span: *span, ValidatorSet: *snap.ValidatorSet, @@ -1335,10 +1401,11 @@ func applyMessage( func validatorContains(a []*Validator, x *Validator) (*Validator, bool) { for _, n := range a { - if bytes.Compare(n.Address.Bytes(), x.Address.Bytes()) == 0 { + if bytes.Equal(n.Address.Bytes(), x.Address.Bytes()) { return n, true } } + return nil, false } @@ -1347,6 +1414,7 @@ func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator) oldVals := v.Validators var changes []*Validator + for _, ov := range oldVals { if f, ok := validatorContains(newVals, ov); ok { ov.VotingPower = f.VotingPower @@ -1363,7 +1431,10 @@ func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator) } } - v.UpdateWithChangeSet(changes) + if err := v.UpdateWithChangeSet(changes); err != nil { + log.Error("Error while updating change set", err) + } + return v } diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index b0ebc96861..6225532ca9 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -4,6 +4,8 @@ import ( "math/big" "testing" + "github.com/stretchr/testify/assert" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" @@ -12,10 +14,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" - "github.com/stretchr/testify/assert" ) func TestGenesisContractChange(t *testing.T) { + t.Parallel() + addr0 := common.Address{0x1} b := &Bor{ @@ -101,6 +104,8 @@ func TestGenesisContractChange(t *testing.T) { } func TestEncodeSigHeaderJaipur(t *testing.T) { + t.Parallel() + // As part of the EIP-1559 fork in mumbai, an incorrect seal hash // was used for Bor that did not included the BaseFee. The Jaipur // block is a hard fork to fix that. diff --git a/consensus/bor/clerk.go b/consensus/bor/clerk.go index d7e6982873..ca610282a5 100644 --- a/consensus/bor/clerk.go +++ b/consensus/bor/clerk.go @@ -23,7 +23,7 @@ type EventRecordWithTime struct { Time time.Time `json:"record_time" yaml:"record_time"` } -// String returns the string representatin of span +// String returns the string representations of span func (e *EventRecordWithTime) String() string { return fmt.Sprintf( "id %v, contract %v, data: %v, txHash: %v, logIndex: %v, chainId: %v, time %s", diff --git a/consensus/bor/genesis_contracts_client.go b/consensus/bor/genesis_contracts_client.go index 582358e0cb..2b36b6e5e0 100644 --- a/consensus/bor/genesis_contracts_client.go +++ b/consensus/bor/genesis_contracts_client.go @@ -38,6 +38,7 @@ func NewGenesisContractsClient( ) *GenesisContractsClient { vABI, _ := abi.JSON(strings.NewReader(validatorsetABI)) sABI, _ := abi.JSON(strings.NewReader(stateReceiverABI)) + return &GenesisContractsClient{ validatorSetABI: vABI, stateReceiverABI: sABI, @@ -56,21 +57,27 @@ func (gc *GenesisContractsClient) CommitState( ) error { eventRecord := event.BuildEventRecord() recordBytes, err := rlp.EncodeToBytes(eventRecord) + if err != nil { return err } + method := "commitState" t := event.Time.Unix() data, err := gc.stateReceiverABI.Pack(method, big.NewInt(0).SetInt64(t), recordBytes) + if err != nil { log.Error("Unable to pack tx for commitState", "error", err) return err } + log.Info("→ committing new state", "eventRecord", event.String()) + msg := getSystemMessage(common.HexToAddress(gc.StateReceiverContract), data) if err := applyMessage(msg, state, header, gc.chainConfig, chCtx); err != nil { return err } + return nil } @@ -78,6 +85,7 @@ func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, blockNr := rpc.BlockNumber(snapshotNumber) method := "lastStateId" data, err := gc.stateReceiverABI.Pack(method) + if err != nil { log.Error("Unable to pack tx for LastStateId", "error", err) return nil, err @@ -91,6 +99,7 @@ func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, To: &toAddress, Data: &msgData, }, rpc.BlockNumberOrHash{BlockNumber: &blockNr}, nil) + if err != nil { return nil, err } @@ -99,5 +108,6 @@ func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil { return nil, err } + return *ret, nil } diff --git a/consensus/bor/merkle.go b/consensus/bor/merkle.go index bdfbaba983..5c61eb4a12 100644 --- a/consensus/bor/merkle.go +++ b/consensus/bor/merkle.go @@ -2,12 +2,12 @@ package bor func appendBytes32(data ...[]byte) []byte { var result []byte + for _, v := range data { - paddedV, err := convertTo32(v) - if err == nil { - result = append(result, paddedV[:]...) - } + paddedV := convertTo32(v) + result = append(result, paddedV[:]...) } + return result } @@ -24,25 +24,29 @@ func nextPowerOfTwo(n uint64) uint64 { n |= n >> 16 n |= n >> 32 n++ + return n } -func convertTo32(input []byte) (output [32]byte, err error) { +func convertTo32(input []byte) (output [32]byte) { l := len(input) if l > 32 || l == 0 { return } + copy(output[32-l:], input[:]) + return } func convert(input []([32]byte)) [][]byte { var output [][]byte + for _, in := range input { newInput := make([]byte, len(in[:])) copy(newInput, in[:]) output = append(output, newInput) - } + return output } diff --git a/consensus/bor/rest.go b/consensus/bor/rest.go index 3ef531de18..49ecb38af5 100644 --- a/consensus/bor/rest.go +++ b/consensus/bor/rest.go @@ -40,39 +40,49 @@ func NewHeimdallClient(urlString string) (*HeimdallClient, error) { h := &HeimdallClient{ urlString: urlString, client: http.Client{ - Timeout: time.Duration(5 * time.Second), + Timeout: 5 * time.Second, }, closeCh: make(chan struct{}), } + return h, nil } func (h *HeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error) { eventRecords := make([]*EventRecordWithTime, 0) + for { queryParams := fmt.Sprintf("from-id=%d&to-time=%d&limit=%d", fromID, to, stateFetchLimit) log.Info("Fetching state sync events", "queryParams", queryParams) response, err := h.FetchWithRetry("clerk/event-record/list", queryParams) + if err != nil { return nil, err } + var _eventRecords []*EventRecordWithTime + if response.Result == nil { // status 204 break } + if err := json.Unmarshal(response.Result, &_eventRecords); err != nil { return nil, err } + eventRecords = append(eventRecords, _eventRecords...) + if len(_eventRecords) < stateFetchLimit { break } + fromID += uint64(stateFetchLimit) } sort.SliceStable(eventRecords, func(i, j int) bool { return eventRecords[i].ID < eventRecords[j].ID }) + return eventRecords, nil } @@ -130,7 +140,7 @@ func (h *HeimdallClient) FetchWithRetry(rawPath string, rawQuery string) (*Respo // internal fetch method func (h *HeimdallClient) internalFetch(u *url.URL) (*ResponseWithHeight, error) { - res, err := h.client.Get(u.String()) + res, err := h.client.Get(u.String()) // nolint: noctx if err != nil { return nil, err } diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go index 8d212f33ef..ef92cc99b4 100644 --- a/consensus/bor/snapshot.go +++ b/consensus/bor/snapshot.go @@ -25,13 +25,6 @@ type Snapshot struct { Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections } -// signersAscending implements the sort interface to allow sorting a list of addresses -type signersAscending []common.Address - -func (s signersAscending) Len() int { return len(s) } -func (s signersAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 } -func (s signersAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - // newSnapshot creates a new snapshot with the specified startup parameters. This // method does not initialize the set of recent signers, so only ever use if for // the genesis block. @@ -52,6 +45,7 @@ func newSnapshot( ValidatorSet: NewValidatorSet(validators), Recents: make(map[uint64]common.Address), } + return snap } @@ -61,10 +55,13 @@ func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Dat if err != nil { return nil, err } + snap := new(Snapshot) + if err := json.Unmarshal(blob, snap); err != nil { return nil, err } + snap.config = config snap.sigcache = sigcache snap.ethAPI = ethAPI @@ -83,6 +80,7 @@ func (s *Snapshot) store(db ethdb.Database) error { if err != nil { return err } + return db.Put(append([]byte("bor-"), s.Hash[:]...), blob) } @@ -115,6 +113,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { return nil, errOutOfRangeChain } } + if headers[0].Number.Uint64() != s.Number+1 { return nil, errOutOfRangeChain } @@ -126,7 +125,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { number := header.Number.Uint64() // Delete the oldest signer from the recent list to allow it signing again - if number >= s.config.Sprint && number-s.config.Sprint >= 0 { + if number >= s.config.Sprint { delete(snap.Recents, number-s.config.Sprint) } @@ -153,6 +152,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { if err := validateHeaderExtraField(header.Extra); err != nil { return nil, err } + validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal] // get validators from headers and use that for new validator set @@ -162,6 +162,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { snap.ValidatorSet = v } } + snap.Number += uint64(len(headers)) snap.Hash = headers[len(headers)-1].Hash() @@ -173,10 +174,13 @@ func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error) validators := s.ValidatorSet.Validators proposer := s.ValidatorSet.GetProposer().Address proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer) + if proposerIndex == -1 { return -1, &UnauthorizedProposerError{s.Number, proposer.Bytes()} } + signerIndex, _ := s.ValidatorSet.GetByAddress(signer) + if signerIndex == -1 { return -1, &UnauthorizedSignerError{s.Number, signer.Bytes()} } @@ -187,6 +191,7 @@ func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error) tempIndex = tempIndex + len(validators) } } + return tempIndex - proposerIndex, nil } @@ -196,13 +201,14 @@ func (s *Snapshot) signers() []common.Address { for _, sig := range s.ValidatorSet.Validators { sigs = append(sigs, sig.Address) } + return sigs } // Difficulty returns the difficulty for a particular signer at the current snapshot number func (s *Snapshot) Difficulty(signer common.Address) uint64 { // if signer is empty - if bytes.Compare(signer.Bytes(), common.Address{}.Bytes()) == 0 { + if bytes.Equal(signer.Bytes(), common.Address{}.Bytes()) { return 1 } diff --git a/consensus/bor/snapshot_test.go b/consensus/bor/snapshot_test.go index 6bb8547843..2bbbc32123 100644 --- a/consensus/bor/snapshot_test.go +++ b/consensus/bor/snapshot_test.go @@ -16,6 +16,8 @@ const ( ) func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) { + t.Parallel() + validators := buildRandomValidatorSet(numVals) validatorSet := NewValidatorSet(validators) snap := Snapshot{ @@ -25,17 +27,22 @@ func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) { // proposer is signer signer := validatorSet.Proposer.Address successionNumber, err := snap.GetSignerSuccessionNumber(signer) + if err != nil { t.Fatalf("%s", err) } + assert.Equal(t, 0, successionNumber) } func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) { + t.Parallel() + validators := buildRandomValidatorSet(numVals) // sort validators by address, which is what NewValidatorSet also does sort.Sort(ValidatorsByAddress(validators)) + proposerIndex := 32 signerIndex := 56 // give highest ProposerPriority to a particular val, so that they become the proposer @@ -47,13 +54,17 @@ func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) { // choose a signer at an index greater than proposer index signer := snap.ValidatorSet.Validators[signerIndex].Address successionNumber, err := snap.GetSignerSuccessionNumber(signer) + if err != nil { t.Fatalf("%s", err) } + assert.Equal(t, signerIndex-proposerIndex, successionNumber) } func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) { + t.Parallel() + validators := buildRandomValidatorSet(numVals) proposerIndex := 98 signerIndex := 11 @@ -66,13 +77,17 @@ func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) { // choose a signer at an index greater than proposer index signer := snap.ValidatorSet.Validators[signerIndex].Address successionNumber, err := snap.GetSignerSuccessionNumber(signer) + if err != nil { t.Fatalf("%s", err) } + assert.Equal(t, signerIndex+numVals-proposerIndex, successionNumber) } func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) { + t.Parallel() + validators := buildRandomValidatorSet(numVals) snap := Snapshot{ ValidatorSet: NewValidatorSet(validators), @@ -89,6 +104,8 @@ func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) { } func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { + t.Parallel() + validators := buildRandomValidatorSet(numVals) snap := Snapshot{ ValidatorSet: NewValidatorSet(validators), @@ -101,9 +118,12 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { assert.Equal(t, dummySignerAddress.Bytes(), e.Signer) } +// nolint: unparam func buildRandomValidatorSet(numVals int) []*Validator { rand.Seed(time.Now().Unix()) + validators := make([]*Validator, numVals) + for i := 0; i < numVals; i++ { validators[i] = &Validator{ Address: randomAddress(), @@ -114,11 +134,13 @@ func buildRandomValidatorSet(numVals int) []*Validator { // sort validators by address, which is what NewValidatorSet also does sort.Sort(ValidatorsByAddress(validators)) + return validators } func randomAddress() common.Address { bytes := make([]byte, 32) rand.Read(bytes) + return common.BytesToAddress(bytes) } diff --git a/consensus/bor/validator.go b/consensus/bor/validator.go index 00e9fdc645..57905fdf89 100644 --- a/consensus/bor/validator.go +++ b/consensus/bor/validator.go @@ -43,9 +43,12 @@ func (v *Validator) Cmp(other *Validator) *Validator { if v == nil { return other } + if other == nil { return v } + + // nolint:nestif if v.ProposerPriority > other.ProposerPriority { return v } else if v.ProposerPriority < other.ProposerPriority { @@ -66,6 +69,7 @@ func (v *Validator) String() string { if v == nil { return "nil-Validator" } + return fmt.Sprintf("Validator{%v Power:%v Priority:%v}", v.Address.Hex(), v.VotingPower, @@ -87,6 +91,7 @@ func (v *Validator) HeaderBytes() []byte { result := make([]byte, 40) copy(result[:20], v.Address.Bytes()) copy(result[20:], v.PowerBytes()) + return result } @@ -95,6 +100,7 @@ func (v *Validator) PowerBytes() []byte { powerBytes := big.NewInt(0).SetInt64(v.VotingPower).Bytes() result := make([]byte, 20) copy(result[20-len(powerBytes):], powerBytes) + return result } @@ -114,6 +120,7 @@ func ParseValidators(validatorsBytes []byte) ([]*Validator, error) { } result := make([]*Validator, len(validatorsBytes)/40) + for i := 0; i < len(validatorsBytes); i += 40 { address := make([]byte, 20) power := make([]byte, 20) @@ -142,6 +149,7 @@ func SortMinimalValByAddress(a []MinimalVal) []MinimalVal { sort.Slice(a, func(i, j int) bool { return bytes.Compare(a[i].Signer.Bytes(), a[j].Signer.Bytes()) < 0 }) + return a } @@ -150,5 +158,6 @@ func ValidatorsToMinimalValidators(vals []Validator) (minVals []MinimalVal) { for _, val := range vals { minVals = append(minVals, val.MinimalVal()) } + return } diff --git a/consensus/bor/validator_set.go b/consensus/bor/validator_set.go index 0b5c10ebd0..892891bbda 100644 --- a/consensus/bor/validator_set.go +++ b/consensus/bor/validator_set.go @@ -56,12 +56,15 @@ type ValidatorSet struct { func NewValidatorSet(valz []*Validator) *ValidatorSet { vals := &ValidatorSet{} err := vals.updateWithChangeSet(valz, false) + if err != nil { panic(fmt.Sprintf("cannot create validator set: %s", err)) } + if len(valz) > 0 { vals.IncrementProposerPriority(1) } + return vals } @@ -72,9 +75,10 @@ func (vals *ValidatorSet) IsNilOrEmpty() bool { // Increment ProposerPriority and update the proposer on a copy, and return it. func (vals *ValidatorSet) CopyIncrementProposerPriority(times int) *ValidatorSet { - copy := vals.Copy() - copy.IncrementProposerPriority(times) - return copy + validatorCopy := vals.Copy() + validatorCopy.IncrementProposerPriority(times) + + return validatorCopy } // IncrementProposerPriority increments ProposerPriority of each validator and updates the @@ -84,6 +88,7 @@ func (vals *ValidatorSet) IncrementProposerPriority(times int) { if vals.IsNilOrEmpty() { panic("empty validator set") } + if times <= 0 { panic("Cannot call IncrementProposerPriority with non-positive times") } @@ -120,6 +125,7 @@ func (vals *ValidatorSet) RescalePriorities(diffMax int64) { // NOTE: This may make debugging priority issues easier as well. diff := computeMaxMinPriorityDiff(vals) ratio := (diff + diffMax - 1) / diffMax + if diff > diffMax { for _, val := range vals.Validators { val.ProposerPriority = val.ProposerPriority / ratio @@ -145,10 +151,13 @@ func (vals *ValidatorSet) incrementProposerPriority() *Validator { func (vals *ValidatorSet) computeAvgProposerPriority() int64 { n := int64(len(vals.Validators)) sum := big.NewInt(0) + for _, val := range vals.Validators { sum.Add(sum, big.NewInt(val.ProposerPriority)) } + avg := sum.Div(sum, big.NewInt(n)) + if avg.IsInt64() { return avg.Int64() } @@ -162,17 +171,22 @@ func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 { if vals.IsNilOrEmpty() { panic("empty validator set") } + max := int64(math.MinInt64) min := int64(math.MaxInt64) + for _, v := range vals.Validators { if v.ProposerPriority < min { min = v.ProposerPriority } + if v.ProposerPriority > max { max = v.ProposerPriority } } + diff := max - min + if diff < 0 { return -1 * diff } else { @@ -185,6 +199,7 @@ func (vals *ValidatorSet) getValWithMostPriority() *Validator { for _, val := range vals.Validators { res = res.Cmp(val) } + return res } @@ -192,7 +207,9 @@ func (vals *ValidatorSet) shiftByAvgProposerPriority() { if vals.IsNilOrEmpty() { panic("empty validator set") } + avgProposerPriority := vals.computeAvgProposerPriority() + for _, val := range vals.Validators { val.ProposerPriority = safeSubClip(val.ProposerPriority, avgProposerPriority) } @@ -203,10 +220,13 @@ func validatorListCopy(valsList []*Validator) []*Validator { if valsList == nil { return nil } + valsCopy := make([]*Validator, len(valsList)) + for i, val := range valsList { valsCopy[i] = val.Copy() } + return valsCopy } @@ -225,6 +245,7 @@ func (vals *ValidatorSet) HasAddress(address []byte) bool { idx := sort.Search(len(vals.Validators), func(i int) bool { return bytes.Compare(address, vals.Validators[i].Address.Bytes()) <= 0 }) + return idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address) } @@ -237,6 +258,7 @@ func (vals *ValidatorSet) GetByAddress(address common.Address) (index int, val * if idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address.Bytes()) { return idx, vals.Validators[idx].Copy() } + return -1, nil } @@ -247,7 +269,9 @@ func (vals *ValidatorSet) GetByIndex(index int) (address []byte, val *Validator) if index < 0 || index >= len(vals.Validators) { return nil, nil } + val = vals.Validators[index] + return val.Address.Bytes(), val.Copy() } @@ -258,7 +282,6 @@ func (vals *ValidatorSet) Size() int { // Force recalculation of the set's total voting power. func (vals *ValidatorSet) updateTotalVotingPower() error { - sum := int64(0) for _, val := range vals.Validators { // mind overflow @@ -267,7 +290,9 @@ func (vals *ValidatorSet) updateTotalVotingPower() error { return &TotalVotingPowerExceededError{sum, vals.Validators} } } + vals.totalVotingPower = sum + return nil } @@ -276,11 +301,13 @@ func (vals *ValidatorSet) updateTotalVotingPower() error { func (vals *ValidatorSet) TotalVotingPower() int64 { if vals.totalVotingPower == 0 { log.Info("invoking updateTotalVotingPower before returning it") + if err := vals.updateTotalVotingPower(); err != nil { // Can/should we do better? panic(err) } } + return vals.totalVotingPower } @@ -290,9 +317,11 @@ func (vals *ValidatorSet) GetProposer() (proposer *Validator) { if len(vals.Validators) == 0 { return nil } + if vals.Proposer == nil { vals.Proposer = vals.findProposer() } + return vals.Proposer.Copy() } @@ -303,6 +332,7 @@ func (vals *ValidatorSet) findProposer() *Validator { proposer = proposer.Cmp(val) } } + return proposer } @@ -343,6 +373,7 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e removals = make([]*Validator, 0, len(changes)) updates = make([]*Validator, 0, len(changes)) + var prevAddr common.Address // Scan changes by address and append valid validators to updates or removals lists. @@ -351,22 +382,27 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes) return nil, nil, err } + if valUpdate.VotingPower < 0 { err = fmt.Errorf("voting power can't be negative: %v", valUpdate) return nil, nil, err } + if valUpdate.VotingPower > MaxTotalVotingPower { err = fmt.Errorf("to prevent clipping/ overflow, voting power can't be higher than %v: %v ", MaxTotalVotingPower, valUpdate) return nil, nil, err } + if valUpdate.VotingPower == 0 { removals = append(removals, valUpdate) } else { updates = append(updates, valUpdate) } + prevAddr = valUpdate.Address } + return updates, removals, err } @@ -382,12 +418,12 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e // by processChanges for duplicates and invalid values. // No changes are made to the validator set 'vals'. func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVotingPower int64, numNewValidators int, err error) { - updatedTotalVotingPower = vals.TotalVotingPower() for _, valUpdate := range updates { address := valUpdate.Address _, val := vals.GetByAddress(address) + if val == nil { // New validator, add its voting power the the total. updatedTotalVotingPower += valUpdate.VotingPower @@ -396,11 +432,14 @@ func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVoting // Updated validator, add the difference in power to the total. updatedTotalVotingPower += valUpdate.VotingPower - val.VotingPower } + overflow := updatedTotalVotingPower > MaxTotalVotingPower + if overflow { err = fmt.Errorf( "failed to add/update validator %v, total voting power would exceed the max allowed %v", valUpdate, MaxTotalVotingPower) + return 0, 0, err } } @@ -414,10 +453,10 @@ func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVoting // 'updates' parameter must be a list of unique validators to be added or updated. // No changes are made to the validator set 'vals'. func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) { - for _, valUpdate := range updates { address := valUpdate.Address _, val := vals.GetByAddress(address) + if val == nil { // add val // Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't @@ -432,7 +471,6 @@ func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotal valUpdate.ProposerPriority = val.ProposerPriority } } - } // Merges the vals' validator list with the updates list. @@ -440,7 +478,6 @@ func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotal // Expects updates to be a list of updates sorted by address with no duplicates or errors, // must have been validated with verifyUpdates() and priorities computed with computeNewPriorities(). func (vals *ValidatorSet) applyUpdates(updates []*Validator) { - existing := vals.Validators merged := make([]*Validator, len(existing)+len(updates)) i := 0 @@ -478,24 +515,25 @@ func (vals *ValidatorSet) applyUpdates(updates []*Validator) { // Checks that the validators to be removed are part of the validator set. // No changes are made to the validator set 'vals'. func verifyRemovals(deletes []*Validator, vals *ValidatorSet) error { - for _, valUpdate := range deletes { address := valUpdate.Address _, val := vals.GetByAddress(address) + if val == nil { return fmt.Errorf("failed to find validator %X to remove", address) } } + if len(deletes) > len(vals.Validators) { panic("more deletes than validators") } + return nil } // Removes the validators specified in 'deletes' from validator set 'vals'. // Should not fail as verification has been done before. func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { - existing := vals.Validators merged := make([]*Validator, len(existing)-len(deletes)) @@ -509,6 +547,7 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { merged[i] = existing[0] i++ } + existing = existing[1:] } @@ -526,7 +565,6 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { // are not allowed and will trigger an error if present in 'changes'. // The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet(). func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error { - if len(changes) <= 0 { return nil } @@ -596,19 +634,19 @@ func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error { func IsErrTooMuchChange(err error) bool { switch err.(type) { - case errTooMuchChange: + case tooMuchChangeError: return true default: return false } } -type errTooMuchChange struct { +type tooMuchChangeError struct { got int64 needed int64 } -func (e errTooMuchChange) Error() string { +func (e tooMuchChangeError) Error() string { return fmt.Sprintf("Invalid commit -- insufficient old voting power: got %v, needed %v", e.got, e.needed) } @@ -622,11 +660,14 @@ func (vals *ValidatorSet) StringIndented(indent string) string { if vals == nil { return "nil-ValidatorSet" } + var valStrings []string + vals.Iterate(func(index int, val *Validator) bool { valStrings = append(valStrings, val.String()) return false }) + return fmt.Sprintf(`ValidatorSet{ %s Proposer: %v %s Validators: @@ -636,7 +677,6 @@ func (vals *ValidatorSet) StringIndented(indent string) string { indent, indent, strings.Join(valStrings, "\n"+indent+" "), indent) - } //------------------------------------- @@ -668,6 +708,7 @@ func safeAdd(a, b int64) (int64, bool) { } else if b < 0 && a < math.MinInt64-b { return -1, true } + return a + b, false } @@ -677,6 +718,7 @@ func safeSub(a, b int64) (int64, bool) { } else if b < 0 && a > math.MaxInt64+b { return -1, true } + return a - b, false } @@ -686,8 +728,10 @@ func safeAddClip(a, b int64) int64 { if b < 0 { return math.MinInt64 } + return math.MaxInt64 } + return c } @@ -697,7 +741,9 @@ func safeSubClip(a, b int64) int64 { if b > 0 { return math.MinInt64 } + return math.MaxInt64 } + return c } From 45a72bc49e40516b2d8969a3849d82655f0927f2 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 20 May 2022 13:49:37 -0700 Subject: [PATCH 71/80] Lint internal/cli --- internal/cli/account.go | 1 + internal/cli/account_import.go | 5 +++++ internal/cli/account_list.go | 5 +++++ internal/cli/account_new.go | 1 + internal/cli/attach.go | 27 ++++++++++++++++++++------- internal/cli/bootnode.go | 12 +++++++++++- internal/cli/bor_fingerprint.go | 12 +++++++++--- internal/cli/chain.go | 1 + internal/cli/chain_sethead.go | 4 ++++ internal/cli/chain_watch.go | 8 +++++++- internal/cli/command.go | 17 +++++++++++++++-- internal/cli/debug.go | 15 ++++++++++++--- internal/cli/markdown_test.go | 1 + internal/cli/peers.go | 1 + internal/cli/peers_add.go | 2 ++ internal/cli/peers_list.go | 5 +++++ internal/cli/peers_remove.go | 2 ++ internal/cli/peers_status.go | 4 ++++ internal/cli/status.go | 5 +++++ internal/cli/version.go | 2 ++ 20 files changed, 113 insertions(+), 17 deletions(-) diff --git a/internal/cli/account.go b/internal/cli/account.go index 7ce6c09b63..bb8b30b892 100644 --- a/internal/cli/account.go +++ b/internal/cli/account.go @@ -19,6 +19,7 @@ func (a *Account) MarkDown() string { "- [```account list```](./account_list.md): List the wallets in the Bor client.", "- [```account import```](./account_import.md): Import an account to the Bor client.", } + return strings.Join(items, "\n\n") } diff --git a/internal/cli/account_import.go b/internal/cli/account_import.go index d7ab14601a..a3f65ab512 100644 --- a/internal/cli/account_import.go +++ b/internal/cli/account_import.go @@ -20,6 +20,7 @@ func (a *AccountImportCommand) MarkDown() string { "The ```account import``` command imports an account in Json format to the Bor data directory.", a.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -58,7 +59,9 @@ func (a *AccountImportCommand) Run(args []string) int { a.UI.Error("Expected one argument") return 1 } + key, err := crypto.LoadECDSA(args[0]) + if err != nil { a.UI.Error(fmt.Sprintf("Failed to load the private key '%s': %v", args[0], err)) return 1 @@ -80,6 +83,8 @@ func (a *AccountImportCommand) Run(args []string) int { if err != nil { utils.Fatalf("Could not create the account: %v", err) } + a.UI.Output(fmt.Sprintf("Account created: %s", acct.Address.String())) + return 0 } diff --git a/internal/cli/account_list.go b/internal/cli/account_list.go index db77158b8e..854934c447 100644 --- a/internal/cli/account_list.go +++ b/internal/cli/account_list.go @@ -19,6 +19,7 @@ func (a *AccountListCommand) MarkDown() string { "The `account list` command lists all the accounts in the Bor data directory.", a.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -53,7 +54,9 @@ func (a *AccountListCommand) Run(args []string) int { a.UI.Error(fmt.Sprintf("Failed to get keystore: %v", err)) return 1 } + a.UI.Output(formatAccounts(keystore.Accounts())) + return 0 } @@ -64,10 +67,12 @@ func formatAccounts(accts []accounts.Account) string { rows := make([]string, len(accts)+1) rows[0] = "Index|Address" + for i, d := range accts { rows[i+1] = fmt.Sprintf("%d|%s", i, d.Address.String()) } + return formatList(rows) } diff --git a/internal/cli/account_new.go b/internal/cli/account_new.go index f6591fc53b..aef272a389 100644 --- a/internal/cli/account_new.go +++ b/internal/cli/account_new.go @@ -18,6 +18,7 @@ func (a *AccountNewCommand) MarkDown() string { "The `account new` command creates a new local account file on the Bor data directory. Bor should not be running to execute this command.", a.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } diff --git a/internal/cli/attach.go b/internal/cli/attach.go index df1c76ff3d..1aa888c12b 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -6,12 +6,12 @@ import ( "path/filepath" "strings" - "github.com/ethereum/go-ethereum/internal/cli/flagset" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/console" + "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" + "github.com/mitchellh/cli" ) @@ -33,6 +33,7 @@ func (c *AttachCommand) MarkDown() string { "Connect to remote Bor IPC console.", c.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -49,7 +50,6 @@ func (c *AttachCommand) Synopsis() string { } func (c *AttachCommand) Flags() *flagset.Flagset { - f := flagset.NewFlagSet("attach") f.StringFlag(&flagset.StringFlag{ @@ -75,13 +75,13 @@ func (c *AttachCommand) Flags() *flagset.Flagset { // Run implements the cli.Command interface func (c *AttachCommand) Run(args []string) int { - flags := c.Flags() //check if first arg is flag or IPC location if len(args) == 0 { args = append(args, "") } + if args[0] != "" && strings.HasPrefix(args[0], "--") { if err := flags.Parse(args); err != nil { c.UI.Error(err.Error()) @@ -94,6 +94,7 @@ func (c *AttachCommand) Run(args []string) int { return 1 } } + if err := c.remoteConsole(); err != nil { c.UI.Error(err.Error()) return 1 @@ -104,25 +105,30 @@ func (c *AttachCommand) Run(args []string) int { // remoteConsole will connect to a remote bor instance, attaching a JavaScript // console to it. +// nolint: unparam func (c *AttachCommand) remoteConsole() error { // Attach to a remotely running geth instance and start the JavaScript console - path := node.DefaultDataDir() if c.Endpoint == "" { if c.Meta.dataDir != "" { path = c.Meta.dataDir } + if path != "" { homeDir, _ := os.UserHomeDir() path = filepath.Join(homeDir, "/.bor/data") } + c.Endpoint = fmt.Sprintf("%s/bor.ipc", path) } + client, err := dialRPC(c.Endpoint) + if err != nil { utils.Fatalf("Unable to attach to remote bor: %v", err) } + config := console.Config{ DataDir: path, DocRoot: c.JSpathFlag, @@ -134,7 +140,12 @@ func (c *AttachCommand) remoteConsole() error { if err != nil { utils.Fatalf("Failed to start the JavaScript console: %v", err) } - defer console.Stop(false) + + defer func() { + if err := console.Stop(false); err != nil { + c.UI.Error(err.Error()) + } + }() if c.ExecCMD != "" { console.Evaluate(c.ExecCMD) @@ -159,6 +170,7 @@ func dialRPC(endpoint string) (*rpc.Client, error) { // these prefixes. endpoint = endpoint[4:] } + return rpc.Dial(endpoint) } @@ -175,5 +187,6 @@ func (c *AttachCommand) makeConsolePreloads() []string { for _, file := range strings.Split(c.PreloadJSFlag, ",") { preloads = append(preloads, strings.TrimSpace(file)) } + return preloads } diff --git a/internal/cli/bootnode.go b/internal/cli/bootnode.go index f9127494a6..9e1a0fcde9 100644 --- a/internal/cli/bootnode.go +++ b/internal/cli/bootnode.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/nat" + "github.com/mitchellh/cli" ) @@ -45,6 +46,7 @@ func (c *BootnodeCommand) MarkDown() string { "# Bootnode", c.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -103,6 +105,7 @@ func (b *BootnodeCommand) Synopsis() string { } // Run implements the cli.Command interface +// nolint: gocognit func (b *BootnodeCommand) Run(args []string) int { flags := b.Flags() if err := flags.Parse(args); err != nil { @@ -118,6 +121,7 @@ func (b *BootnodeCommand) Run(args []string) int { } else { glogger.Verbosity(log.LvlInfo) } + log.Root().SetHandler(glogger) natm, err := nat.Parse(b.nat) @@ -128,6 +132,7 @@ func (b *BootnodeCommand) Run(args []string) int { // create a one time key var nodeKey *ecdsa.PrivateKey + // nolint: nestif if b.nodeKey != "" { // try to read the key either from file or command line if _, err := os.Stat(b.nodeKey); errors.Is(err, os.ErrNotExist) { @@ -157,7 +162,7 @@ func (b *BootnodeCommand) Run(args []string) int { } // save the public key pubRaw := fmt.Sprintf("%x", crypto.FromECDSAPub(&nodeKey.PublicKey)[1:]) - if err := ioutil.WriteFile(filepath.Join(path, "pub.key"), []byte(pubRaw), 0755); err != nil { + if err := ioutil.WriteFile(filepath.Join(path, "pub.key"), []byte(pubRaw), 0600); err != nil { b.UI.Error(fmt.Sprintf("failed to write node pub key: %v", err)) return 1 } @@ -169,7 +174,9 @@ func (b *BootnodeCommand) Run(args []string) int { b.UI.Error(fmt.Sprintf("could not resolve udp addr '%s': %v", b.listenAddr, err)) return 1 } + conn, err := net.ListenUDP("udp", addr) + if err != nil { b.UI.Error(fmt.Sprintf("failed to listen udp addr '%s': %v", b.listenAddr, err)) return 1 @@ -180,7 +187,9 @@ func (b *BootnodeCommand) Run(args []string) int { if !realaddr.IP.IsLoopback() { go nat.Map(natm, nil, "udp", realaddr.Port, realaddr.Port, "ethereum discovery") } + if ext, err := natm.ExternalIP(); err == nil { + // nolint: govet realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port} } } @@ -198,6 +207,7 @@ func (b *BootnodeCommand) Run(args []string) int { PrivateKey: nodeKey, Log: log.Root(), } + if b.v5 { if _, err := discover.ListenV5(conn, ln, cfg); err != nil { utils.Fatalf("%v", err) diff --git a/internal/cli/bor_fingerprint.go b/internal/cli/bor_fingerprint.go index e9f4e70398..4e21f02956 100644 --- a/internal/cli/bor_fingerprint.go +++ b/internal/cli/bor_fingerprint.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/params" + "github.com/mitchellh/cli" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/disk" @@ -25,6 +26,7 @@ func (c *FingerprintCommand) MarkDown() string { "# Fingerprint", "Display the system fingerprint", } + return strings.Join(items, "\n\n") } @@ -45,6 +47,7 @@ func getCoresCount(cp []cpu.InfoStat) int { for i := 0; i < len(cp); i++ { cores += int(cp[i].Cores) } + return cores } @@ -76,6 +79,7 @@ func formatFingerprint(borFingerprint *BorFingerprint) string { fmt.Sprintf("RAM :: total : %v GB, free : %v GB, used : %v GB", borFingerprint.MemoryDetails.TotalMem, borFingerprint.MemoryDetails.FreeMem, borFingerprint.MemoryDetails.UsedMem), fmt.Sprintf("STORAGE :: total : %v GB, free : %v GB, used : %v GB", borFingerprint.DiskDetails.TotalDisk, borFingerprint.DiskDetails.FreeDisk, borFingerprint.DiskDetails.UsedDisk), }) + return base } @@ -85,13 +89,13 @@ func convertBytesToGB(bytesValue uint64) float64 { // Checks if fio exists on the node func (c *FingerprintCommand) checkFio() error { - cmd := exec.Command("/bin/sh", "-c", "fio -v") _, err := cmd.CombinedOutput() if err != nil { message := "\nFio package not installed. Install Fio for IOPS Benchmarking :\n\nDebianOS : 'sudo apt-get update && sudo apt-get install fio -y'\nAWS AMI/CentOS : 'sudo yum install fio -y'\nOracle LinuxOS : 'sudo dnf install fio -y'\n" c.UI.Output(message) + return err } @@ -101,9 +105,12 @@ func (c *FingerprintCommand) checkFio() error { // Run the IOPS benchmark for the node func (c *FingerprintCommand) benchmark() error { var b []byte + err := c.checkFio() + if err != nil { - return nil + // Missing Fio is not a fatal error. A message will be logged in console when it is missing in "checkFio()". + return nil //nolint:nilerr } c.UI.Output("\nRunning a 10 second test...\n") @@ -123,7 +130,6 @@ func (c *FingerprintCommand) benchmark() error { // Run implements the cli.Command interface func (c *FingerprintCommand) Run(args []string) int { - v, err := mem.VirtualMemory() if err != nil { c.UI.Error(err.Error()) diff --git a/internal/cli/chain.go b/internal/cli/chain.go index 896ce42cc4..9a7e9e8537 100644 --- a/internal/cli/chain.go +++ b/internal/cli/chain.go @@ -19,6 +19,7 @@ func (c *ChainCommand) MarkDown() string { "- [```chain sethead```](./chain_sethead.md): Set the current chain to a certain block.", "- [```chain watch```](./chain_watch.md): Watch the chainHead, reorg and fork events in real-time.", } + return strings.Join(items, "\n\n") } diff --git a/internal/cli/chain_sethead.go b/internal/cli/chain_sethead.go index 4d34479e0b..718ada4648 100644 --- a/internal/cli/chain_sethead.go +++ b/internal/cli/chain_sethead.go @@ -26,6 +26,7 @@ func (a *ChainSetHeadCommand) MarkDown() string { "- ```number```: The block number to roll back.", a.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -45,6 +46,7 @@ func (c *ChainSetHeadCommand) Flags() *flagset.Flagset { Default: false, Value: &c.yes, }) + return flags } @@ -88,6 +90,7 @@ func (c *ChainSetHeadCommand) Run(args []string) int { c.UI.Error(err.Error()) return 1 } + if response != "y" { c.UI.Output("set head aborted") return 0 @@ -100,5 +103,6 @@ func (c *ChainSetHeadCommand) Run(args []string) int { } c.UI.Output("Done!") + return 0 } diff --git a/internal/cli/chain_watch.go b/internal/cli/chain_watch.go index 72bd21b85d..17a65a8d99 100644 --- a/internal/cli/chain_watch.go +++ b/internal/cli/chain_watch.go @@ -24,6 +24,7 @@ func (c *ChainWatchCommand) MarkDown() string { "# Chain watch", "The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time.", } + return strings.Join(items, "\n\n") } @@ -70,7 +71,10 @@ func (c *ChainWatchCommand) Run(args []string) int { go func() { <-signalCh - sub.CloseSend() + + if err := sub.CloseSend(); err != nil { + c.UI.Error(err.Error()) + } }() for { @@ -80,6 +84,7 @@ func (c *ChainWatchCommand) Run(args []string) int { c.UI.Output(err.Error()) break } + c.UI.Output(formatHeadEvent(msg)) } @@ -95,5 +100,6 @@ func formatHeadEvent(msg *proto.ChainWatchResponse) string { } else if msg.Type == core.Chain2HeadReorgEvent { out = fmt.Sprintf("Reorg Detected \nAdded : %v \nRemoved : %v", msg.Newchain, msg.Oldchain) } + return out } diff --git a/internal/cli/command.go b/internal/cli/command.go index d1851594a7..34f7c4ef12 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -9,11 +9,16 @@ import ( "github.com/ethereum/go-ethereum/internal/cli/server" "github.com/ethereum/go-ethereum/internal/cli/server/proto" "github.com/ethereum/go-ethereum/node" + "github.com/mitchellh/cli" "github.com/ryanuber/columnize" "google.golang.org/grpc" ) +const ( + emptyPlaceHolder = "" +) + type MarkDownCommand interface { MarkDown cli.Command @@ -48,6 +53,7 @@ func Run(args []string) int { fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err.Error()) return 1 } + return exitCode } @@ -64,6 +70,7 @@ func Commands() map[string]MarkDownCommandFactory { meta := &Meta{ UI: ui, } + return map[string]MarkDownCommandFactory{ "server": func() (MarkDownCommand, error) { return &server.Command{ @@ -180,6 +187,7 @@ func (m *Meta2) NewFlagSet(n string) *flagset.Flagset { Usage: "Address of the grpc endpoint", Default: "127.0.0.1:3131", }) + return f } @@ -188,6 +196,7 @@ func (m *Meta2) Conn() (*grpc.ClientConn, error) { if err != nil { return nil, fmt.Errorf("failed to connect to server: %v", err) } + return conn, nil } @@ -196,6 +205,7 @@ func (m *Meta2) BorConn() (proto.BorClient, error) { if err != nil { return nil, err } + return proto.NewBorClient(conn), nil } @@ -243,18 +253,21 @@ func (m *Meta) GetKeystore() (*keystore.KeyStore, error) { scryptP := keystore.StandardScryptP keys := keystore.NewKeyStore(keydir, scryptN, scryptP) + return keys, nil } func formatList(in []string) string { columnConf := columnize.DefaultConfig() - columnConf.Empty = "" + columnConf.Empty = emptyPlaceHolder + return columnize.Format(in, columnConf) } func formatKV(in []string) string { columnConf := columnize.DefaultConfig() - columnConf.Empty = "" + columnConf.Empty = emptyPlaceHolder columnConf.Glue = " = " + return columnize.Format(in, columnConf) } diff --git a/internal/cli/debug.go b/internal/cli/debug.go index 66e936995c..fb998ee4b9 100644 --- a/internal/cli/debug.go +++ b/internal/cli/debug.go @@ -18,8 +18,9 @@ import ( "github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/server/proto" - "github.com/golang/protobuf/jsonpb" - gproto "github.com/golang/protobuf/proto" + + "github.com/golang/protobuf/jsonpb" // nolint:staticcheck + gproto "github.com/golang/protobuf/proto" // nolint:staticcheck "github.com/golang/protobuf/ptypes/empty" grpc_net_conn "github.com/mitchellh/go-grpc-net-conn" ) @@ -55,6 +56,7 @@ func (d *DebugCommand) MarkDown() string { d.Flags().MarkDown(), } items = append(items, examples...) + return strings.Join(items, "\n\n") } @@ -112,6 +114,7 @@ func (d *DebugCommand) Run(args []string) int { // User specified output directory tmp = filepath.Join(d.output, stamped) _, err := os.Stat(tmp) + if !os.IsNotExist(err) { d.UI.Error("Output directory already exists") return 1 @@ -139,6 +142,7 @@ func (d *DebugCommand) Run(args []string) int { req := &proto.PprofRequest{ Seconds: int64(d.seconds), } + switch profile { case "cpu": req.Type = proto.PprofRequest_CPU @@ -148,7 +152,9 @@ func (d *DebugCommand) Run(args []string) int { req.Type = proto.PprofRequest_LOOKUP req.Profile = profile } + stream, err := clt.Pprof(ctx, req) + if err != nil { return err } @@ -157,6 +163,7 @@ func (d *DebugCommand) Run(args []string) int { if err != nil { return err } + if _, ok := msg.Event.(*proto.PprofResponse_Open_); !ok { return fmt.Errorf("expected open message") } @@ -179,6 +186,7 @@ func (d *DebugCommand) Run(args []string) int { if _, err := io.Copy(file, conn); err != nil { return err } + return nil } @@ -210,7 +218,7 @@ func (d *DebugCommand) Run(args []string) int { d.UI.Output(err.Error()) return 1 } - if err := ioutil.WriteFile(filepath.Join(tmp, "status.json"), []byte(data), 0644); err != nil { + if err := ioutil.WriteFile(filepath.Join(tmp, "status.json"), []byte(data), 0600); err != nil { d.UI.Output(fmt.Sprintf("Failed to write status: %v", err)) return 1 } @@ -230,6 +238,7 @@ func (d *DebugCommand) Run(args []string) int { } d.UI.Output(fmt.Sprintf("Created debug archive: %s", archiveFile)) + return 0 } diff --git a/internal/cli/markdown_test.go b/internal/cli/markdown_test.go index 13a5c4ece3..30c272a220 100644 --- a/internal/cli/markdown_test.go +++ b/internal/cli/markdown_test.go @@ -7,6 +7,7 @@ import ( ) func TestCodeBlock(t *testing.T) { + t.Parallel() assert := assert.New(t) lines := []string{ diff --git a/internal/cli/peers.go b/internal/cli/peers.go index ee70a747b8..fbbca24fad 100644 --- a/internal/cli/peers.go +++ b/internal/cli/peers.go @@ -21,6 +21,7 @@ func (a *PeersCommand) MarkDown() string { "- [```peers remove```](./peers_remove.md): Disconnects the local client from a connected peer if exists.", "- [```peers status```](./peers_status.md): Display the status of a peer by its id.", } + return strings.Join(items, "\n\n") } diff --git a/internal/cli/peers_add.go b/internal/cli/peers_add.go index ae84f4e0c1..3df1a6b6cb 100644 --- a/internal/cli/peers_add.go +++ b/internal/cli/peers_add.go @@ -22,6 +22,7 @@ func (p *PeersAddCommand) MarkDown() string { "The ```peers add ``` command joins the local client to another remote peer.", p.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -79,5 +80,6 @@ func (c *PeersAddCommand) Run(args []string) int { c.UI.Error(err.Error()) return 1 } + return 0 } diff --git a/internal/cli/peers_list.go b/internal/cli/peers_list.go index 56dfdc317d..4a572447c1 100644 --- a/internal/cli/peers_list.go +++ b/internal/cli/peers_list.go @@ -21,6 +21,7 @@ func (p *PeersListCommand) MarkDown() string { "The ```peers list``` command lists the connected peers.", p.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -60,12 +61,14 @@ func (c *PeersListCommand) Run(args []string) int { req := &proto.PeersListRequest{} resp, err := borClt.PeersList(context.Background(), req) + if err != nil { c.UI.Error(err.Error()) return 1 } c.UI.Output(formatPeers(resp.Peers)) + return 0 } @@ -76,6 +79,7 @@ func formatPeers(peers []*proto.Peer) string { rows := make([]string, len(peers)+1) rows[0] = "ID|Enode|Name|Caps|Static|Trusted" + for i, d := range peers { enode := strings.TrimPrefix(d.Enode, "enode://") @@ -87,5 +91,6 @@ func formatPeers(peers []*proto.Peer) string { d.Static, d.Trusted) } + return formatList(rows) } diff --git a/internal/cli/peers_remove.go b/internal/cli/peers_remove.go index 5cd3796e3c..f53284c40c 100644 --- a/internal/cli/peers_remove.go +++ b/internal/cli/peers_remove.go @@ -22,6 +22,7 @@ func (p *PeersRemoveCommand) MarkDown() string { "The ```peers remove ``` command disconnects the local client from a connected peer if exists.", p.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -79,5 +80,6 @@ func (c *PeersRemoveCommand) Run(args []string) int { c.UI.Error(err.Error()) return 1 } + return 0 } diff --git a/internal/cli/peers_status.go b/internal/cli/peers_status.go index bb8d385291..f5d700a273 100644 --- a/internal/cli/peers_status.go +++ b/internal/cli/peers_status.go @@ -21,6 +21,7 @@ func (p *PeersStatusCommand) MarkDown() string { "The ```peers status ``` command displays the status of a peer by its id.", p.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } @@ -68,12 +69,14 @@ func (c *PeersStatusCommand) Run(args []string) int { Enode: args[0], } resp, err := borClt.PeersStatus(context.Background(), req) + if err != nil { c.UI.Error(err.Error()) return 1 } c.UI.Output(formatPeer(resp.Peer)) + return 0 } @@ -87,5 +90,6 @@ func formatPeer(peer *proto.Peer) string { fmt.Sprintf("Static|%v", peer.Static), fmt.Sprintf("Trusted|%v", peer.Trusted), }) + return base } diff --git a/internal/cli/status.go b/internal/cli/status.go index c4165b0a2e..2a8b7d7470 100644 --- a/internal/cli/status.go +++ b/internal/cli/status.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/internal/cli/server/proto" + "github.com/golang/protobuf/ptypes/empty" ) @@ -20,6 +21,7 @@ func (p *StatusCommand) MarkDown() string { "# Status", "The ```status``` command outputs the status of the client.", } + return strings.Join(items, "\n\n") } @@ -56,6 +58,7 @@ func (c *StatusCommand) Run(args []string) int { } c.UI.Output(printStatus(status)) + return 0 } @@ -69,6 +72,7 @@ func printStatus(status *proto.StatusResponse) string { forks := make([]string, len(status.Forks)+1) forks[0] = "Name|Block|Enabled" + for i, d := range status.Forks { forks[i+1] = fmt.Sprintf("%s|%d|%v", d.Name, d.Block, !d.Disabled) } @@ -92,5 +96,6 @@ func printStatus(status *proto.StatusResponse) string { "\nForks", formatList(forks), } + return strings.Join(full, "\n") } diff --git a/internal/cli/version.go b/internal/cli/version.go index 080cf41221..cd155f43a7 100644 --- a/internal/cli/version.go +++ b/internal/cli/version.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/params" + "github.com/mitchellh/cli" ) @@ -27,6 +28,7 @@ func (d *VersionCommand) MarkDown() string { "The ```bor version``` command outputs the version of the binary.", } items = append(items, examples...) + return strings.Join(items, "\n\n") } From 2e2557a2d004006e72be463d45a3b4a04c397cd2 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 24 May 2022 13:08:45 -0700 Subject: [PATCH 72/80] Enable prealloc check and improve address comparison --- .golangci.yml | 2 +- consensus/bor/api.go | 2 +- consensus/bor/bor.go | 19 ++++++++++--------- consensus/bor/merkle.go | 2 +- consensus/bor/snapshot.go | 3 +-- consensus/bor/validator_set.go | 2 +- internal/cli/attach.go | 5 +++-- 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index daea4e1e0b..b063984061 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -38,7 +38,7 @@ linters: - noctx #- nosprintfhostport # TODO: do we use IPv6? - paralleltest - # - prealloc + - prealloc - predeclared #- promlinter #- revive diff --git a/consensus/bor/api.go b/consensus/bor/api.go index 361e439bf7..364fc448b8 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -61,7 +61,7 @@ type difficultiesKV struct { } func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV { - var ss []difficultiesKV + ss := make([]difficultiesKV, 0, len(values)) for k, v := range values { ss = append(ss, difficultiesKV{k, v}) } diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index ada601f838..62336e73f0 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -472,10 +472,9 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t // nolint: gocognit func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { // Search for a snapshot in memory or on disk for checkpoints - var ( - headers []*types.Header - snap *Snapshot - ) + var snap *Snapshot + + headers := make([]*types.Header, 0, 16) //nolint:govet for snap == nil { @@ -549,6 +548,8 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co number, hash = number-1, header.ParentHash } + log.Info("Snapshot has been found in %d headers depth.", len(headers)) + // check if snapshot is nil if snap == nil { return nil, fmt.Errorf("Unknown error while retrieving snapshot at block number %v", number) @@ -701,7 +702,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e var succession int // if signer is not empty - if !bytes.Equal(c.signer.Bytes(), common.Address{}.Bytes()) { + if c.signer != (common.Address{}) { succession, err = snap.GetSignerSuccessionNumber(c.signer) if err != nil { return err @@ -1146,7 +1147,7 @@ func (c *Bor) fetchAndCommitSpan( } // get validators bytes - var validators []MinimalVal + validators := make([]MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators)) for _, val := range heimdallSpan.ValidatorSet.Validators { validators = append(validators, val.MinimalVal()) } @@ -1158,7 +1159,7 @@ func (c *Bor) fetchAndCommitSpan( } // get producers bytes - var producers []MinimalVal + producers := make([]MinimalVal, 0, len(heimdallSpan.SelectedProducers)) for _, val := range heimdallSpan.SelectedProducers { producers = append(producers, val.MinimalVal()) } @@ -1401,7 +1402,7 @@ func applyMessage( func validatorContains(a []*Validator, x *Validator) (*Validator, bool) { for _, n := range a { - if bytes.Equal(n.Address.Bytes(), x.Address.Bytes()) { + if n.Address == x.Address { return n, true } } @@ -1413,7 +1414,7 @@ func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator) v := oldValidatorSet oldVals := v.Validators - var changes []*Validator + changes := make([]*Validator, 0, len(oldVals)) for _, ov := range oldVals { if f, ok := validatorContains(newVals, ov); ok { diff --git a/consensus/bor/merkle.go b/consensus/bor/merkle.go index 5c61eb4a12..ef1b4eb87e 100644 --- a/consensus/bor/merkle.go +++ b/consensus/bor/merkle.go @@ -40,7 +40,7 @@ func convertTo32(input []byte) (output [32]byte) { } func convert(input []([32]byte)) [][]byte { - var output [][]byte + output := make([][]byte, 0, len(input)) for _, in := range input { newInput := make([]byte, len(in[:])) diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go index ef92cc99b4..606c28340b 100644 --- a/consensus/bor/snapshot.go +++ b/consensus/bor/snapshot.go @@ -1,7 +1,6 @@ package bor import ( - "bytes" "encoding/json" lru "github.com/hashicorp/golang-lru" @@ -208,7 +207,7 @@ func (s *Snapshot) signers() []common.Address { // Difficulty returns the difficulty for a particular signer at the current snapshot number func (s *Snapshot) Difficulty(signer common.Address) uint64 { // if signer is empty - if bytes.Equal(signer.Bytes(), common.Address{}.Bytes()) { + if signer == (common.Address{}) { return 1 } diff --git a/consensus/bor/validator_set.go b/consensus/bor/validator_set.go index 892891bbda..ee14ef2cb1 100644 --- a/consensus/bor/validator_set.go +++ b/consensus/bor/validator_set.go @@ -255,7 +255,7 @@ func (vals *ValidatorSet) GetByAddress(address common.Address) (index int, val * idx := sort.Search(len(vals.Validators), func(i int) bool { return bytes.Compare(address.Bytes(), vals.Validators[i].Address.Bytes()) <= 0 }) - if idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address.Bytes()) { + if idx < len(vals.Validators) && vals.Validators[idx].Address == address { return idx, vals.Validators[idx].Copy() } diff --git a/internal/cli/attach.go b/internal/cli/attach.go index 1aa888c12b..134a282180 100644 --- a/internal/cli/attach.go +++ b/internal/cli/attach.go @@ -182,9 +182,10 @@ func (c *AttachCommand) makeConsolePreloads() []string { return nil } // Otherwise resolve absolute paths and return them - var preloads []string + splitFlags := strings.Split(c.PreloadJSFlag, ",") + preloads := make([]string, 0, len(splitFlags)) - for _, file := range strings.Split(c.PreloadJSFlag, ",") { + for _, file := range splitFlags { preloads = append(preloads, strings.TrimSpace(file)) } From 5092006b27988adf9c2d2195c38ed967d4affd37 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 27 May 2022 14:40:04 -0700 Subject: [PATCH 73/80] Fix default Dockerfile for new CLI --- Dockerfile | 4 +++- consensus/bor/bor.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8af791ab3f..7a2770ce9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,9 @@ RUN apt-get update -y && apt-get upgrade -y \ WORKDIR ${BOR_DIR} COPY . . -RUN make bor-all +RUN make bor + +RUN cp build/bin/bor /usr/local/bin/ ENV SHELL /bin/bash EXPOSE 8545 8546 8547 30303 30303/udp diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 62336e73f0..9e43e67037 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -548,7 +548,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co number, hash = number-1, header.ParentHash } - log.Info("Snapshot has been found in %d headers depth.", len(headers)) + log.Info("Snapshot has been found in", "headers depth", len(headers)) // check if snapshot is nil if snap == nil { From 3ae87c0d464981a82bf4912618baa029c9b5b1ea Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 26 May 2022 14:36:12 -0700 Subject: [PATCH 74/80] Read static-nodes and trusted-nodes from default files if not specified in CLI --- internal/cli/server/config.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index f3ab7ed0d6..a93c4f057f 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -935,9 +935,15 @@ func (c *Config) buildNode() (*node.Config, error) { if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil { return nil, err } + if len(cfg.P2P.StaticNodes) == 0 { + cfg.P2P.StaticNodes = cfg.StaticNodes() + } if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil { return nil, err } + if len(cfg.P2P.TrustedNodes) == 0 { + cfg.P2P.TrustedNodes = cfg.TrustedNodes() + } } if c.P2P.NoDiscover { From 4cec5f01c3e8530b7a193479a5f88f05491d5590 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 26 May 2022 15:36:38 -0700 Subject: [PATCH 75/80] Add ability to parse legacy genesis file --- internal/cli/server/chains/chain.go | 15 ++++ internal/cli/server/chains/chain_test.go | 10 +++ .../chains/test_files/chain_legacy_test.json | 83 +++++++++++++++++++ .../server/chains/test_files/wrong_chain.json | 1 + 4 files changed, 109 insertions(+) create mode 100644 internal/cli/server/chains/test_files/chain_legacy_test.json create mode 100644 internal/cli/server/chains/test_files/wrong_chain.json diff --git a/internal/cli/server/chains/chain.go b/internal/cli/server/chains/chain.go index 4fc7bad5d1..32f5159b38 100644 --- a/internal/cli/server/chains/chain.go +++ b/internal/cli/server/chains/chain.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/log" ) type Chain struct { @@ -59,5 +60,19 @@ func importChain(content []byte) (*Chain, error) { return nil, err } + if chain.Genesis == nil { + log.Info("Try reading as legacy genesis") + var genesis core.Genesis + if err := json.Unmarshal(content, &genesis); err != nil { + return nil, err + } + if genesis.Config != nil { + chain.Genesis = &genesis + chain.NetworkId = genesis.Config.ChainID.Uint64() + } else { + return nil, fmt.Errorf("unable to parse chain config") + } + } + return chain, nil } diff --git a/internal/cli/server/chains/chain_test.go b/internal/cli/server/chains/chain_test.go index 0f309b2919..8f57b7d220 100644 --- a/internal/cli/server/chains/chain_test.go +++ b/internal/cli/server/chains/chain_test.go @@ -18,6 +18,16 @@ func TestChain_ImportFromFile(t *testing.T) { args: args{filename: "test_files/chain_test.json"}, wantErr: false, }, + { + name: "ImportFromFile correct legacy json file", + args: args{filename: "test_files/chain_legacy_test.json"}, + wantErr: false, + }, + { + name: "ImportFromFile wrong json file", + args: args{filename: "test_files/wrong_chain.json"}, + wantErr: true, + }, { name: "ImportFromFile nonexistent json file", args: args{filename: "test_files/chain_test_nonexistent.json"}, diff --git a/internal/cli/server/chains/test_files/chain_legacy_test.json b/internal/cli/server/chains/test_files/chain_legacy_test.json new file mode 100644 index 0000000000..5702eaca40 --- /dev/null +++ b/internal/cli/server/chains/test_files/chain_legacy_test.json @@ -0,0 +1,83 @@ +{ + "config":{ + "chainId":80001, + "homesteadBlock":0, + "daoForkSupport":true, + "eip150Block":0, + "eip150Hash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":2722000, + "muirGlacierBlock":2722000, + "berlinBlock":13996000, + "londonBlock":13996000, + "bor":{ + "period":{ + "0":2 + }, + "producerDelay":6, + "sprint":64, + "backupMultiplier":{ + "0":2 + }, + "validatorContract":"0x0000000000000000000000000000000000001000", + "stateReceiverContract":"0x0000000000000000000000000000000000001001", + "overrideStateSyncRecords":null, + "blockAlloc":{ + "22244000":{ + "0000000000000000000000000000000000001010":{ + "balance":"0x0", + "code":"0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611548565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154e565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115db565b005b348015610b2e57600080fd5b50610b376115f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161e90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da96023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163e90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d866023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165d565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611755565b90505b92915050565b6040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b12565b611be8565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611dcc605291396040516020018082805190602001908083835b6020831061159d578051825260208201915060208101905060208303925061157a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e3611381565b6115ec57600080fd5b6115f58161165d565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162d57600080fd5b600082840390508091505092915050565b60008082840190508381101561165357600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169757600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d557600080fd5b505afa1580156117e9573d6000803e3d6000fd5b505050506040513d60208110156117ff57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561189157600080fd5b505afa1580156118a5573d6000803e3d6000fd5b505050506040513d60208110156118bb57600080fd5b810190808051906020019092919050505090506118d9868686611c32565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119e157600080fd5b505afa1580156119f5573d6000803e3d6000fd5b505050506040513d6020811015611a0b57600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9957600080fd5b505afa158015611aad573d6000803e3d6000fd5b505050506040513d6020811015611ac357600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b60208310611b645780518252602082019150602081019050602083039250611b41565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d1a573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820ccd6c2a9c259832bbb367986ee06cd87af23022681b0cb22311a864b701d939564736f6c63430005100032" + } + } + }, + "burntContract":{ + "22640000":"0x70bcA57F4579f58670aB2d18Ef16e02C17553C38" + }, + "jaipurBlock":22770000 + } + }, + "nonce":"0x0", + "timestamp":"0x5ce28211", + "extraData":"0x", + "gasLimit":"0x989680", + "difficulty":"0x1", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0000000000000000000000000000000000001000":{ + "code":"0x608060405234801561001057600080fd5b50600436106101f05760003560e01c806360c8614d1161010f578063af26aa96116100a2578063d5b844eb11610071578063d5b844eb14610666578063dcf2793a14610684578063e3b7c924146106b6578063f59cf565146106d4576101f0565b8063af26aa96146105c7578063b71d7a69146105e7578063b7ab4db514610617578063c1b3c91914610636576101f0565b806370ba5707116100de57806370ba57071461052b57806398ab2b621461055b5780639d11b80714610579578063ae756451146105a9576101f0565b806360c8614d1461049c57806365b3a1e2146104bc57806366332354146104db578063687a9bd6146104f9576101f0565b80633434735f1161018757806344d6528f1161015657806344d6528f146103ee5780634dbc959f1461041e57806355614fcc1461043c578063582a8d081461046c576101f0565b80633434735f1461035257806335ddfeea1461037057806343ee8213146103a057806344c15cb1146103be576101f0565b806323f2a73f116101c357806323f2a73f146102a45780632bc06564146102d45780632de3a180146102f25780632eddf35214610322576101f0565b8063047a6c5b146101f55780630c35b1cb146102275780631270b5741461025857806323c2a2b414610288575b600080fd5b61020f600480360361020a9190810190612b24565b610706565b60405161021e93929190613463565b60405180910390f35b610241600480360361023c9190810190612b24565b61075d565b60405161024f929190613284565b60405180910390f35b610272600480360361026d9190810190612b4d565b610939565b60405161027f91906132bb565b60405180910390f35b6102a2600480360361029d9190810190612c2c565b610a91565b005b6102be60048036036102b99190810190612b4d565b61112a565b6040516102cb91906132bb565b60405180910390f35b6102dc611281565b6040516102e99190613411565b60405180910390f35b61030c60048036036103079190810190612a81565b611286565b60405161031991906132d6565b60405180910390f35b61033c60048036036103379190810190612b24565b611307565b6040516103499190613411565b60405180910390f35b61035a611437565b6040516103679190613269565b60405180910390f35b61038a60048036036103859190810190612abd565b61144f565b60405161039791906132bb565b60405180910390f35b6103a861151a565b6040516103b591906132d6565b60405180910390f35b6103d860048036036103d39190810190612b89565b611531565b6040516103e59190613411565b60405180910390f35b61040860048036036104039190810190612b4d565b611619565b60405161041591906133f6565b60405180910390f35b610426611781565b6040516104339190613411565b60405180910390f35b61045660048036036104519190810190612a06565b611791565b60405161046391906132bb565b60405180910390f35b61048660048036036104819190810190612a2f565b6117ab565b60405161049391906132d6565b60405180910390f35b6104a4611829565b6040516104b393929190613463565b60405180910390f35b6104c461189d565b6040516104d2929190613284565b60405180910390f35b6104e3611b6e565b6040516104f09190613411565b60405180910390f35b610513600480360361050e9190810190612bf0565b611b73565b6040516105229392919061342c565b60405180910390f35b61054560048036036105409190810190612a06565b611bd7565b60405161055291906132bb565b60405180910390f35b610563611bf1565b60405161057091906132d6565b60405180910390f35b610593600480360361058e9190810190612b24565b611c08565b6040516105a09190613411565b60405180910390f35b6105b1611d39565b6040516105be91906132d6565b60405180910390f35b6105cf611d50565b6040516105de93929190613463565b60405180910390f35b61060160048036036105fc9190810190612b24565b611db1565b60405161060e9190613411565b60405180910390f35b61061f611eb1565b60405161062d929190613284565b60405180910390f35b610650600480360361064b9190810190612b24565b611ec5565b60405161065d9190613411565b60405180910390f35b61066e611ee6565b60405161067b919061349a565b60405180910390f35b61069e60048036036106999190810190612bf0565b611eeb565b6040516106ad9392919061342c565b60405180910390f35b6106be611f4f565b6040516106cb9190613411565b60405180910390f35b6106ee60048036036106e99190810190612b24565b611f61565b6040516106fd93929190613463565b60405180910390f35b60008060006002600085815260200190815260200160002060000154600260008681526020019081526020016000206001015460026000878152602001908152602001600020600201549250925092509193909250565b60608060ff83116107795761077061189d565b91509150610934565b600061078484611db1565b9050606060016000838152602001908152602001600020805490506040519080825280602002602001820160405280156107cd5781602001602082028038833980820191505090505b509050606060016000848152602001908152602001600020805490506040519080825280602002602001820160405280156108175781602001602082028038833980820191505090505b50905060008090505b60016000858152602001908152602001600020805490508110156109295760016000858152602001908152602001600020818154811061085c57fe5b906000526020600020906003020160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683828151811061089a57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001600085815260200190815260200160002081815481106108f257fe5b90600052602060002090600302016001015482828151811061091057fe5b6020026020010181815250508080600101915050610820565b508181945094505050505b915091565b6000606060016000858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015610a0c578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190610970565b50505050905060008090505b8151811015610a84578373ffffffffffffffffffffffffffffffffffffffff16828281518110610a4457fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff161415610a7757600192505050610a8b565b8080600101915050610a18565b5060009150505b92915050565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0a906133d6565b60405180910390fd5b6000610b1d611781565b90506000811415610b3157610b30611f8b565b5b610b456001826122ac90919063ffffffff16565b8814610b86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7d90613356565b60405180910390fd5b868611610bc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bbf906133b6565b60405180910390fd5b6000604060018989030181610bd957fe5b0614610c1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1190613396565b60405180910390fd5b8660026000838152602001908152602001600020600101541115610c73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6a90613336565b60405180910390fd5b6000600260008a81526020019081526020016000206000015414610ccc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc390613376565b60405180910390fd5b604051806060016040528089815260200188815260200187815250600260008a8152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050600388908060018154018082558091505090600182039060005260206000200160009091929091909150555060008060008a815260200190815260200160002081610d669190612800565b506000600160008a815260200190815260200160002081610d879190612800565b506060610ddf610dda87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506122cb565b6122f9565b905060008090505b8151811015610f51576060610e0e838381518110610e0157fe5b60200260200101516122f9565b90506000808c81526020019081526020016000208054809190600101610e349190612800565b506040518060600160405280610e5d83600081518110610e5057fe5b60200260200101516123d6565b8152602001610e7f83600181518110610e7257fe5b60200260200101516123d6565b8152602001610ea183600281518110610e9457fe5b6020026020010151612447565b73ffffffffffffffffffffffffffffffffffffffff168152506000808d81526020019081526020016000208381548110610ed757fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050508080600101915050610de7565b506060610fa9610fa486868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506122cb565b6122f9565b905060008090505b815181101561111d576060610fd8838381518110610fcb57fe5b60200260200101516122f9565b9050600160008d81526020019081526020016000208054809190600101610fff9190612800565b5060405180606001604052806110288360008151811061101b57fe5b60200260200101516123d6565b815260200161104a8360018151811061103d57fe5b60200260200101516123d6565b815260200161106c8360028151811061105f57fe5b6020026020010151612447565b73ffffffffffffffffffffffffffffffffffffffff16815250600160008e815260200190815260200160002083815481106110a357fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050508080600101915050610fb1565b5050505050505050505050565b60006060600080858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156111fc578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611160565b50505050905060008090505b8151811015611274578373ffffffffffffffffffffffffffffffffffffffff1682828151811061123457fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff1614156112675760019250505061127b565b8080600101915050611208565b5060009150505b92915050565b604081565b60006002600160f81b84846040516020016112a3939291906131d6565b6040516020818303038152906040526040516112bf9190613213565b602060405180830381855afa1580156112dc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506112ff9190810190612a58565b905092915050565b60006060600080848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156113d9578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250508152602001906001019061133d565b505050509050600080905060008090505b825181101561142c5761141d83828151811061140257fe5b602002602001015160200151836122ac90919063ffffffff16565b915080806001019150506113ea565b508092505050919050565b73fffffffffffffffffffffffffffffffffffffffe81565b600080600080859050600060218087518161146657fe5b04029050600081111561147f5761147c876117ab565b91505b6000602190505b818111611509576000600182038801519050818801519550806000602081106114ab57fe5b1a60f81b9450600060f81b857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156114f0576114e98685611286565b93506114fd565b6114fa8487611286565b93505b50602181019050611486565b508782149450505050509392505050565b60405161152690613254565b604051809103902081565b60008060009050600080905060008090505b84518167ffffffffffffffff16101561160c57606061156e868367ffffffffffffffff16604161246a565b9050600061158582896124f690919063ffffffff16565b905061158f612832565b6115998a83611619565b90506115a58a8361112a565b80156115dc57508473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16115b156115fe578194506115fb8160200151876122ac90919063ffffffff16565b95505b505050604181019050611543565b5081925050509392505050565b611621612832565b6060600080858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156116f1578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611655565b50505050905060008090505b8151811015611779578373ffffffffffffffffffffffffffffffffffffffff1682828151811061172957fe5b60200260200101516040015173ffffffffffffffffffffffffffffffffffffffff16141561176c5781818151811061175d57fe5b60200260200101519250611779565b80806001019150506116fd565b505092915050565b600061178c43611db1565b905090565b60006117a461179e611781565b8361112a565b9050919050565b60006002600060f81b836040516020016117c69291906131aa565b6040516020818303038152906040526040516117e29190613213565b602060405180830381855afa1580156117ff573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506118229190810190612a58565b9050919050565b60008060008061184a600161183c611781565b6122ac90919063ffffffff16565b905060026000828152602001908152602001600020600001546002600083815260200190815260200160002060010154600260008481526020019081526020016000206002015493509350935050909192565b606080606060056040519080825280602002602001820160405280156118d25781602001602082028038833980820191505090505b50905073c26880a0af2ea0c7e8130e6ec47af756465452e8816000815181106118f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073be188d6641e8b680743a4815dfa0f6208038960f8160018151811061195357fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073c275dc8be39f50d12f66b6a63629c39da5bae5bd816002815181106119af57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073f903ba9e006193c1527bfbe65fe2123704ea3f9981600381518110611a0b57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073928ed6a3e94437bbd316ccad78479f1d163a6a8c81600481518110611a6757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060606005604051908082528060200260200182016040528015611ad35781602001602082028038833980820191505090505b50905061271081600081518110611ae657fe5b60200260200101818152505061271081600181518110611b0257fe5b60200260200101818152505061271081600281518110611b1e57fe5b60200260200101818152505061271081600381518110611b3a57fe5b60200260200101818152505061271081600481518110611b5657fe5b60200260200101818152505081819350935050509091565b60ff81565b60016020528160005260406000208181548110611b8c57fe5b9060005260206000209060030201600091509150508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b6000611bea611be4611781565b83610939565b9050919050565b604051611bfd9061322a565b604051809103902081565b6000606060016000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611cdb578382906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190611c3f565b505050509050600080905060008090505b8251811015611d2e57611d1f838281518110611d0457fe5b602002602001015160200151836122ac90919063ffffffff16565b91508080600101915050611cec565b508092505050919050565b604051611d459061323f565b604051809103902081565b600080600080611d5e611781565b905060026000828152602001908152602001600020600001546002600083815260200190815260200160002060010154600260008481526020019081526020016000206002015493509350935050909192565b60008060038054905090505b6000811115611e7157611dce612869565b6002600060036001850381548110611de257fe5b906000526020600020015481526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905083816020015111158015611e3f57506000816040015114155b8015611e4f575080604001518411155b15611e6257806000015192505050611eac565b50808060019003915050611dbd565b5060006003805490501115611ea757600360016003805490500381548110611e9557fe5b90600052602060002001549050611eac565b600090505b919050565b606080611ebd4361075d565b915091509091565b60038181548110611ed257fe5b906000526020600020016000915090505481565b600281565b60006020528160005260406000208181548110611f0457fe5b9060005260206000209060030201600091509150508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905083565b600060404381611f5b57fe5b04905090565b60026020528060005260406000206000915090508060000154908060010154908060020154905083565b606080611f9661189d565b8092508193505050600080905060405180606001604052808281526020016000815260200160ff81525060026000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155905050600381908060018154018082558091505090600182039060005260206000200160009091929091909150555060008060008381526020019081526020016000208161203f9190612800565b50600060016000838152602001908152602001600020816120609190612800565b5060008090505b83518110156121825760008083815260200190815260200160002080548091906001016120949190612800565b5060405180606001604052808281526020018483815181106120b257fe5b602002602001015181526020018583815181106120cb57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16815250600080848152602001908152602001600020828154811061210957fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508080600101915050612067565b5060008090505b83518110156122a6576001600083815260200190815260200160002080548091906001016121b79190612800565b5060405180606001604052808281526020018483815181106121d557fe5b602002602001015181526020018583815181106121ee57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1681525060016000848152602001908152602001600020828154811061222d57fe5b9060005260206000209060030201600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508080600101915050612189565b50505050565b6000808284019050838110156122c157600080fd5b8091505092915050565b6122d361288a565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061230482612600565b61230d57600080fd5b60006123188361264e565b905060608160405190808252806020026020018201604052801561235657816020015b6123436128a4565b81526020019060019003908161233b5790505b509050600061236885602001516126bf565b8560200151019050600080600090505b848110156123c95761238983612748565b91506040518060400160405280838152602001848152508482815181106123ac57fe5b602002602001018190525081830192508080600101915050612378565b5082945050505050919050565b60008082600001511180156123f057506021826000015111155b6123f957600080fd5b600061240883602001516126bf565b9050600081846000015103905060008083866020015101905080519150602083101561243b57826020036101000a820491505b81945050505050919050565b6000601582600001511461245a57600080fd5b612463826123d6565b9050919050565b60608183018451101561247c57600080fd5b6060821560008114612499576040519150602082016040526124ea565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156124d757805183526020830192506020810190506124ba565b50868552601f19601f8301166040525050505b50809150509392505050565b600080600080604185511461251157600093505050506125fa565b602085015192506040850151915060ff6041860151169050601b8160ff16101561253c57601b810190505b601b8160ff16141580156125545750601c8160ff1614155b1561256557600093505050506125fa565b60006001878386866040516000815260200160405260405161258a94939291906132f1565b6020604051602081039080840390855afa1580156125ac573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125f257600080fd5b809450505050505b92915050565b600080826000015114156126175760009050612649565b60008083602001519050805160001a915060c060ff168260ff16101561264257600092505050612649565b6001925050505b919050565b6000808260000151141561266557600090506126ba565b6000809050600061267984602001516126bf565b84602001510190506000846000015185602001510190505b808210156126b3576126a282612748565b820191508280600101935050612691565b8293505050505b919050565b600080825160001a9050608060ff168110156126df576000915050612743565b60b860ff16811080612704575060c060ff168110158015612703575060f860ff1681105b5b15612713576001915050612743565b60c060ff168110156127335760018060b80360ff16820301915050612743565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561276957600191506127f6565b60b860ff16811015612786576001608060ff1682030191506127f5565b60c060ff168110156127b65760b78103600185019450806020036101000a855104600182018101935050506127f4565b60f860ff168110156127d357600160c060ff1682030191506127f3565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b81548183558181111561282d5760030281600302836000526020600020918201910161282c91906128be565b5b505050565b60405180606001604052806000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b60405180606001604052806000815260200160008152602001600081525090565b604051806040016040528060008152602001600081525090565b604051806040016040528060008152602001600081525090565b61291191905b8082111561290d5760008082016000905560018201600090556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506003016128c4565b5090565b90565b60008135905061292381613693565b92915050565b600081359050612938816136aa565b92915050565b60008151905061294d816136aa565b92915050565b60008083601f84011261296557600080fd5b8235905067ffffffffffffffff81111561297e57600080fd5b60208301915083600182028301111561299657600080fd5b9250929050565b600082601f8301126129ae57600080fd5b81356129c16129bc826134e2565b6134b5565b915080825260208301602083018583830111156129dd57600080fd5b6129e883828461363d565b50505092915050565b600081359050612a00816136c1565b92915050565b600060208284031215612a1857600080fd5b6000612a2684828501612914565b91505092915050565b600060208284031215612a4157600080fd5b6000612a4f84828501612929565b91505092915050565b600060208284031215612a6a57600080fd5b6000612a788482850161293e565b91505092915050565b60008060408385031215612a9457600080fd5b6000612aa285828601612929565b9250506020612ab385828601612929565b9150509250929050565b600080600060608486031215612ad257600080fd5b6000612ae086828701612929565b9350506020612af186828701612929565b925050604084013567ffffffffffffffff811115612b0e57600080fd5b612b1a8682870161299d565b9150509250925092565b600060208284031215612b3657600080fd5b6000612b44848285016129f1565b91505092915050565b60008060408385031215612b6057600080fd5b6000612b6e858286016129f1565b9250506020612b7f85828601612914565b9150509250929050565b600080600060608486031215612b9e57600080fd5b6000612bac868287016129f1565b9350506020612bbd86828701612929565b925050604084013567ffffffffffffffff811115612bda57600080fd5b612be68682870161299d565b9150509250925092565b60008060408385031215612c0357600080fd5b6000612c11858286016129f1565b9250506020612c22858286016129f1565b9150509250929050565b600080600080600080600060a0888a031215612c4757600080fd5b6000612c558a828b016129f1565b9750506020612c668a828b016129f1565b9650506040612c778a828b016129f1565b955050606088013567ffffffffffffffff811115612c9457600080fd5b612ca08a828b01612953565b9450945050608088013567ffffffffffffffff811115612cbf57600080fd5b612ccb8a828b01612953565b925092505092959891949750929550565b6000612ce88383612d0c565b60208301905092915050565b6000612d00838361317d565b60208301905092915050565b612d15816135b2565b82525050565b612d24816135b2565b82525050565b6000612d358261352e565b612d3f8185613569565b9350612d4a8361350e565b8060005b83811015612d7b578151612d628882612cdc565b9750612d6d8361354f565b925050600181019050612d4e565b5085935050505092915050565b6000612d9382613539565b612d9d818561357a565b9350612da88361351e565b8060005b83811015612dd9578151612dc08882612cf4565b9750612dcb8361355c565b925050600181019050612dac565b5085935050505092915050565b612def816135c4565b82525050565b612e06612e01826135d0565b61367f565b82525050565b612e15816135fc565b82525050565b612e2c612e27826135fc565b613689565b82525050565b6000612e3d82613544565b612e47818561358b565b9350612e5781856020860161364c565b80840191505092915050565b6000612e706004836135a7565b91507f766f7465000000000000000000000000000000000000000000000000000000006000830152600482019050919050565b6000612eb0602d83613596565b91507f537461727420626c6f636b206d7573742062652067726561746572207468616e60008301527f2063757272656e74207370616e000000000000000000000000000000000000006020830152604082019050919050565b6000612f16600f83613596565b91507f496e76616c6964207370616e20696400000000000000000000000000000000006000830152602082019050919050565b6000612f56601383613596565b91507f5370616e20616c726561647920657869737473000000000000000000000000006000830152602082019050919050565b6000612f96604583613596565b91507f446966666572656e6365206265747765656e20737461727420616e6420656e6460008301527f20626c6f636b206d75737420626520696e206d756c7469706c6573206f66207360208301527f7072696e740000000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000613022602a83613596565b91507f456e6420626c6f636b206d7573742062652067726561746572207468616e207360008301527f7461727420626c6f636b000000000000000000000000000000000000000000006020830152604082019050919050565b6000613088601283613596565b91507f4e6f742053797374656d204164646573732100000000000000000000000000006000830152602082019050919050565b60006130c86005836135a7565b91507f38303030310000000000000000000000000000000000000000000000000000006000830152600582019050919050565b6000613108600e836135a7565b91507f6865696d64616c6c2d38303030310000000000000000000000000000000000006000830152600e82019050919050565b606082016000820151613151600085018261317d565b506020820151613164602085018261317d565b5060408201516131776040850182612d0c565b50505050565b61318681613626565b82525050565b61319581613626565b82525050565b6131a481613630565b82525050565b60006131b68285612df5565b6001820191506131c68284612e1b565b6020820191508190509392505050565b60006131e28286612df5565b6001820191506131f28285612e1b565b6020820191506132028284612e1b565b602082019150819050949350505050565b600061321f8284612e32565b915081905092915050565b600061323582612e63565b9150819050919050565b600061324a826130bb565b9150819050919050565b600061325f826130fb565b9150819050919050565b600060208201905061327e6000830184612d1b565b92915050565b6000604082019050818103600083015261329e8185612d2a565b905081810360208301526132b28184612d88565b90509392505050565b60006020820190506132d06000830184612de6565b92915050565b60006020820190506132eb6000830184612e0c565b92915050565b60006080820190506133066000830187612e0c565b613313602083018661319b565b6133206040830185612e0c565b61332d6060830184612e0c565b95945050505050565b6000602082019050818103600083015261334f81612ea3565b9050919050565b6000602082019050818103600083015261336f81612f09565b9050919050565b6000602082019050818103600083015261338f81612f49565b9050919050565b600060208201905081810360008301526133af81612f89565b9050919050565b600060208201905081810360008301526133cf81613015565b9050919050565b600060208201905081810360008301526133ef8161307b565b9050919050565b600060608201905061340b600083018461313b565b92915050565b6000602082019050613426600083018461318c565b92915050565b6000606082019050613441600083018661318c565b61344e602083018561318c565b61345b6040830184612d1b565b949350505050565b6000606082019050613478600083018661318c565b613485602083018561318c565b613492604083018461318c565b949350505050565b60006020820190506134af600083018461319b565b92915050565b6000604051905081810181811067ffffffffffffffff821117156134d857600080fd5b8060405250919050565b600067ffffffffffffffff8211156134f957600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006135bd82613606565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b8381101561366a57808201518184015260208101905061364f565b83811115613679576000848401525b50505050565b6000819050919050565b6000819050919050565b61369c816135b2565b81146136a757600080fd5b50565b6136b3816135fc565b81146136be57600080fd5b50565b6136ca81613626565b81146136d557600080fd5b5056fea365627a7a723158208f52ee07630ffe523cc6ad3e15f437f973dcfa36729cd697f9b0fc4a145a48f06c6578706572696d656e74616cf564736f6c634300050b0040", + "balance":"0x0" + }, + "0000000000000000000000000000000000001001":{ + "code":"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806319494a17146100465780633434735f146100e15780635407ca671461012b575b600080fd5b6100c76004803603604081101561005c57600080fd5b81019080803590602001909291908035906020019064010000000081111561008357600080fd5b82018360208201111561009557600080fd5b803590602001918460018302840111640100000000831117156100b757600080fd5b9091929391929390505050610149565b604051808215151515815260200191505060405180910390f35b6100e961047a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610133610492565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061025761025285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610498565b6104c6565b905060006102788260008151811061026b57fe5b60200260200101516105a3565b905080600160005401146102f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103248360018151811061031757fe5b6020026020010151610614565b905060606103458460028151811061033857fe5b6020026020010151610637565b9050610350826106c3565b1561046f576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103aa57808201518184015260208101905061038f565b50505050905090810190601f1680156103d75780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f1965050505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104a0610943565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606104d1826106dc565b6104da57600080fd5b60006104e58361072a565b905060608160405190808252806020026020018201604052801561052357816020015b61051061095d565b8152602001906001900390816105085790505b5090506000610535856020015161079b565b8560200151019050600080600090505b848110156105965761055683610824565b915060405180604001604052808381526020018481525084828151811061057957fe5b602002602001018190525081830192508080600101915050610545565b5082945050505050919050565b60008082600001511180156105bd57506021826000015111155b6105c657600080fd5b60006105d5836020015161079b565b9050600081846000015103905060008083866020015101905080519150602083101561060857826020036101000a820491505b81945050505050919050565b6000601582600001511461062757600080fd5b610630826105a3565b9050919050565b6060600082600001511161064a57600080fd5b6000610659836020015161079b565b905060008184600001510390506060816040519080825280601f01601f19166020018201604052801561069b5781602001600182028038833980820191505090505b50905060008160200190506106b78487602001510182856108dc565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b600080826000015114156106f35760009050610725565b60008083602001519050805160001a915060c060ff168260ff16101561071e57600092505050610725565b6001925050505b919050565b600080826000015114156107415760009050610796565b60008090506000610755846020015161079b565b84602001510190506000846000015185602001510190505b8082101561078f5761077e82610824565b82019150828060010193505061076d565b8293505050505b919050565b600080825160001a9050608060ff168110156107bb57600091505061081f565b60b860ff168110806107e0575060c060ff1681101580156107df575060f860ff1681105b5b156107ef57600191505061081f565b60c060ff1681101561080f5760018060b80360ff1682030191505061081f565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561084557600191506108d2565b60b860ff16811015610862576001608060ff1682030191506108d1565b60c060ff168110156108925760b78103600185019450806020036101000a855104600182018101935050506108d0565b60f860ff168110156108af57600160c060ff1682030191506108cf565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b60008114156108ea5761093e565b5b602060ff16811061091a5782518252602060ff1683019250602060ff1682019150602060ff16810390506108eb565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a7231582083fbdacb76f32b4112d0f7db9a596937925824798a0026ba0232322390b5263764736f6c634300050b0032", + "balance":"0x0" + }, + "0000000000000000000000000000000000001010":{ + "code":"0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610e06565b005b3480156103eb57600080fd5b506103f4610f58565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f61565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061111d565b005b3480156104e857600080fd5b506104f16111ec565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b50610548611212565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611238565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b50610604611259565b005b34801561061257600080fd5b5061061b611329565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061132f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b506107586114b4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af6114dd565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de611534565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e61156d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506115aa565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b506109646115d0565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b810190808035906020019092919050505061165d565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919050505061167d565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a6561169d565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a906116a4565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb6116aa565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611737565b005b348015610b2e57600080fd5b50610b37611754565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b6000808511610c4857600080fd5b6000831480610c575750824311155b610cc9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5369676e6174757265206973206578706972656400000000000000000000000081525060200191505060405180910390fd5b6000610cd73387878761167d565b9050600015156005600083815260200190815260200160002060009054906101000a900460ff16151514610d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f536967206465616374697661746564000000000000000000000000000000000081525060200191505060405180910390fd5b60016005600083815260200190815260200160002060006101000a81548160ff021916908315150217905550610ded8189898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061132f565b9150610dfa82848861177a565b50509695505050505050565b60003390506000610e1682611238565b9050610e2d83600654611b3790919063ffffffff16565b600681905550600083118015610e4257508234145b610eb4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610f3087611238565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610f696114dd565b610f7257600080fd5b600081118015610faf5750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b611004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611e636023913960400191505060405180910390fd5b600061100f83611238565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f1935050505015801561105c573d6000803e3d6000fd5b5061107283600654611b5790919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f685856110f489611238565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611183576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611e406023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506111e882611b76565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b6112616114dd565b61126a57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b600080600080604185511461134a57600093505050506114ae565b602085015192506040850151915060ff6041860151169050601b8160ff16101561137557601b810190505b601b8160ff161415801561138d5750601c8160ff1614155b1561139e57600093505050506114ae565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156113fb573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156114aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b60008134146115bc57600090506115ca565b6115c733848461177a565b90505b92915050565b6040518060800160405280605b8152602001611ed8605b91396040516020018082805190602001908083835b6020831061161f57805182526020820191506020810190506020830392506115fc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061169361168e86868686611c6e565b611d44565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611e86605291396040516020018082805190602001908083835b602083106116f957805182526020820191506020810190506020830392506116d6565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b61173f6114dd565b61174857600080fd5b61175181611b76565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117fa57600080fd5b505afa15801561180e573d6000803e3d6000fd5b505050506040513d602081101561182457600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156118b657600080fd5b505afa1580156118ca573d6000803e3d6000fd5b505050506040513d60208110156118e057600080fd5b810190808051906020019092919050505090506118fe868686611d8e565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a0657600080fd5b505afa158015611a1a573d6000803e3d6000fd5b505050506040513d6020811015611a3057600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611abe57600080fd5b505afa158015611ad2573d6000803e3d6000fd5b505050506040513d6020811015611ae857600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b600082821115611b4657600080fd5b600082840390508091505092915050565b600080828401905083811015611b6c57600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611bb057600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000806040518060800160405280605b8152602001611ed8605b91396040516020018082805190602001908083835b60208310611cc05780518252602082019150602081019050602083039250611c9d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611dd4573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158208f81700133738d766ae3d68af591ad588b0125bd91449192179f460893f79f6b64736f6c634300050b0032", + "balance":"0x204fcd4f31349d83b6e00000" + }, + "928ed6a3e94437bbd316ccad78479f1d163a6a8c":{ + "balance":"0x3635c9adc5dea00000" + }, + "be188d6641e8b680743a4815dfa0f6208038960f":{ + "balance":"0x3635c9adc5dea00000" + }, + "c26880a0af2ea0c7e8130e6ec47af756465452e8":{ + "balance":"0x3635c9adc5dea00000" + }, + "c275dc8be39f50d12f66b6a63629c39da5bae5bd":{ + "balance":"0x3635c9adc5dea00000" + }, + "f903ba9e006193c1527bfbe65fe2123704ea3f99":{ + "balance":"0x3635c9adc5dea00000" + } + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":null +} diff --git a/internal/cli/server/chains/test_files/wrong_chain.json b/internal/cli/server/chains/test_files/wrong_chain.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/internal/cli/server/chains/test_files/wrong_chain.json @@ -0,0 +1 @@ +{} \ No newline at end of file From 96ac8d16d4dc66c6eb4d28c8c7e9a70063d330b5 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 31 May 2022 18:52:18 -0700 Subject: [PATCH 76/80] Overwrite default config with CLI input even when the input value is considered as empty This change will fix two issues: 1. When CLI sets a flag to an empty value in Go, e.g. 0 as to Uint64, the flag will be skipped and never set correctly. This problem could be solved by using option "WithOverwriteWithEmptyValue" when merge two configs. 2. The default non-empty value in server config will be overwritten to an empty value after flag initialization. This problem is solved by explicitly providing default value to all flags that have a default value option. --- internal/cli/server/config.go | 7 +- internal/cli/server/config_test.go | 5 +- internal/cli/server/flags.go | 652 ++++++++++++++++------------- 3 files changed, 366 insertions(+), 298 deletions(-) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index a93c4f057f..4c17a58fc8 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -956,14 +956,9 @@ func (c *Config) buildNode() (*node.Config, error) { func (c *Config) Merge(cc ...*Config) error { for _, elem := range cc { - if err := mergo.Merge(c, elem, mergo.WithOverride, mergo.WithAppendSlice); err != nil { + if err := mergo.Merge(c, elem, mergo.WithOverwriteWithEmptyValue, mergo.WithAppendSlice); err != nil { return fmt.Errorf("failed to merge configurations: %v", err) } - - // override max peers - if elem.P2P.MaxPeers == 0 { - c.P2P.MaxPeers = 0 - } } return nil } diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go index c897fa789c..7368478123 100644 --- a/internal/cli/server/config_test.go +++ b/internal/cli/server/config_test.go @@ -54,14 +54,11 @@ func TestConfigMerge(t *testing.T) { } expected := &Config{ Chain: "1", - NoSnapshot: true, + NoSnapshot: false, RequiredBlocks: map[string]string{ "a": "b", "b": "c", }, - TxPool: &TxPoolConfig{ - LifeTime: 5 * time.Second, - }, P2P: &P2PConfig{ MaxPeers: 10, Discovery: &P2PDiscovery{ diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index 1fec151e61..6269e1c6fa 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -10,24 +10,28 @@ func (c *Command) Flags() *flagset.Flagset { f := flagset.NewFlagSet("server") f.StringFlag(&flagset.StringFlag{ - Name: "chain", - Usage: "Name of the chain to sync", - Value: &c.cliConfig.Chain, + Name: "chain", + Usage: "Name of the chain to sync", + Value: &c.cliConfig.Chain, + Default: c.cliConfig.Chain, }) f.StringFlag(&flagset.StringFlag{ - Name: "name", - Usage: "Name/Identity of the node", - Value: &c.cliConfig.Name, + Name: "name", + Usage: "Name/Identity of the node", + Value: &c.cliConfig.Name, + Default: c.cliConfig.Name, }) f.StringFlag(&flagset.StringFlag{ - Name: "log-level", - Usage: "Set log level for the server", - Value: &c.cliConfig.LogLevel, + Name: "log-level", + Usage: "Set log level for the server", + Value: &c.cliConfig.LogLevel, + Default: c.cliConfig.LogLevel, }) f.StringFlag(&flagset.StringFlag{ - Name: "datadir", - Usage: "Path of the data directory to store information", - Value: &c.cliConfig.DataDir, + Name: "datadir", + Usage: "Path of the data directory to store information", + Value: &c.cliConfig.DataDir, + Default: c.cliConfig.DataDir, }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "config", @@ -35,14 +39,16 @@ func (c *Command) Flags() *flagset.Flagset { Value: &c.configFile, }) f.StringFlag(&flagset.StringFlag{ - Name: "syncmode", - Usage: `Blockchain sync mode ("fast", "full", or "snap")`, - Value: &c.cliConfig.SyncMode, + Name: "syncmode", + Usage: `Blockchain sync mode ("fast", "full", or "snap")`, + Value: &c.cliConfig.SyncMode, + Default: c.cliConfig.SyncMode, }) f.StringFlag(&flagset.StringFlag{ - Name: "gcmode", - Usage: `Blockchain garbage collection mode ("full", "archive")`, - Value: &c.cliConfig.GcMode, + Name: "gcmode", + Usage: `Blockchain garbage collection mode ("full", "archive")`, + Value: &c.cliConfig.GcMode, + Default: c.cliConfig.GcMode, }) f.MapStringFlag(&flagset.MapStringFlag{ Name: "requiredblocks", @@ -50,21 +56,24 @@ func (c *Command) Flags() *flagset.Flagset { Value: &c.cliConfig.RequiredBlocks, }) f.BoolFlag(&flagset.BoolFlag{ - Name: "no-snapshot", - Usage: `Disables the snapshot-database mode (default = false)`, - Value: &c.cliConfig.NoSnapshot, + Name: "no-snapshot", + Usage: `Disables the snapshot-database mode (default = false)`, + Value: &c.cliConfig.NoSnapshot, + Default: c.cliConfig.NoSnapshot, }) // heimdall f.StringFlag(&flagset.StringFlag{ - Name: "bor.heimdall", - Usage: "URL of Heimdall service", - Value: &c.cliConfig.Heimdall.URL, + Name: "bor.heimdall", + Usage: "URL of Heimdall service", + Value: &c.cliConfig.Heimdall.URL, + Default: c.cliConfig.Heimdall.URL, }) f.BoolFlag(&flagset.BoolFlag{ - Name: "bor.withoutheimdall", - Usage: "Run without Heimdall service (for testing purpose)", - Value: &c.cliConfig.Heimdall.Without, + Name: "bor.withoutheimdall", + Usage: "Run without Heimdall service (for testing purpose)", + Value: &c.cliConfig.Heimdall.Without, + Default: c.cliConfig.Heimdall.Without, }) // txpool options @@ -75,90 +84,104 @@ func (c *Command) Flags() *flagset.Flagset { Group: "Transaction Pool", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "txpool.nolocals", - Usage: "Disables price exemptions for locally submitted transactions", - Value: &c.cliConfig.TxPool.NoLocals, - Group: "Transaction Pool", + Name: "txpool.nolocals", + Usage: "Disables price exemptions for locally submitted transactions", + Value: &c.cliConfig.TxPool.NoLocals, + Default: c.cliConfig.TxPool.NoLocals, + Group: "Transaction Pool", }) f.StringFlag(&flagset.StringFlag{ - Name: "txpool.journal", - Usage: "Disk journal for local transaction to survive node restarts", - Value: &c.cliConfig.TxPool.Journal, - Group: "Transaction Pool", + Name: "txpool.journal", + Usage: "Disk journal for local transaction to survive node restarts", + Value: &c.cliConfig.TxPool.Journal, + Default: c.cliConfig.TxPool.Journal, + Group: "Transaction Pool", }) f.DurationFlag(&flagset.DurationFlag{ - Name: "txpool.rejournal", - Usage: "Time interval to regenerate the local transaction journal", - Value: &c.cliConfig.TxPool.Rejournal, - Group: "Transaction Pool", + Name: "txpool.rejournal", + Usage: "Time interval to regenerate the local transaction journal", + Value: &c.cliConfig.TxPool.Rejournal, + Default: c.cliConfig.TxPool.Rejournal, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.pricelimit", - Usage: "Minimum gas price limit to enforce for acceptance into the pool", - Value: &c.cliConfig.TxPool.PriceLimit, - Group: "Transaction Pool", + Name: "txpool.pricelimit", + Usage: "Minimum gas price limit to enforce for acceptance into the pool", + Value: &c.cliConfig.TxPool.PriceLimit, + Default: c.cliConfig.TxPool.PriceLimit, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.pricebump", - Usage: "Price bump percentage to replace an already existing transaction", - Value: &c.cliConfig.TxPool.PriceBump, - Group: "Transaction Pool", + Name: "txpool.pricebump", + Usage: "Price bump percentage to replace an already existing transaction", + Value: &c.cliConfig.TxPool.PriceBump, + Default: c.cliConfig.TxPool.PriceBump, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.accountslots", - Usage: "Minimum number of executable transaction slots guaranteed per account", - Value: &c.cliConfig.TxPool.AccountSlots, - Group: "Transaction Pool", + Name: "txpool.accountslots", + Usage: "Minimum number of executable transaction slots guaranteed per account", + Value: &c.cliConfig.TxPool.AccountSlots, + Default: c.cliConfig.TxPool.AccountSlots, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.globalslots", - Usage: "Maximum number of executable transaction slots for all accounts", - Value: &c.cliConfig.TxPool.GlobalSlots, - Group: "Transaction Pool", + Name: "txpool.globalslots", + Usage: "Maximum number of executable transaction slots for all accounts", + Value: &c.cliConfig.TxPool.GlobalSlots, + Default: c.cliConfig.TxPool.GlobalSlots, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.accountqueue", - Usage: "Maximum number of non-executable transaction slots permitted per account", - Value: &c.cliConfig.TxPool.AccountQueue, - Group: "Transaction Pool", + Name: "txpool.accountqueue", + Usage: "Maximum number of non-executable transaction slots permitted per account", + Value: &c.cliConfig.TxPool.AccountQueue, + Default: c.cliConfig.TxPool.AccountQueue, + Group: "Transaction Pool", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txpool.globalqueue", - Usage: "Maximum number of non-executable transaction slots for all accounts", - Value: &c.cliConfig.TxPool.GlobalQueue, - Group: "Transaction Pool", + Name: "txpool.globalqueue", + Usage: "Maximum number of non-executable transaction slots for all accounts", + Value: &c.cliConfig.TxPool.GlobalQueue, + Default: c.cliConfig.TxPool.GlobalQueue, + Group: "Transaction Pool", }) f.DurationFlag(&flagset.DurationFlag{ - Name: "txpool.lifetime", - Usage: "Maximum amount of time non-executable transaction are queued", - Value: &c.cliConfig.TxPool.LifeTime, - Group: "Transaction Pool", + Name: "txpool.lifetime", + Usage: "Maximum amount of time non-executable transaction are queued", + Value: &c.cliConfig.TxPool.LifeTime, + Default: c.cliConfig.TxPool.LifeTime, + Group: "Transaction Pool", }) // sealer options f.BoolFlag(&flagset.BoolFlag{ - Name: "mine", - Usage: "Enable mining", - Value: &c.cliConfig.Sealer.Enabled, - Group: "Sealer", + Name: "mine", + Usage: "Enable mining", + Value: &c.cliConfig.Sealer.Enabled, + Default: c.cliConfig.Sealer.Enabled, + Group: "Sealer", }) f.StringFlag(&flagset.StringFlag{ - Name: "miner.etherbase", - Usage: "Public address for block mining rewards (default = first account)", - Value: &c.cliConfig.Sealer.Etherbase, - Group: "Sealer", + Name: "miner.etherbase", + Usage: "Public address for block mining rewards (default = first account)", + Value: &c.cliConfig.Sealer.Etherbase, + Default: c.cliConfig.Sealer.Etherbase, + Group: "Sealer", }) f.StringFlag(&flagset.StringFlag{ - Name: "miner.extradata", - Usage: "Block extra data set by the miner (default = client version)", - Value: &c.cliConfig.Sealer.ExtraData, - Group: "Sealer", + Name: "miner.extradata", + Usage: "Block extra data set by the miner (default = client version)", + Value: &c.cliConfig.Sealer.ExtraData, + Default: c.cliConfig.Sealer.ExtraData, + Group: "Sealer", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "miner.gaslimit", - Usage: "Target gas ceiling for mined blocks", - Value: &c.cliConfig.Sealer.GasCeil, - Group: "Sealer", + Name: "miner.gaslimit", + Usage: "Target gas ceiling for mined blocks", + Value: &c.cliConfig.Sealer.GasCeil, + Default: c.cliConfig.Sealer.GasCeil, + Group: "Sealer", }) f.BigIntFlag(&flagset.BigIntFlag{ Name: "miner.gasprice", @@ -169,21 +192,24 @@ func (c *Command) Flags() *flagset.Flagset { // ethstats f.StringFlag(&flagset.StringFlag{ - Name: "ethstats", - Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", - Value: &c.cliConfig.Ethstats, + Name: "ethstats", + Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", + Value: &c.cliConfig.Ethstats, + Default: c.cliConfig.Ethstats, }) // gas price oracle f.Uint64Flag(&flagset.Uint64Flag{ - Name: "gpo.blocks", - Usage: "Number of recent blocks to check for gas prices", - Value: &c.cliConfig.Gpo.Blocks, + Name: "gpo.blocks", + Usage: "Number of recent blocks to check for gas prices", + Value: &c.cliConfig.Gpo.Blocks, + Default: c.cliConfig.Gpo.Blocks, }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "gpo.percentile", - Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", - Value: &c.cliConfig.Gpo.Percentile, + Name: "gpo.percentile", + Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", + Value: &c.cliConfig.Gpo.Percentile, + Default: c.cliConfig.Gpo.Percentile, }) f.BigIntFlag(&flagset.BigIntFlag{ Name: "gpo.maxprice", @@ -198,90 +224,104 @@ func (c *Command) Flags() *flagset.Flagset { // cache options f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache", - Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)", - Value: &c.cliConfig.Cache.Cache, - Group: "Cache", + Name: "cache", + Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node)", + Value: &c.cliConfig.Cache.Cache, + Default: c.cliConfig.Cache.Cache, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache.database", - Usage: "Percentage of cache memory allowance to use for database io", - Value: &c.cliConfig.Cache.PercDatabase, - Group: "Cache", + Name: "cache.database", + Usage: "Percentage of cache memory allowance to use for database io", + Value: &c.cliConfig.Cache.PercDatabase, + Default: c.cliConfig.Cache.PercDatabase, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache.trie", - Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", - Value: &c.cliConfig.Cache.PercTrie, - Group: "Cache", + Name: "cache.trie", + Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", + Value: &c.cliConfig.Cache.PercTrie, + Default: c.cliConfig.Cache.PercTrie, + Group: "Cache", }) f.StringFlag(&flagset.StringFlag{ - Name: "cache.trie.journal", - Usage: "Disk journal directory for trie cache to survive node restarts", - Value: &c.cliConfig.Cache.Journal, - Group: "Cache", + Name: "cache.trie.journal", + Usage: "Disk journal directory for trie cache to survive node restarts", + Value: &c.cliConfig.Cache.Journal, + Default: c.cliConfig.Cache.Journal, + Group: "Cache", }) f.DurationFlag(&flagset.DurationFlag{ - Name: "cache.trie.rejournal", - Usage: "Time interval to regenerate the trie cache journal", - Value: &c.cliConfig.Cache.Rejournal, - Group: "Cache", + Name: "cache.trie.rejournal", + Usage: "Time interval to regenerate the trie cache journal", + Value: &c.cliConfig.Cache.Rejournal, + Default: c.cliConfig.Cache.Rejournal, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache.gc", - Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", - Value: &c.cliConfig.Cache.PercGc, - Group: "Cache", + Name: "cache.gc", + Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", + Value: &c.cliConfig.Cache.PercGc, + Default: c.cliConfig.Cache.PercGc, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "cache.snapshot", - Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", - Value: &c.cliConfig.Cache.PercSnapshot, - Group: "Cache", + Name: "cache.snapshot", + Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", + Value: &c.cliConfig.Cache.PercSnapshot, + Default: c.cliConfig.Cache.PercSnapshot, + Group: "Cache", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "cache.noprefetch", - Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", - Value: &c.cliConfig.Cache.NoPrefetch, - Group: "Cache", + Name: "cache.noprefetch", + Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", + Value: &c.cliConfig.Cache.NoPrefetch, + Default: c.cliConfig.Cache.NoPrefetch, + Group: "Cache", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "cache.preimages", - Usage: "Enable recording the SHA3/keccak preimages of trie keys", - Value: &c.cliConfig.Cache.Preimages, - Group: "Cache", + Name: "cache.preimages", + Usage: "Enable recording the SHA3/keccak preimages of trie keys", + Value: &c.cliConfig.Cache.Preimages, + Default: c.cliConfig.Cache.Preimages, + Group: "Cache", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "txlookuplimit", - Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)", - Value: &c.cliConfig.Cache.TxLookupLimit, - Group: "Cache", + Name: "txlookuplimit", + Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)", + Value: &c.cliConfig.Cache.TxLookupLimit, + Default: c.cliConfig.Cache.TxLookupLimit, + Group: "Cache", }) // rpc options f.Uint64Flag(&flagset.Uint64Flag{ - Name: "rpc.gascap", - Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", - Value: &c.cliConfig.JsonRPC.GasCap, - Group: "JsonRPC", + Name: "rpc.gascap", + Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", + Value: &c.cliConfig.JsonRPC.GasCap, + Default: c.cliConfig.JsonRPC.GasCap, + Group: "JsonRPC", }) f.Float64Flag(&flagset.Float64Flag{ - Name: "rpc.txfeecap", - Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", - Value: &c.cliConfig.JsonRPC.TxFeeCap, - Group: "JsonRPC", + Name: "rpc.txfeecap", + Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", + Value: &c.cliConfig.JsonRPC.TxFeeCap, + Default: c.cliConfig.JsonRPC.TxFeeCap, + Group: "JsonRPC", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "ipcdisable", - Usage: "Disable the IPC-RPC server", - Value: &c.cliConfig.JsonRPC.IPCDisable, - Group: "JsonRPC", + Name: "ipcdisable", + Usage: "Disable the IPC-RPC server", + Value: &c.cliConfig.JsonRPC.IPCDisable, + Default: c.cliConfig.JsonRPC.IPCDisable, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ - Name: "ipcpath", - Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", - Value: &c.cliConfig.JsonRPC.IPCPath, - Group: "JsonRPC", + Name: "ipcpath", + Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", + Value: &c.cliConfig.JsonRPC.IPCPath, + Default: c.cliConfig.JsonRPC.IPCPath, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "jsonrpc.corsdomain", @@ -298,28 +338,32 @@ func (c *Command) Flags() *flagset.Flagset { // http options f.BoolFlag(&flagset.BoolFlag{ - Name: "http", - Usage: "Enable the HTTP-RPC server", - Value: &c.cliConfig.JsonRPC.Http.Enabled, - Group: "JsonRPC", + Name: "http", + Usage: "Enable the HTTP-RPC server", + Value: &c.cliConfig.JsonRPC.Http.Enabled, + Default: c.cliConfig.JsonRPC.Http.Enabled, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ - Name: "http.addr", - Usage: "HTTP-RPC server listening interface", - Value: &c.cliConfig.JsonRPC.Http.Host, - Group: "JsonRPC", + Name: "http.addr", + Usage: "HTTP-RPC server listening interface", + Value: &c.cliConfig.JsonRPC.Http.Host, + Default: c.cliConfig.JsonRPC.Http.Host, + Group: "JsonRPC", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "http.port", - Usage: "HTTP-RPC server listening port", - Value: &c.cliConfig.JsonRPC.Http.Port, - Group: "JsonRPC", + Name: "http.port", + Usage: "HTTP-RPC server listening port", + Value: &c.cliConfig.JsonRPC.Http.Port, + Default: c.cliConfig.JsonRPC.Http.Port, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ - Name: "http.rpcprefix", - Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", - Value: &c.cliConfig.JsonRPC.Http.Prefix, - Group: "JsonRPC", + Name: "http.rpcprefix", + Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", + Value: &c.cliConfig.JsonRPC.Http.Prefix, + Default: c.cliConfig.JsonRPC.Http.Prefix, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "http.modules", @@ -330,28 +374,32 @@ func (c *Command) Flags() *flagset.Flagset { // ws options f.BoolFlag(&flagset.BoolFlag{ - Name: "ws", - Usage: "Enable the WS-RPC server", - Value: &c.cliConfig.JsonRPC.Ws.Enabled, - Group: "JsonRPC", + Name: "ws", + Usage: "Enable the WS-RPC server", + Value: &c.cliConfig.JsonRPC.Ws.Enabled, + Default: c.cliConfig.JsonRPC.Ws.Enabled, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ - Name: "ws.addr", - Usage: "WS-RPC server listening interface", - Value: &c.cliConfig.JsonRPC.Ws.Host, - Group: "JsonRPC", + Name: "ws.addr", + Usage: "WS-RPC server listening interface", + Value: &c.cliConfig.JsonRPC.Ws.Host, + Default: c.cliConfig.JsonRPC.Ws.Host, + Group: "JsonRPC", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "ws.port", - Usage: "WS-RPC server listening port", - Value: &c.cliConfig.JsonRPC.Ws.Port, - Group: "JsonRPC", + Name: "ws.port", + Usage: "WS-RPC server listening port", + Value: &c.cliConfig.JsonRPC.Ws.Port, + Default: c.cliConfig.JsonRPC.Ws.Port, + Group: "JsonRPC", }) f.StringFlag(&flagset.StringFlag{ - Name: "ws.rpcprefix", - Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", - Value: &c.cliConfig.JsonRPC.Ws.Prefix, - Group: "JsonRPC", + Name: "ws.rpcprefix", + Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", + Value: &c.cliConfig.JsonRPC.Ws.Prefix, + Default: c.cliConfig.JsonRPC.Ws.Prefix, + Group: "JsonRPC", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "ws.modules", @@ -362,24 +410,27 @@ func (c *Command) Flags() *flagset.Flagset { // graphql options f.BoolFlag(&flagset.BoolFlag{ - Name: "graphql", - Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.", - Value: &c.cliConfig.JsonRPC.Graphql.Enabled, - Group: "JsonRPC", + Name: "graphql", + Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.", + Value: &c.cliConfig.JsonRPC.Graphql.Enabled, + Default: c.cliConfig.JsonRPC.Graphql.Enabled, + Group: "JsonRPC", }) // p2p options f.StringFlag(&flagset.StringFlag{ - Name: "bind", - Usage: "Network binding address", - Value: &c.cliConfig.P2P.Bind, - Group: "P2P", + Name: "bind", + Usage: "Network binding address", + Value: &c.cliConfig.P2P.Bind, + Default: c.cliConfig.P2P.Bind, + Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "port", - Usage: "Network listening port", - Value: &c.cliConfig.P2P.Port, - Group: "P2P", + Name: "port", + Usage: "Network listening port", + Value: &c.cliConfig.P2P.Port, + Default: c.cliConfig.P2P.Port, + Group: "P2P", }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "bootnodes", @@ -388,78 +439,90 @@ func (c *Command) Flags() *flagset.Flagset { Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "maxpeers", - Usage: "Maximum number of network peers (network disabled if set to 0)", - Value: &c.cliConfig.P2P.MaxPeers, - Group: "P2P", + Name: "maxpeers", + Usage: "Maximum number of network peers (network disabled if set to 0)", + Value: &c.cliConfig.P2P.MaxPeers, + Default: c.cliConfig.P2P.MaxPeers, + Group: "P2P", }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "maxpendpeers", - Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", - Value: &c.cliConfig.P2P.MaxPendPeers, - Group: "P2P", + Name: "maxpendpeers", + Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", + Value: &c.cliConfig.P2P.MaxPendPeers, + Default: c.cliConfig.P2P.MaxPendPeers, + Group: "P2P", }) f.StringFlag(&flagset.StringFlag{ - Name: "nat", - Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", - Value: &c.cliConfig.P2P.NAT, - Group: "P2P", + Name: "nat", + Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:)", + Value: &c.cliConfig.P2P.NAT, + Default: c.cliConfig.P2P.NAT, + Group: "P2P", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "nodiscover", - Usage: "Disables the peer discovery mechanism (manual peer addition)", - Value: &c.cliConfig.P2P.NoDiscover, - Group: "P2P", + Name: "nodiscover", + Usage: "Disables the peer discovery mechanism (manual peer addition)", + Value: &c.cliConfig.P2P.NoDiscover, + Default: c.cliConfig.P2P.NoDiscover, + Group: "P2P", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "v5disc", - Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", - Value: &c.cliConfig.P2P.Discovery.V5Enabled, - Group: "P2P", + Name: "v5disc", + Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", + Value: &c.cliConfig.P2P.Discovery.V5Enabled, + Default: c.cliConfig.P2P.Discovery.V5Enabled, + Group: "P2P", }) // metrics f.BoolFlag(&flagset.BoolFlag{ - Name: "metrics", - Usage: "Enable metrics collection and reporting", - Value: &c.cliConfig.Telemetry.Enabled, - Group: "Telemetry", + Name: "metrics", + Usage: "Enable metrics collection and reporting", + Value: &c.cliConfig.Telemetry.Enabled, + Default: c.cliConfig.Telemetry.Enabled, + Group: "Telemetry", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "metrics.expensive", - Usage: "Enable expensive metrics collection and reporting", - Value: &c.cliConfig.Telemetry.Expensive, - Group: "Telemetry", + Name: "metrics.expensive", + Usage: "Enable expensive metrics collection and reporting", + Value: &c.cliConfig.Telemetry.Expensive, + Default: c.cliConfig.Telemetry.Expensive, + Group: "Telemetry", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "metrics.influxdb", - Usage: "Enable metrics export/push to an external InfluxDB database (v1)", - Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled, - Group: "Telemetry", + Name: "metrics.influxdb", + Usage: "Enable metrics export/push to an external InfluxDB database (v1)", + Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled, + Default: c.cliConfig.Telemetry.InfluxDB.V1Enabled, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.endpoint", - Usage: "InfluxDB API endpoint to report metrics to", - Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint, - Group: "Telemetry", + Name: "metrics.influxdb.endpoint", + Usage: "InfluxDB API endpoint to report metrics to", + Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint, + Default: c.cliConfig.Telemetry.InfluxDB.Endpoint, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.database", - Usage: "InfluxDB database name to push reported metrics to", - Value: &c.cliConfig.Telemetry.InfluxDB.Database, - Group: "Telemetry", + Name: "metrics.influxdb.database", + Usage: "InfluxDB database name to push reported metrics to", + Value: &c.cliConfig.Telemetry.InfluxDB.Database, + Default: c.cliConfig.Telemetry.InfluxDB.Database, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.username", - Usage: "Username to authorize access to the database", - Value: &c.cliConfig.Telemetry.InfluxDB.Username, - Group: "Telemetry", + Name: "metrics.influxdb.username", + Usage: "Username to authorize access to the database", + Value: &c.cliConfig.Telemetry.InfluxDB.Username, + Default: c.cliConfig.Telemetry.InfluxDB.Username, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.password", - Usage: "Password to authorize access to the database", - Value: &c.cliConfig.Telemetry.InfluxDB.Password, - Group: "Telemetry", + Name: "metrics.influxdb.password", + Usage: "Password to authorize access to the database", + Value: &c.cliConfig.Telemetry.InfluxDB.Password, + Default: c.cliConfig.Telemetry.InfluxDB.Password, + Group: "Telemetry", }) f.MapStringFlag(&flagset.MapStringFlag{ Name: "metrics.influxdb.tags", @@ -468,41 +531,47 @@ func (c *Command) Flags() *flagset.Flagset { Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.prometheus-addr", - Usage: "Address for Prometheus Server", - Value: &c.cliConfig.Telemetry.PrometheusAddr, - Group: "Telemetry", + Name: "metrics.prometheus-addr", + Usage: "Address for Prometheus Server", + Value: &c.cliConfig.Telemetry.PrometheusAddr, + Default: c.cliConfig.Telemetry.PrometheusAddr, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.opencollector-endpoint", - Usage: "OpenCollector Endpoint (host:port)", - Value: &c.cliConfig.Telemetry.OpenCollectorEndpoint, - Group: "Telemetry", + Name: "metrics.opencollector-endpoint", + Usage: "OpenCollector Endpoint (host:port)", + Value: &c.cliConfig.Telemetry.OpenCollectorEndpoint, + Default: c.cliConfig.Telemetry.OpenCollectorEndpoint, + Group: "Telemetry", }) // influx db v2 f.BoolFlag(&flagset.BoolFlag{ - Name: "metrics.influxdbv2", - Usage: "Enable metrics export/push to an external InfluxDB v2 database", - Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled, - Group: "Telemetry", + Name: "metrics.influxdbv2", + Usage: "Enable metrics export/push to an external InfluxDB v2 database", + Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled, + Default: c.cliConfig.Telemetry.InfluxDB.V2Enabled, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.token", - Usage: "Token to authorize access to the database (v2 only)", - Value: &c.cliConfig.Telemetry.InfluxDB.Token, - Group: "Telemetry", + Name: "metrics.influxdb.token", + Usage: "Token to authorize access to the database (v2 only)", + Value: &c.cliConfig.Telemetry.InfluxDB.Token, + Default: c.cliConfig.Telemetry.InfluxDB.Token, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.bucket", - Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", - Value: &c.cliConfig.Telemetry.InfluxDB.Bucket, - Group: "Telemetry", + Name: "metrics.influxdb.bucket", + Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", + Value: &c.cliConfig.Telemetry.InfluxDB.Bucket, + Default: c.cliConfig.Telemetry.InfluxDB.Bucket, + Group: "Telemetry", }) f.StringFlag(&flagset.StringFlag{ - Name: "metrics.influxdb.organization", - Usage: "InfluxDB organization name (v2 only)", - Value: &c.cliConfig.Telemetry.InfluxDB.Organization, - Group: "Telemetry", + Name: "metrics.influxdb.organization", + Usage: "InfluxDB organization name (v2 only)", + Value: &c.cliConfig.Telemetry.InfluxDB.Organization, + Default: c.cliConfig.Telemetry.InfluxDB.Organization, + Group: "Telemetry", }) // account @@ -513,46 +582,53 @@ func (c *Command) Flags() *flagset.Flagset { Group: "Account Management", }) f.StringFlag(&flagset.StringFlag{ - Name: "password", - Usage: "Password file to use for non-interactive password input", - Value: &c.cliConfig.Accounts.PasswordFile, - Group: "Account Management", + Name: "password", + Usage: "Password file to use for non-interactive password input", + Value: &c.cliConfig.Accounts.PasswordFile, + Default: c.cliConfig.Accounts.PasswordFile, + Group: "Account Management", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "allow-insecure-unlock", - Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", - Value: &c.cliConfig.Accounts.AllowInsecureUnlock, - Group: "Account Management", + Name: "allow-insecure-unlock", + Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", + Value: &c.cliConfig.Accounts.AllowInsecureUnlock, + Default: c.cliConfig.Accounts.AllowInsecureUnlock, + Group: "Account Management", }) f.BoolFlag(&flagset.BoolFlag{ - Name: "lightkdf", - Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", - Value: &c.cliConfig.Accounts.UseLightweightKDF, - Group: "Account Management", + Name: "lightkdf", + Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", + Value: &c.cliConfig.Accounts.UseLightweightKDF, + Default: c.cliConfig.Accounts.UseLightweightKDF, + Group: "Account Management", }) f.BoolFlag((&flagset.BoolFlag{ - Name: "disable-bor-wallet", - Usage: "Disable the personal wallet endpoints", - Value: &c.cliConfig.Accounts.DisableBorWallet, + Name: "disable-bor-wallet", + Usage: "Disable the personal wallet endpoints", + Value: &c.cliConfig.Accounts.DisableBorWallet, + Default: c.cliConfig.Accounts.DisableBorWallet, })) // grpc f.StringFlag(&flagset.StringFlag{ - Name: "grpc.addr", - Usage: "Address and port to bind the GRPC server", - Value: &c.cliConfig.GRPC.Addr, + Name: "grpc.addr", + Usage: "Address and port to bind the GRPC server", + Value: &c.cliConfig.GRPC.Addr, + Default: c.cliConfig.GRPC.Addr, }) // developer f.BoolFlag(&flagset.BoolFlag{ - Name: "dev", - Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled", - Value: &c.cliConfig.Developer.Enabled, + Name: "dev", + Usage: "Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled", + Value: &c.cliConfig.Developer.Enabled, + Default: c.cliConfig.Developer.Enabled, }) f.Uint64Flag(&flagset.Uint64Flag{ - Name: "dev.period", - Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", - Value: &c.cliConfig.Developer.Period, + Name: "dev.period", + Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", + Value: &c.cliConfig.Developer.Period, + Default: c.cliConfig.Developer.Period, }) return f } From 0d2b1d0630ab81e9646c84d9f0a95b38e7feb1de Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Mon, 6 Jun 2022 14:54:05 +0530 Subject: [PATCH 77/80] internal/cli: add block tracing (#397) * bad block tracing * Add debug env framework * add implementation of custom block tracing * add few comments * use tar name fn * wip: add unit tests for block tracing * complete test for block tracer * fix: close grpc server * refactor cli tests * fix: change condition for parsing args * Fix port binding for test server * add helper for creating and closing mock server for tests * consume mock server in tests * fixes due to geth merge * fix: handle port selection for http server * update help and markdown for debug command * update docs * update debug synopsis * fix: use chunked encoder to handle large data over grpc * fix prints * lint * rm unused function, rename fn to TraceBorBlock Co-authored-by: Ferran Borreguero --- docs/cli/README.md | 4 + docs/cli/debug.md | 8 +- docs/cli/debug_block.md | 9 + docs/cli/debug_pprof.md | 11 + eth/tracers/api_bor.go | 143 +++ internal/cli/command.go | 10 + internal/cli/debug.go | 232 ++--- internal/cli/debug_block.go | 126 +++ internal/cli/debug_pprof.go | 159 ++++ internal/cli/debug_test.go | 112 +++ internal/cli/server/helper.go | 72 ++ internal/cli/server/proto/server.pb.go | 954 ++++++++++++-------- internal/cli/server/proto/server.proto | 25 +- internal/cli/server/proto/server_grpc.pb.go | 193 ++-- internal/cli/server/server.go | 14 + internal/cli/server/server_test.go | 35 +- internal/cli/server/service.go | 96 +- 17 files changed, 1560 insertions(+), 643 deletions(-) create mode 100644 docs/cli/debug_block.md create mode 100644 docs/cli/debug_pprof.md create mode 100644 eth/tracers/api_bor.go create mode 100644 internal/cli/debug_block.go create mode 100644 internal/cli/debug_pprof.go create mode 100644 internal/cli/debug_test.go create mode 100644 internal/cli/server/helper.go diff --git a/docs/cli/README.md b/docs/cli/README.md index d5648dca7d..d92a7b5a05 100644 --- a/docs/cli/README.md +++ b/docs/cli/README.md @@ -22,6 +22,10 @@ - [```debug```](./debug.md) +- [```debug block```](./debug_block.md) + +- [```debug pprof```](./debug_pprof.md) + - [```fingerprint```](./fingerprint.md) - [```peers```](./peers.md) diff --git a/docs/cli/debug.md b/docs/cli/debug.md index eecc6c6ef0..a59e465745 100644 --- a/docs/cli/debug.md +++ b/docs/cli/debug.md @@ -2,13 +2,9 @@ The ```bor debug``` command takes a debug dump of the running client. -## Options +- [```bor debug pprof```](./debug_pprof.md): Dumps bor pprof traces. -- ```address```: Address of the grpc endpoint - -- ```seconds```: seconds to trace - -- ```output```: Output directory +- [```bor debug block ```](./debug_block.md): Dumps bor block traces. ## Examples diff --git a/docs/cli/debug_block.md b/docs/cli/debug_block.md new file mode 100644 index 0000000000..ced7e482ee --- /dev/null +++ b/docs/cli/debug_block.md @@ -0,0 +1,9 @@ +# Debug trace + +The ```bor debug block ``` command will create an archive containing traces of a bor block. + +## Options + +- ```address```: Address of the grpc endpoint + +- ```output```: Output directory \ No newline at end of file diff --git a/docs/cli/debug_pprof.md b/docs/cli/debug_pprof.md new file mode 100644 index 0000000000..86a84b6065 --- /dev/null +++ b/docs/cli/debug_pprof.md @@ -0,0 +1,11 @@ +# Debug Pprof + +The ```debug pprof ``` command will create an archive containing bor pprof traces. + +## Options + +- ```address```: Address of the grpc endpoint + +- ```seconds```: seconds to trace + +- ```output```: Output directory \ No newline at end of file diff --git a/eth/tracers/api_bor.go b/eth/tracers/api_bor.go new file mode 100644 index 0000000000..7f5e2c34d6 --- /dev/null +++ b/eth/tracers/api_bor.go @@ -0,0 +1,143 @@ +package tracers + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" +) + +type BlockTraceResult struct { + // Trace of each transaction executed + Transactions []*TxTraceResult `json:"transactions,omitempty"` + + // Block that we are executing on the trace + Block interface{} `json:"block"` +} + +type TxTraceResult struct { + // Trace results produced by the tracer + Result interface{} `json:"result,omitempty"` + + // Trace failure produced by the tracer + Error string `json:"error,omitempty"` + + // IntermediateHash of the execution if succeeds + IntermediateHash common.Hash `json:"intermediatehash"` +} + +func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *TraceConfig) (*BlockTraceResult, error) { + if block.NumberU64() == 0 { + return nil, fmt.Errorf("genesis is not traceable") + } + + res := &BlockTraceResult{ + Block: block, + } + + // block object cannot be converted to JSON since much of the fields are non-public + blockFields, err := ethapi.RPCMarshalBlock(block, true, true, api.backend.ChainConfig()) + if err != nil { + return nil, err + } + res.Block = blockFields + + parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) + if err != nil { + return nil, err + } + reexec := defaultTraceReexec + if config != nil && config.Reexec != nil { + reexec = *config.Reexec + } + // TODO: discuss consequences of setting preferDisk false. + statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) + if err != nil { + return nil, err + } + + // Execute all the transaction contained within the block concurrently + var ( + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number()) + txs = block.Transactions() + deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number()) + ) + + blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) + + traceTxn := func(indx int, tx *types.Transaction) *TxTraceResult { + message, _ := tx.AsMessage(signer, block.BaseFee()) + txContext := core.NewEVMTxContext(message) + + tracer := logger.NewStructLogger(config.Config) + + // Run the transaction with tracing enabled. + vmenv := vm.NewEVM(blockCtx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Debug: true, Tracer: tracer, NoBaseFee: true}) + + // Call Prepare to clear out the statedb access list + // Not sure if we need to do this + statedb.Prepare(tx.Hash(), indx) + + execRes, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())) + if err != nil { + return &TxTraceResult{ + Error: err.Error(), + } + } + + returnVal := fmt.Sprintf("%x", execRes.Return()) + if len(execRes.Revert()) > 0 { + returnVal = fmt.Sprintf("%x", execRes.Revert()) + } + result := ðapi.ExecutionResult{ + Gas: execRes.UsedGas, + Failed: execRes.Failed(), + ReturnValue: returnVal, + StructLogs: ethapi.FormatLogs(tracer.StructLogs()), + } + res := &TxTraceResult{ + Result: result, + IntermediateHash: statedb.IntermediateRoot(deleteEmptyObjects), + } + return res + } + + for indx, tx := range txs { + res.Transactions = append(res.Transactions, traceTxn(indx, tx)) + } + return res, nil +} + +type TraceBlockRequest struct { + Number int64 + Hash string + IsBadBlock bool + Config *TraceConfig +} + +// If you use context as first parameter this function gets exposed automaticall on rpc endpoint +func (api *API) TraceBorBlock(req *TraceBlockRequest) (*BlockTraceResult, error) { + ctx := context.Background() + + var blockNumber rpc.BlockNumber + if req.Number == -1 { + blockNumber = rpc.LatestBlockNumber + } else { + blockNumber = rpc.BlockNumber(req.Number) + } + + log.Debug("Tracing Bor Block", "block number", blockNumber) + + block, err := api.blockByNumber(ctx, blockNumber) + if err != nil { + return nil, err + } + return api.traceBorBlock(ctx, block, req.Config) +} diff --git a/internal/cli/command.go b/internal/cli/command.go index 34f7c4ef12..1ff95b410f 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -84,6 +84,16 @@ func Commands() map[string]MarkDownCommandFactory { }, "debug": func() (MarkDownCommand, error) { return &DebugCommand{ + UI: ui, + }, nil + }, + "debug pprof": func() (MarkDownCommand, error) { + return &DebugPprofCommand{ + Meta2: meta2, + }, nil + }, + "debug block": func() (MarkDownCommand, error) { + return &DebugBlockCommand{ Meta2: meta2, }, nil }, diff --git a/internal/cli/debug.go b/internal/cli/debug.go index fb998ee4b9..6e083a6974 100644 --- a/internal/cli/debug.go +++ b/internal/cli/debug.go @@ -1,11 +1,8 @@ package cli -// Based on https://github.com/hashicorp/nomad/blob/main/command/operator_debug.go - import ( "archive/tar" "compress/gzip" - "context" "fmt" "io" "io/ioutil" @@ -16,20 +13,20 @@ import ( "syscall" "time" - "github.com/ethereum/go-ethereum/internal/cli/flagset" + "github.com/mitchellh/cli" + "github.com/ethereum/go-ethereum/internal/cli/server/proto" "github.com/golang/protobuf/jsonpb" // nolint:staticcheck gproto "github.com/golang/protobuf/proto" // nolint:staticcheck - "github.com/golang/protobuf/ptypes/empty" grpc_net_conn "github.com/mitchellh/go-grpc-net-conn" + "google.golang.org/grpc" + "google.golang.org/protobuf/runtime/protoiface" ) +// DebugCommand is the command to group the peers commands type DebugCommand struct { - *Meta2 - - seconds uint64 - output string + UI cli.Ui } // MarkDown implements cli.MarkDown interface @@ -53,7 +50,8 @@ func (d *DebugCommand) MarkDown() string { items := []string{ "# Debug", "The ```bor debug``` command takes a debug dump of the running client.", - d.Flags().MarkDown(), + "- [```bor debug pprof```](./debug_pprof.md): Dumps bor pprof traces.", + "- [```bor debug block ```](./debug_block.md): Dumps bor block traces.", } items = append(items, examples...) @@ -61,185 +59,141 @@ func (d *DebugCommand) MarkDown() string { } // Help implements the cli.Command interface -func (d *DebugCommand) Help() string { - return `Usage: bor debug +func (c *DebugCommand) Help() string { + return `Usage: bor debug - Build an archive containing Bor pprof traces + This command takes a debug dump of the running client. + + Get the pprof traces: - ` + d.Flags().Help() -} + $ bor debug pprof -func (d *DebugCommand) Flags() *flagset.Flagset { - flags := d.NewFlagSet("debug") + Get the block traces: - flags.Uint64Flag(&flagset.Uint64Flag{ - Name: "seconds", - Usage: "seconds to trace", - Value: &d.seconds, - Default: 2, - }) - flags.StringFlag(&flagset.StringFlag{ - Name: "output", - Value: &d.output, - Usage: "Output directory", - }) - - return flags + $ bor debug block ` } // Synopsis implements the cli.Command interface -func (d *DebugCommand) Synopsis() string { - return "Build an archive containing Bor pprof traces" +func (c *DebugCommand) Synopsis() string { + return "Get traces of the running client" } // Run implements the cli.Command interface -func (d *DebugCommand) Run(args []string) int { - flags := d.Flags() - if err := flags.Parse(args); err != nil { - d.UI.Error(err.Error()) - return 1 - } +func (c *DebugCommand) Run(args []string) int { + return cli.RunResultHelp +} - clt, err := d.BorConn() - if err != nil { - d.UI.Error(err.Error()) - return 1 - } +type debugEnv struct { + output string + prefix string + + name string + dst string +} - stamped := "bor-debug-" + time.Now().UTC().Format("2006-01-02-150405Z") +func (d *debugEnv) init() error { + d.name = d.prefix + time.Now().UTC().Format("2006-01-02-150405Z") + + var err error // Create the output directory var tmp string if d.output != "" { // User specified output directory - tmp = filepath.Join(d.output, stamped) + tmp = filepath.Join(d.output, d.name) _, err := os.Stat(tmp) if !os.IsNotExist(err) { - d.UI.Error("Output directory already exists") - return 1 + return fmt.Errorf("output directory already exists") } } else { // Generate temp directory - tmp, err = ioutil.TempDir(os.TempDir(), stamped) + tmp, err = ioutil.TempDir(os.TempDir(), d.name) if err != nil { - d.UI.Error(fmt.Sprintf("Error creating tmp directory: %s", err.Error())) - return 1 + return fmt.Errorf("error creating tmp directory: %s", err.Error()) } - defer os.RemoveAll(tmp) } - d.UI.Output("Starting debugger...") - d.UI.Output("") - // ensure destine folder exists if err := os.MkdirAll(tmp, os.ModePerm); err != nil { - d.UI.Error(fmt.Sprintf("failed to create parent directory: %v", err)) - return 1 + return fmt.Errorf("failed to create parent directory: %v", err) } - pprofProfile := func(ctx context.Context, profile string, filename string) error { - req := &proto.PprofRequest{ - Seconds: int64(d.seconds), - } + d.dst = tmp - switch profile { - case "cpu": - req.Type = proto.PprofRequest_CPU - case "trace": - req.Type = proto.PprofRequest_TRACE - default: - req.Type = proto.PprofRequest_LOOKUP - req.Profile = profile - } - - stream, err := clt.Pprof(ctx, req) + return nil +} - if err != nil { - return err - } - // wait for open request - msg, err := stream.Recv() - if err != nil { - return err - } +func (d *debugEnv) tarName() string { + return d.name + ".tar.gz" +} - if _, ok := msg.Event.(*proto.PprofResponse_Open_); !ok { - return fmt.Errorf("expected open message") - } +func (d *debugEnv) finish() error { + // Exit before archive if output directory was specified + if d.output != "" { + return nil + } - // create the stream - conn := &grpc_net_conn.Conn{ - Stream: stream, - Response: &proto.PprofResponse_Input{}, - Decode: grpc_net_conn.SimpleDecoder(func(msg gproto.Message) *[]byte { - return &msg.(*proto.PprofResponse_Input).Data - }), - } + // Create archive tarball + archiveFile := d.tarName() + if err := tarCZF(archiveFile, d.dst, d.name); err != nil { + return fmt.Errorf("error creating archive: %s", err.Error()) + } - file, err := os.OpenFile(filepath.Join(tmp, filename+".prof"), os.O_RDWR|os.O_CREATE, 0644) - if err != nil { - return err - } - defer file.Close() + return nil +} - if _, err := io.Copy(file, conn); err != nil { - return err - } +type debugStream interface { + Recv() (*proto.DebugFileResponse, error) + grpc.ClientStream +} - return nil +func (d *debugEnv) writeFromStream(name string, stream debugStream) error { + // wait for open request + msg, err := stream.Recv() + if err != nil { + return err } - ctx, cancelFn := context.WithCancel(context.Background()) - trapSignal(cancelFn) - - profiles := map[string]string{ - "heap": "heap", - "cpu": "cpu", - "trace": "trace", + if _, ok := msg.Event.(*proto.DebugFileResponse_Open_); !ok { + return fmt.Errorf("expected open message") } - for profile, filename := range profiles { - if err := pprofProfile(ctx, profile, filename); err != nil { - d.UI.Error(fmt.Sprintf("Error creating profile '%s': %v", profile, err)) - return 1 - } + + // create the stream + conn := &grpc_net_conn.Conn{ + Stream: stream, + Response: &proto.DebugFileResponse_Input{}, + Decode: grpc_net_conn.SimpleDecoder(func(msg gproto.Message) *[]byte { + return &msg.(*proto.DebugFileResponse_Input).Data + }), } - // append the status - { - statusResp, err := clt.Status(ctx, &empty.Empty{}) - if err != nil { - d.UI.Output(fmt.Sprintf("Failed to get status: %v", err)) - return 1 - } - m := jsonpb.Marshaler{} - data, err := m.MarshalToString(statusResp) - if err != nil { - d.UI.Output(err.Error()) - return 1 - } - if err := ioutil.WriteFile(filepath.Join(tmp, "status.json"), []byte(data), 0600); err != nil { - d.UI.Output(fmt.Sprintf("Failed to write status: %v", err)) - return 1 - } + file, err := os.OpenFile(filepath.Join(d.dst, name), os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + return err } + defer file.Close() - // Exit before archive if output directory was specified - if d.output != "" { - d.UI.Output(fmt.Sprintf("Created debug directory: %s", tmp)) - return 0 + if _, err := io.Copy(file, conn); err != nil { + return err } - // Create archive tarball - archiveFile := stamped + ".tar.gz" - if err = tarCZF(archiveFile, tmp, stamped); err != nil { - d.UI.Error(fmt.Sprintf("Error creating archive: %s", err.Error())) - return 1 + return nil +} + +func (d *debugEnv) writeJSON(name string, msg protoiface.MessageV1) error { + m := jsonpb.Marshaler{} + data, err := m.MarshalToString(msg) + + if err != nil { + return err } - d.UI.Output(fmt.Sprintf("Created debug archive: %s", archiveFile)) + if err := ioutil.WriteFile(filepath.Join(d.dst, name), []byte(data), 0600); err != nil { + return fmt.Errorf("failed to write status: %v", err) + } - return 0 + return nil } func trapSignal(cancel func()) { diff --git a/internal/cli/debug_block.go b/internal/cli/debug_block.go new file mode 100644 index 0000000000..5a282cc550 --- /dev/null +++ b/internal/cli/debug_block.go @@ -0,0 +1,126 @@ +package cli + +import ( + "context" + "fmt" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/internal/cli/flagset" + "github.com/ethereum/go-ethereum/internal/cli/server/proto" +) + +// DebugBlockCommand is the command to group the peers commands +type DebugBlockCommand struct { + *Meta2 + + output string +} + +func (p *DebugBlockCommand) MarkDown() string { + items := []string{ + "# Debug trace", + "The ```bor debug block ``` command will create an archive containing traces of a bor block.", + p.Flags().MarkDown(), + } + + return strings.Join(items, "\n\n") +} + +// Help implements the cli.Command interface +func (c *DebugBlockCommand) Help() string { + return `Usage: bor debug block + + This command is used get traces of a bor block` +} + +func (c *DebugBlockCommand) Flags() *flagset.Flagset { + flags := c.NewFlagSet("trace") + + flags.StringFlag(&flagset.StringFlag{ + Name: "output", + Value: &c.output, + Usage: "Output directory", + }) + + return flags +} + +// Synopsis implements the cli.Command interface +func (c *DebugBlockCommand) Synopsis() string { + return "Get trace of a bor block" +} + +// Run implements the cli.Command interface +func (c *DebugBlockCommand) Run(args []string) int { + flags := c.Flags() + + var number *int64 = nil + + // parse the block number (if available) + if len(args)%2 != 0 { + num, err := strconv.ParseInt(args[0], 10, 64) + if err == nil { + number = &num + } + + args = args[1:] + } + // parse output directory + if err := flags.Parse(args); err != nil { + c.UI.Error(err.Error()) + return 1 + } + + borClt, err := c.BorConn() + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + dEnv := &debugEnv{ + output: c.output, + prefix: "bor-block-trace-", + } + if err := dEnv.init(); err != nil { + c.UI.Error(err.Error()) + return 1 + } + + c.UI.Output("Starting block tracer...") + c.UI.Output("") + + // create a debug block request + var debugRequest *proto.DebugBlockRequest = &proto.DebugBlockRequest{} + if number != nil { + debugRequest.Number = *number + } else { + debugRequest.Number = -1 + } + + // send the request + // receives a grpc stream of debug block response + stream, err := borClt.DebugBlock(context.Background(), debugRequest) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + if err := dEnv.writeFromStream("block.json", stream); err != nil { + c.UI.Error(err.Error()) + return 1 + } + + if err := dEnv.finish(); err != nil { + c.UI.Error(err.Error()) + return 1 + } + + if c.output != "" { + c.UI.Output(fmt.Sprintf("Created debug directory: %s", dEnv.dst)) + } else { + c.UI.Output(fmt.Sprintf("Created block trace archive: %s", dEnv.tarName())) + } + + return 0 +} diff --git a/internal/cli/debug_pprof.go b/internal/cli/debug_pprof.go new file mode 100644 index 0000000000..ef15e45b58 --- /dev/null +++ b/internal/cli/debug_pprof.go @@ -0,0 +1,159 @@ +package cli + +// Based on https://github.com/hashicorp/nomad/blob/main/command/operator_debug.go + +import ( + "context" + "fmt" + "strings" + + "github.com/golang/protobuf/ptypes/empty" + + "github.com/ethereum/go-ethereum/internal/cli/flagset" + "github.com/ethereum/go-ethereum/internal/cli/server/proto" +) + +type DebugPprofCommand struct { + *Meta2 + + seconds uint64 + output string +} + +func (p *DebugPprofCommand) MarkDown() string { + items := []string{ + "# Debug Pprof", + "The ```debug pprof ``` command will create an archive containing bor pprof traces.", + p.Flags().MarkDown(), + } + + return strings.Join(items, "\n\n") +} + +// Help implements the cli.Command interface +func (d *DebugPprofCommand) Help() string { + return `Usage: bor debug + + Build an archive containing Bor pprof traces + + ` + d.Flags().Help() +} + +func (d *DebugPprofCommand) Flags() *flagset.Flagset { + flags := d.NewFlagSet("debug") + + flags.Uint64Flag(&flagset.Uint64Flag{ + Name: "seconds", + Usage: "seconds to trace", + Value: &d.seconds, + Default: 2, + }) + flags.StringFlag(&flagset.StringFlag{ + Name: "output", + Value: &d.output, + Usage: "Output directory", + }) + + return flags +} + +// Synopsis implements the cli.Command interface +func (d *DebugPprofCommand) Synopsis() string { + return "Build an archive containing Bor pprof traces" +} + +// Run implements the cli.Command interface +func (d *DebugPprofCommand) Run(args []string) int { + flags := d.Flags() + if err := flags.Parse(args); err != nil { + d.UI.Error(err.Error()) + return 1 + } + + clt, err := d.BorConn() + if err != nil { + d.UI.Error(err.Error()) + return 1 + } + + dEnv := &debugEnv{ + output: d.output, + prefix: "bor-debug-", + } + if err := dEnv.init(); err != nil { + d.UI.Error(err.Error()) + return 1 + } + + d.UI.Output("Starting debugger...") + d.UI.Output("") + + pprofProfile := func(ctx context.Context, profile string, filename string) error { + req := &proto.DebugPprofRequest{ + Seconds: int64(d.seconds), + } + + switch profile { + case "cpu": + req.Type = proto.DebugPprofRequest_CPU + case "trace": + req.Type = proto.DebugPprofRequest_TRACE + default: + req.Type = proto.DebugPprofRequest_LOOKUP + req.Profile = profile + } + + stream, err := clt.DebugPprof(ctx, req) + + if err != nil { + return err + } + + if err := dEnv.writeFromStream(filename+".prof", stream); err != nil { + return err + } + + return nil + } + + ctx, cancelFn := context.WithCancel(context.Background()) + trapSignal(cancelFn) + + profiles := map[string]string{ + "heap": "heap", + "cpu": "cpu", + "trace": "trace", + } + for profile, filename := range profiles { + if err := pprofProfile(ctx, profile, filename); err != nil { + d.UI.Error(fmt.Sprintf("Error creating profile '%s': %v", profile, err)) + return 1 + } + } + + // append the status + { + statusResp, err := clt.Status(ctx, &empty.Empty{}) + if err != nil { + d.UI.Output(fmt.Sprintf("Failed to get status: %v", err)) + return 1 + } + if err := dEnv.writeJSON("status.json", statusResp); err != nil { + d.UI.Error(err.Error()) + return 1 + } + } + + if err := dEnv.finish(); err != nil { + d.UI.Error(err.Error()) + return 1 + } + + if d.output != "" { + d.UI.Output(fmt.Sprintf("Created debug directory: %s", dEnv.dst)) + } else { + d.UI.Output(fmt.Sprintf("Created debug archive: %s", dEnv.tarName())) + } + + return 0 +} diff --git a/internal/cli/debug_test.go b/internal/cli/debug_test.go new file mode 100644 index 0000000000..f77cf839ac --- /dev/null +++ b/internal/cli/debug_test.go @@ -0,0 +1,112 @@ +package cli + +import ( + "os" + "path" + "strconv" + "testing" + "time" + + "github.com/mitchellh/cli" + "github.com/stretchr/testify/assert" + + "github.com/ethereum/go-ethereum/internal/cli/server" +) + +var currentDir string = "" + +func TestCommand_DebugBlock(t *testing.T) { + t.Parallel() + + // Start a blockchain in developer mode and get trace of block + config := server.DefaultConfig() + + // enable developer mode + config.Developer.Enabled = true + config.Developer.Period = 2 // block time + + // enable archive mode for getting traces of ancient blocks + config.GcMode = "archive" + + // start the mock server + srv, err := server.CreateMockServer(config) + assert.NoError(t, err) + + defer server.CloseMockServer(srv) + + // get the grpc port + port := srv.GetGrpcAddr() + + // wait for 4 seconds to mine a 2 blocks + time.Sleep(2 * time.Duration(config.Developer.Period) * time.Second) + + // add prefix for debug trace + prefix := "bor-block-trace-" + + // output dir + output := "debug_block_test" + + // set current directory + currentDir, _ = os.Getwd() + + // trace 1st block + start := time.Now() + dst1 := path.Join(output, prefix+time.Now().UTC().Format("2006-01-02-150405Z"), "block.json") + res := traceBlock(port, 1, output) + assert.Equal(t, 0, res) + t.Logf("Completed trace of block %d in %d ms at %s", 1, time.Since(start).Milliseconds(), dst1) + + // adding this to avoid debug directory name conflicts + time.Sleep(time.Second) + + // trace last/recent block + start = time.Now() + latestBlock := srv.GetLatestBlockNumber().Int64() + dst2 := path.Join(output, prefix+time.Now().UTC().Format("2006-01-02-150405Z"), "block.json") + res = traceBlock(port, latestBlock, output) + assert.Equal(t, 0, res) + t.Logf("Completed trace of block %d in %d ms at %s", latestBlock, time.Since(start).Milliseconds(), dst2) + + // verify if the trace files are created + done := verify(dst1) + assert.Equal(t, true, done) + done = verify(dst2) + assert.Equal(t, true, done) + + // delete the traces + deleteTraces(output) +} + +// traceBlock calls the cli command to trace a block +func traceBlock(port string, number int64, output string) int { + ui := cli.NewMockUi() + command := &DebugBlockCommand{ + Meta2: &Meta2{ + UI: ui, + addr: "127.0.0.1:" + port, + }, + } + + // run trace (by explicitly passing the output directory and grpc address) + return command.Run([]string{strconv.FormatInt(number, 10), "--output", output, "--address", command.Meta2.addr}) +} + +// verify checks if the trace file is created at the destination +// directory or not +func verify(dst string) bool { + dst = path.Join(currentDir, dst) + if file, err := os.Stat(dst); err == nil { + // check if the file has content + if file.Size() > 0 { + return true + } + } + + return false +} + +// deleteTraces removes the traces created during the test +func deleteTraces(dst string) { + dst = path.Join(currentDir, dst) + os.RemoveAll(dst) +} diff --git a/internal/cli/server/helper.go b/internal/cli/server/helper.go new file mode 100644 index 0000000000..c6831382b3 --- /dev/null +++ b/internal/cli/server/helper.go @@ -0,0 +1,72 @@ +package server + +import ( + "fmt" + "io/ioutil" + "math/rand" + "net" + "os" + "sync/atomic" + "time" +) + +var maxPortCheck int32 = 100 + +// findAvailablePort returns the next available port starting from `from` +func findAvailablePort(from int32, count int32) (int32, error) { + if count == maxPortCheck { + return 0, fmt.Errorf("no available port found") + } + port := atomic.AddInt32(&from, 1) + addr := fmt.Sprintf("localhost:%d", port) + lis, err := net.Listen("tcp", addr) + count++ + if err == nil { + lis.Close() + return port, nil + } else { + return findAvailablePort(from, count) + } +} + +func CreateMockServer(config *Config) (*Server, error) { + if config == nil { + config = DefaultConfig() + } + + // find available port for grpc server + rand.Seed(time.Now().UnixNano()) + var from int32 = 60000 // the min port to start checking from + var to int32 = 61000 // the max port to start checking from + port, err := findAvailablePort(rand.Int31n(to-from+1)+from, 0) + if err != nil { + return nil, err + } + + // grpc port + config.GRPC.Addr = fmt.Sprintf(":%d", port) + + // datadir + datadir, _ := ioutil.TempDir("/tmp", "bor-cli-test") + config.DataDir = datadir + + // find available port for http server + from = 8545 + to = 9545 + port, err = findAvailablePort(rand.Int31n(to-from+1)+from, 0) + if err != nil { + return nil, err + } + config.JsonRPC.Http.Port = uint64(port) + + // start the server + return NewServer(config) +} + +func CloseMockServer(server *Server) { + // remove the contents of temp data dir + os.RemoveAll(server.config.DataDir) + + // close the server + server.Stop() +} diff --git a/internal/cli/server/proto/server.pb.go b/internal/cli/server/proto/server.pb.go index 2b45fb37e9..5512d83b72 100644 --- a/internal/cli/server/proto/server.pb.go +++ b/internal/cli/server/proto/server.pb.go @@ -1,13 +1,12 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.25.0 +// protoc-gen-go v1.27.1 // protoc v3.19.3 // source: internal/cli/server/proto/server.proto package proto import ( - proto "github.com/golang/protobuf/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" @@ -22,57 +21,138 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -type PprofRequest_Type int32 +type DebugPprofRequest_Type int32 const ( - PprofRequest_LOOKUP PprofRequest_Type = 0 - PprofRequest_CPU PprofRequest_Type = 1 - PprofRequest_TRACE PprofRequest_Type = 2 + DebugPprofRequest_LOOKUP DebugPprofRequest_Type = 0 + DebugPprofRequest_CPU DebugPprofRequest_Type = 1 + DebugPprofRequest_TRACE DebugPprofRequest_Type = 2 ) -// Enum value maps for PprofRequest_Type. +// Enum value maps for DebugPprofRequest_Type. var ( - PprofRequest_Type_name = map[int32]string{ + DebugPprofRequest_Type_name = map[int32]string{ 0: "LOOKUP", 1: "CPU", 2: "TRACE", } - PprofRequest_Type_value = map[string]int32{ + DebugPprofRequest_Type_value = map[string]int32{ "LOOKUP": 0, "CPU": 1, "TRACE": 2, } ) -func (x PprofRequest_Type) Enum() *PprofRequest_Type { - p := new(PprofRequest_Type) +func (x DebugPprofRequest_Type) Enum() *DebugPprofRequest_Type { + p := new(DebugPprofRequest_Type) *p = x return p } -func (x PprofRequest_Type) String() string { +func (x DebugPprofRequest_Type) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } -func (PprofRequest_Type) Descriptor() protoreflect.EnumDescriptor { +func (DebugPprofRequest_Type) Descriptor() protoreflect.EnumDescriptor { return file_internal_cli_server_proto_server_proto_enumTypes[0].Descriptor() } -func (PprofRequest_Type) Type() protoreflect.EnumType { +func (DebugPprofRequest_Type) Type() protoreflect.EnumType { return &file_internal_cli_server_proto_server_proto_enumTypes[0] } -func (x PprofRequest_Type) Number() protoreflect.EnumNumber { +func (x DebugPprofRequest_Type) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// Deprecated: Use PprofRequest_Type.Descriptor instead. -func (PprofRequest_Type) EnumDescriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16, 0} +// Deprecated: Use DebugPprofRequest_Type.Descriptor instead. +func (DebugPprofRequest_Type) EnumDescriptor() ([]byte, []int) { + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{18, 0} +} + +type TraceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"` +} + +func (x *TraceRequest) Reset() { + *x = TraceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TraceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TraceRequest) ProtoMessage() {} + +func (x *TraceRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TraceRequest.ProtoReflect.Descriptor instead. +func (*TraceRequest) Descriptor() ([]byte, []int) { + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{0} +} + +func (x *TraceRequest) GetNumber() int64 { + if x != nil { + return x.Number + } + return 0 +} + +type TraceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *TraceResponse) Reset() { + *x = TraceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TraceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TraceResponse) ProtoMessage() {} + +func (x *TraceResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TraceResponse.ProtoReflect.Descriptor instead. +func (*TraceResponse) Descriptor() ([]byte, []int) { + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{1} } type ChainWatchRequest struct { @@ -84,7 +164,7 @@ type ChainWatchRequest struct { func (x *ChainWatchRequest) Reset() { *x = ChainWatchRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[0] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -97,7 +177,7 @@ func (x *ChainWatchRequest) String() string { func (*ChainWatchRequest) ProtoMessage() {} func (x *ChainWatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[0] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -110,7 +190,7 @@ func (x *ChainWatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainWatchRequest.ProtoReflect.Descriptor instead. func (*ChainWatchRequest) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{0} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{2} } type ChainWatchResponse struct { @@ -126,7 +206,7 @@ type ChainWatchResponse struct { func (x *ChainWatchResponse) Reset() { *x = ChainWatchResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[1] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -139,7 +219,7 @@ func (x *ChainWatchResponse) String() string { func (*ChainWatchResponse) ProtoMessage() {} func (x *ChainWatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[1] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -152,7 +232,7 @@ func (x *ChainWatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainWatchResponse.ProtoReflect.Descriptor instead. func (*ChainWatchResponse) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{1} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{3} } func (x *ChainWatchResponse) GetOldchain() []*BlockStub { @@ -188,7 +268,7 @@ type BlockStub struct { func (x *BlockStub) Reset() { *x = BlockStub{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[2] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -201,7 +281,7 @@ func (x *BlockStub) String() string { func (*BlockStub) ProtoMessage() {} func (x *BlockStub) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[2] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -214,7 +294,7 @@ func (x *BlockStub) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockStub.ProtoReflect.Descriptor instead. func (*BlockStub) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{2} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{4} } func (x *BlockStub) GetHash() string { @@ -243,7 +323,7 @@ type PeersAddRequest struct { func (x *PeersAddRequest) Reset() { *x = PeersAddRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[3] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -256,7 +336,7 @@ func (x *PeersAddRequest) String() string { func (*PeersAddRequest) ProtoMessage() {} func (x *PeersAddRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[3] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -269,7 +349,7 @@ func (x *PeersAddRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersAddRequest.ProtoReflect.Descriptor instead. func (*PeersAddRequest) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{3} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{5} } func (x *PeersAddRequest) GetEnode() string { @@ -295,7 +375,7 @@ type PeersAddResponse struct { func (x *PeersAddResponse) Reset() { *x = PeersAddResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[4] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -308,7 +388,7 @@ func (x *PeersAddResponse) String() string { func (*PeersAddResponse) ProtoMessage() {} func (x *PeersAddResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[4] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -321,7 +401,7 @@ func (x *PeersAddResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersAddResponse.ProtoReflect.Descriptor instead. func (*PeersAddResponse) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{4} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{6} } type PeersRemoveRequest struct { @@ -336,7 +416,7 @@ type PeersRemoveRequest struct { func (x *PeersRemoveRequest) Reset() { *x = PeersRemoveRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[5] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -349,7 +429,7 @@ func (x *PeersRemoveRequest) String() string { func (*PeersRemoveRequest) ProtoMessage() {} func (x *PeersRemoveRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[5] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -362,7 +442,7 @@ func (x *PeersRemoveRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersRemoveRequest.ProtoReflect.Descriptor instead. func (*PeersRemoveRequest) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{5} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{7} } func (x *PeersRemoveRequest) GetEnode() string { @@ -388,7 +468,7 @@ type PeersRemoveResponse struct { func (x *PeersRemoveResponse) Reset() { *x = PeersRemoveResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[6] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -401,7 +481,7 @@ func (x *PeersRemoveResponse) String() string { func (*PeersRemoveResponse) ProtoMessage() {} func (x *PeersRemoveResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[6] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -414,7 +494,7 @@ func (x *PeersRemoveResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersRemoveResponse.ProtoReflect.Descriptor instead. func (*PeersRemoveResponse) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{6} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{8} } type PeersListRequest struct { @@ -426,7 +506,7 @@ type PeersListRequest struct { func (x *PeersListRequest) Reset() { *x = PeersListRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[7] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -439,7 +519,7 @@ func (x *PeersListRequest) String() string { func (*PeersListRequest) ProtoMessage() {} func (x *PeersListRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[7] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -452,7 +532,7 @@ func (x *PeersListRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersListRequest.ProtoReflect.Descriptor instead. func (*PeersListRequest) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{7} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{9} } type PeersListResponse struct { @@ -466,7 +546,7 @@ type PeersListResponse struct { func (x *PeersListResponse) Reset() { *x = PeersListResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[8] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -479,7 +559,7 @@ func (x *PeersListResponse) String() string { func (*PeersListResponse) ProtoMessage() {} func (x *PeersListResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[8] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -492,7 +572,7 @@ func (x *PeersListResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersListResponse.ProtoReflect.Descriptor instead. func (*PeersListResponse) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{8} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{10} } func (x *PeersListResponse) GetPeers() []*Peer { @@ -513,7 +593,7 @@ type PeersStatusRequest struct { func (x *PeersStatusRequest) Reset() { *x = PeersStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[9] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -526,7 +606,7 @@ func (x *PeersStatusRequest) String() string { func (*PeersStatusRequest) ProtoMessage() {} func (x *PeersStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[9] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -539,7 +619,7 @@ func (x *PeersStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersStatusRequest.ProtoReflect.Descriptor instead. func (*PeersStatusRequest) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{9} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{11} } func (x *PeersStatusRequest) GetEnode() string { @@ -560,7 +640,7 @@ type PeersStatusResponse struct { func (x *PeersStatusResponse) Reset() { *x = PeersStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[10] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -573,7 +653,7 @@ func (x *PeersStatusResponse) String() string { func (*PeersStatusResponse) ProtoMessage() {} func (x *PeersStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[10] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -586,7 +666,7 @@ func (x *PeersStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersStatusResponse.ProtoReflect.Descriptor instead. func (*PeersStatusResponse) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{10} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{12} } func (x *PeersStatusResponse) GetPeer() *Peer { @@ -613,7 +693,7 @@ type Peer struct { func (x *Peer) Reset() { *x = Peer{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[11] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -626,7 +706,7 @@ func (x *Peer) String() string { func (*Peer) ProtoMessage() {} func (x *Peer) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[11] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -639,7 +719,7 @@ func (x *Peer) ProtoReflect() protoreflect.Message { // Deprecated: Use Peer.ProtoReflect.Descriptor instead. func (*Peer) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{11} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{13} } func (x *Peer) GetId() string { @@ -702,7 +782,7 @@ type ChainSetHeadRequest struct { func (x *ChainSetHeadRequest) Reset() { *x = ChainSetHeadRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[12] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -715,7 +795,7 @@ func (x *ChainSetHeadRequest) String() string { func (*ChainSetHeadRequest) ProtoMessage() {} func (x *ChainSetHeadRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[12] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -728,7 +808,7 @@ func (x *ChainSetHeadRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainSetHeadRequest.ProtoReflect.Descriptor instead. func (*ChainSetHeadRequest) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{12} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{14} } func (x *ChainSetHeadRequest) GetNumber() uint64 { @@ -747,7 +827,7 @@ type ChainSetHeadResponse struct { func (x *ChainSetHeadResponse) Reset() { *x = ChainSetHeadResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[13] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -760,7 +840,7 @@ func (x *ChainSetHeadResponse) String() string { func (*ChainSetHeadResponse) ProtoMessage() {} func (x *ChainSetHeadResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[13] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -773,7 +853,7 @@ func (x *ChainSetHeadResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChainSetHeadResponse.ProtoReflect.Descriptor instead. func (*ChainSetHeadResponse) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{13} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{15} } type StatusResponse struct { @@ -792,7 +872,7 @@ type StatusResponse struct { func (x *StatusResponse) Reset() { *x = StatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[14] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -805,7 +885,7 @@ func (x *StatusResponse) String() string { func (*StatusResponse) ProtoMessage() {} func (x *StatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[14] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -818,7 +898,7 @@ func (x *StatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. func (*StatusResponse) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{14} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16} } func (x *StatusResponse) GetCurrentBlock() *Header { @@ -875,7 +955,7 @@ type Header struct { func (x *Header) Reset() { *x = Header{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[15] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -888,7 +968,7 @@ func (x *Header) String() string { func (*Header) ProtoMessage() {} func (x *Header) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[15] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -901,7 +981,7 @@ func (x *Header) ProtoReflect() protoreflect.Message { // Deprecated: Use Header.ProtoReflect.Descriptor instead. func (*Header) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{15} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{17} } func (x *Header) GetHash() string { @@ -918,33 +998,33 @@ func (x *Header) GetNumber() uint64 { return 0 } -type PprofRequest struct { +type DebugPprofRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Type PprofRequest_Type `protobuf:"varint,1,opt,name=type,proto3,enum=proto.PprofRequest_Type" json:"type,omitempty"` - Profile string `protobuf:"bytes,2,opt,name=profile,proto3" json:"profile,omitempty"` - Seconds int64 `protobuf:"varint,3,opt,name=seconds,proto3" json:"seconds,omitempty"` + Type DebugPprofRequest_Type `protobuf:"varint,1,opt,name=type,proto3,enum=proto.DebugPprofRequest_Type" json:"type,omitempty"` + Profile string `protobuf:"bytes,2,opt,name=profile,proto3" json:"profile,omitempty"` + Seconds int64 `protobuf:"varint,3,opt,name=seconds,proto3" json:"seconds,omitempty"` } -func (x *PprofRequest) Reset() { - *x = PprofRequest{} +func (x *DebugPprofRequest) Reset() { + *x = DebugPprofRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[16] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *PprofRequest) String() string { +func (x *DebugPprofRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*PprofRequest) ProtoMessage() {} +func (*DebugPprofRequest) ProtoMessage() {} -func (x *PprofRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[16] +func (x *DebugPprofRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -955,61 +1035,108 @@ func (x *PprofRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use PprofRequest.ProtoReflect.Descriptor instead. -func (*PprofRequest) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16} +// Deprecated: Use DebugPprofRequest.ProtoReflect.Descriptor instead. +func (*DebugPprofRequest) Descriptor() ([]byte, []int) { + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{18} } -func (x *PprofRequest) GetType() PprofRequest_Type { +func (x *DebugPprofRequest) GetType() DebugPprofRequest_Type { if x != nil { return x.Type } - return PprofRequest_LOOKUP + return DebugPprofRequest_LOOKUP } -func (x *PprofRequest) GetProfile() string { +func (x *DebugPprofRequest) GetProfile() string { if x != nil { return x.Profile } return "" } -func (x *PprofRequest) GetSeconds() int64 { +func (x *DebugPprofRequest) GetSeconds() int64 { if x != nil { return x.Seconds } return 0 } -type PprofResponse struct { +type DebugBlockRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Number int64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"` +} + +func (x *DebugBlockRequest) Reset() { + *x = DebugBlockRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DebugBlockRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DebugBlockRequest) ProtoMessage() {} + +func (x *DebugBlockRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DebugBlockRequest.ProtoReflect.Descriptor instead. +func (*DebugBlockRequest) Descriptor() ([]byte, []int) { + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{19} +} + +func (x *DebugBlockRequest) GetNumber() int64 { + if x != nil { + return x.Number + } + return 0 +} + +type DebugFileResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to Event: - // *PprofResponse_Open_ - // *PprofResponse_Input_ - // *PprofResponse_Eof - Event isPprofResponse_Event `protobuf_oneof:"event"` + // *DebugFileResponse_Open_ + // *DebugFileResponse_Input_ + // *DebugFileResponse_Eof + Event isDebugFileResponse_Event `protobuf_oneof:"event"` } -func (x *PprofResponse) Reset() { - *x = PprofResponse{} +func (x *DebugFileResponse) Reset() { + *x = DebugFileResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[17] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *PprofResponse) String() string { +func (x *DebugFileResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*PprofResponse) ProtoMessage() {} +func (*DebugFileResponse) ProtoMessage() {} -func (x *PprofResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[17] +func (x *DebugFileResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1020,60 +1147,60 @@ func (x *PprofResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use PprofResponse.ProtoReflect.Descriptor instead. -func (*PprofResponse) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{17} +// Deprecated: Use DebugFileResponse.ProtoReflect.Descriptor instead. +func (*DebugFileResponse) Descriptor() ([]byte, []int) { + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{20} } -func (m *PprofResponse) GetEvent() isPprofResponse_Event { +func (m *DebugFileResponse) GetEvent() isDebugFileResponse_Event { if m != nil { return m.Event } return nil } -func (x *PprofResponse) GetOpen() *PprofResponse_Open { - if x, ok := x.GetEvent().(*PprofResponse_Open_); ok { +func (x *DebugFileResponse) GetOpen() *DebugFileResponse_Open { + if x, ok := x.GetEvent().(*DebugFileResponse_Open_); ok { return x.Open } return nil } -func (x *PprofResponse) GetInput() *PprofResponse_Input { - if x, ok := x.GetEvent().(*PprofResponse_Input_); ok { +func (x *DebugFileResponse) GetInput() *DebugFileResponse_Input { + if x, ok := x.GetEvent().(*DebugFileResponse_Input_); ok { return x.Input } return nil } -func (x *PprofResponse) GetEof() *emptypb.Empty { - if x, ok := x.GetEvent().(*PprofResponse_Eof); ok { +func (x *DebugFileResponse) GetEof() *emptypb.Empty { + if x, ok := x.GetEvent().(*DebugFileResponse_Eof); ok { return x.Eof } return nil } -type isPprofResponse_Event interface { - isPprofResponse_Event() +type isDebugFileResponse_Event interface { + isDebugFileResponse_Event() } -type PprofResponse_Open_ struct { - Open *PprofResponse_Open `protobuf:"bytes,1,opt,name=open,proto3,oneof"` +type DebugFileResponse_Open_ struct { + Open *DebugFileResponse_Open `protobuf:"bytes,1,opt,name=open,proto3,oneof"` } -type PprofResponse_Input_ struct { - Input *PprofResponse_Input `protobuf:"bytes,2,opt,name=input,proto3,oneof"` +type DebugFileResponse_Input_ struct { + Input *DebugFileResponse_Input `protobuf:"bytes,2,opt,name=input,proto3,oneof"` } -type PprofResponse_Eof struct { +type DebugFileResponse_Eof struct { Eof *emptypb.Empty `protobuf:"bytes,3,opt,name=eof,proto3,oneof"` } -func (*PprofResponse_Open_) isPprofResponse_Event() {} +func (*DebugFileResponse_Open_) isDebugFileResponse_Event() {} -func (*PprofResponse_Input_) isPprofResponse_Event() {} +func (*DebugFileResponse_Input_) isDebugFileResponse_Event() {} -func (*PprofResponse_Eof) isPprofResponse_Event() {} +func (*DebugFileResponse_Eof) isDebugFileResponse_Event() {} type StatusResponse_Fork struct { state protoimpl.MessageState @@ -1088,7 +1215,7 @@ type StatusResponse_Fork struct { func (x *StatusResponse_Fork) Reset() { *x = StatusResponse_Fork{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[18] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1101,7 +1228,7 @@ func (x *StatusResponse_Fork) String() string { func (*StatusResponse_Fork) ProtoMessage() {} func (x *StatusResponse_Fork) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[18] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1114,7 +1241,7 @@ func (x *StatusResponse_Fork) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusResponse_Fork.ProtoReflect.Descriptor instead. func (*StatusResponse_Fork) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{14, 0} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16, 0} } func (x *StatusResponse_Fork) GetName() string { @@ -1151,7 +1278,7 @@ type StatusResponse_Syncing struct { func (x *StatusResponse_Syncing) Reset() { *x = StatusResponse_Syncing{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[19] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1164,7 +1291,7 @@ func (x *StatusResponse_Syncing) String() string { func (*StatusResponse_Syncing) ProtoMessage() {} func (x *StatusResponse_Syncing) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[19] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1177,7 +1304,7 @@ func (x *StatusResponse_Syncing) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusResponse_Syncing.ProtoReflect.Descriptor instead. func (*StatusResponse_Syncing) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{14, 1} + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{16, 1} } func (x *StatusResponse_Syncing) GetStartingBlock() int64 { @@ -1201,32 +1328,31 @@ func (x *StatusResponse_Syncing) GetCurrentBlock() int64 { return 0 } -type PprofResponse_Open struct { +type DebugFileResponse_Open struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Headers map[string]string `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Size int64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"` } -func (x *PprofResponse_Open) Reset() { - *x = PprofResponse_Open{} +func (x *DebugFileResponse_Open) Reset() { + *x = DebugFileResponse_Open{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[20] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *PprofResponse_Open) String() string { +func (x *DebugFileResponse_Open) String() string { return protoimpl.X.MessageStringOf(x) } -func (*PprofResponse_Open) ProtoMessage() {} +func (*DebugFileResponse_Open) ProtoMessage() {} -func (x *PprofResponse_Open) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[20] +func (x *DebugFileResponse_Open) ProtoReflect() protoreflect.Message { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1237,26 +1363,19 @@ func (x *PprofResponse_Open) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use PprofResponse_Open.ProtoReflect.Descriptor instead. -func (*PprofResponse_Open) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{17, 0} +// Deprecated: Use DebugFileResponse_Open.ProtoReflect.Descriptor instead. +func (*DebugFileResponse_Open) Descriptor() ([]byte, []int) { + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{20, 0} } -func (x *PprofResponse_Open) GetHeaders() map[string]string { +func (x *DebugFileResponse_Open) GetHeaders() map[string]string { if x != nil { return x.Headers } return nil } -func (x *PprofResponse_Open) GetSize() int64 { - if x != nil { - return x.Size - } - return 0 -} - -type PprofResponse_Input struct { +type DebugFileResponse_Input struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -1264,23 +1383,23 @@ type PprofResponse_Input struct { Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` } -func (x *PprofResponse_Input) Reset() { - *x = PprofResponse_Input{} +func (x *DebugFileResponse_Input) Reset() { + *x = DebugFileResponse_Input{} if protoimpl.UnsafeEnabled { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[21] + mi := &file_internal_cli_server_proto_server_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *PprofResponse_Input) String() string { +func (x *DebugFileResponse_Input) String() string { return protoimpl.X.MessageStringOf(x) } -func (*PprofResponse_Input) ProtoMessage() {} +func (*DebugFileResponse_Input) ProtoMessage() {} -func (x *PprofResponse_Input) ProtoReflect() protoreflect.Message { - mi := &file_internal_cli_server_proto_server_proto_msgTypes[21] +func (x *DebugFileResponse_Input) ProtoReflect() protoreflect.Message { + mi := &file_internal_cli_server_proto_server_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1291,12 +1410,12 @@ func (x *PprofResponse_Input) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use PprofResponse_Input.ProtoReflect.Descriptor instead. -func (*PprofResponse_Input) Descriptor() ([]byte, []int) { - return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{17, 1} +// Deprecated: Use DebugFileResponse_Input.ProtoReflect.Descriptor instead. +func (*DebugFileResponse_Input) Descriptor() ([]byte, []int) { + return file_internal_cli_server_proto_server_proto_rawDescGZIP(), []int{20, 1} } -func (x *PprofResponse_Input) GetData() []byte { +func (x *DebugFileResponse_Input) GetData() []byte { if x != nil { return x.Data } @@ -1310,158 +1429,170 @@ var file_internal_cli_server_proto_server_proto_rawDesc = []byte{ 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13, 0x0a, 0x11, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x84, 0x01, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6f, 0x6c, - 0x64, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x37, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x53, 0x74, 0x75, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x22, 0x41, 0x0a, 0x0f, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x65, 0x64, 0x22, 0x12, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, - 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x15, - 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x50, 0x65, 0x65, - 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, - 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, - 0x73, 0x22, 0x2a, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x26, 0x0a, 0x0c, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x22, 0x0f, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x0a, 0x11, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, + 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x84, 0x01, 0x0a, 0x12, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x53, 0x74, 0x75, 0x62, 0x52, 0x08, 0x6f, 0x6c, 0x64, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, + 0x2c, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, + 0x74, 0x75, 0x62, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x22, 0x37, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x62, 0x12, 0x12, + 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, + 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x0f, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, + 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x12, 0x0a, + 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x36, 0x0a, - 0x13, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, - 0x04, 0x70, 0x65, 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, - 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x65, 0x6e, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63, 0x61, 0x70, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, - 0x22, 0x2d, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, - 0x16, 0x0a, 0x14, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe2, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, - 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x33, 0x0a, - 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x52, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x1a, - 0x0a, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x79, - 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, + 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2a, 0x0a, 0x12, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x36, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, + 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x22, 0x98, + 0x01, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x65, 0x6e, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x72, 0x12, + 0x12, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63, + 0x61, 0x70, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x22, 0x2d, 0x0a, 0x13, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0xe2, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x33, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0d, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6e, + 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6e, + 0x75, 0x6d, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x4d, + 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x4d, + 0x6f, 0x64, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x05, + 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x73, 0x79, 0x6e, 0x63, - 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x05, - 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x1a, 0x4c, 0x0a, 0x04, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x1a, 0x77, 0x0a, 0x07, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x24, - 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x68, 0x69, 0x67, 0x68, - 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x34, 0x0a, 0x06, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x22, 0x98, 0x01, 0x0a, 0x0c, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x65, - 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x26, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, - 0x06, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x50, 0x55, - 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x02, 0x22, 0xe1, 0x02, - 0x0a, 0x0d, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2f, 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, - 0x12, 0x32, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x05, 0x69, - 0x6e, 0x70, 0x75, 0x74, 0x12, 0x2a, 0x0a, 0x03, 0x65, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x48, 0x00, 0x52, 0x03, 0x65, 0x6f, 0x66, - 0x1a, 0x98, 0x01, 0x0a, 0x04, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x40, 0x0a, 0x07, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x73, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x6b, 0x73, 0x1a, 0x4c, + 0x0a, 0x04, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x77, 0x0a, 0x07, + 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x22, 0x0a, + 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xa2, 0x01, 0x0a, 0x11, + 0x44, 0x65, 0x62, 0x75, 0x67, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x50, 0x70, 0x72, + 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x26, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, + 0x43, 0x50, 0x55, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x02, + 0x22, 0x2b, 0x0a, 0x11, 0x44, 0x65, 0x62, 0x75, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xdd, 0x02, + 0x0a, 0x11, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, + 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e, + 0x48, 0x00, 0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x12, 0x36, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x12, 0x2a, 0x0a, 0x03, 0x65, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x48, 0x00, 0x52, 0x03, 0x65, 0x6f, 0x66, 0x1a, 0x88, 0x01, 0x0a, + 0x04, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x44, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, + 0x65, 0x62, 0x75, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x1a, - 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x1b, 0x0a, 0x05, 0x49, - 0x6e, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x32, 0x8b, 0x04, 0x0a, 0x03, 0x42, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x05, 0x50, 0x70, 0x72, - 0x6f, 0x66, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x70, 0x72, 0x6f, 0x66, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, - 0x3b, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x12, 0x16, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, - 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x19, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, - 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x37, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, - 0x1c, 0x5a, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6c, 0x69, - 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x1b, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x32, 0xdd, 0x04, + 0x0a, 0x03, 0x42, 0x6f, 0x72, 0x12, 0x3b, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, + 0x64, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, + 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, + 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1a, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, + 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x43, 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x18, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x50, 0x70, + 0x72, 0x6f, 0x66, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0a, 0x44, 0x65, 0x62, + 0x75, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x44, 0x65, 0x62, 0x75, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x46, + 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x1c, 0x5a, + 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1477,66 +1608,71 @@ func file_internal_cli_server_proto_server_proto_rawDescGZIP() []byte { } var file_internal_cli_server_proto_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_internal_cli_server_proto_server_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_internal_cli_server_proto_server_proto_msgTypes = make([]protoimpl.MessageInfo, 26) var file_internal_cli_server_proto_server_proto_goTypes = []interface{}{ - (PprofRequest_Type)(0), // 0: proto.PprofRequest.Type - (*ChainWatchRequest)(nil), // 1: proto.ChainWatchRequest - (*ChainWatchResponse)(nil), // 2: proto.ChainWatchResponse - (*BlockStub)(nil), // 3: proto.BlockStub - (*PeersAddRequest)(nil), // 4: proto.PeersAddRequest - (*PeersAddResponse)(nil), // 5: proto.PeersAddResponse - (*PeersRemoveRequest)(nil), // 6: proto.PeersRemoveRequest - (*PeersRemoveResponse)(nil), // 7: proto.PeersRemoveResponse - (*PeersListRequest)(nil), // 8: proto.PeersListRequest - (*PeersListResponse)(nil), // 9: proto.PeersListResponse - (*PeersStatusRequest)(nil), // 10: proto.PeersStatusRequest - (*PeersStatusResponse)(nil), // 11: proto.PeersStatusResponse - (*Peer)(nil), // 12: proto.Peer - (*ChainSetHeadRequest)(nil), // 13: proto.ChainSetHeadRequest - (*ChainSetHeadResponse)(nil), // 14: proto.ChainSetHeadResponse - (*StatusResponse)(nil), // 15: proto.StatusResponse - (*Header)(nil), // 16: proto.Header - (*PprofRequest)(nil), // 17: proto.PprofRequest - (*PprofResponse)(nil), // 18: proto.PprofResponse - (*StatusResponse_Fork)(nil), // 19: proto.StatusResponse.Fork - (*StatusResponse_Syncing)(nil), // 20: proto.StatusResponse.Syncing - (*PprofResponse_Open)(nil), // 21: proto.PprofResponse.Open - (*PprofResponse_Input)(nil), // 22: proto.PprofResponse.Input - nil, // 23: proto.PprofResponse.Open.HeadersEntry - (*emptypb.Empty)(nil), // 24: google.protobuf.Empty + (DebugPprofRequest_Type)(0), // 0: proto.DebugPprofRequest.Type + (*TraceRequest)(nil), // 1: proto.TraceRequest + (*TraceResponse)(nil), // 2: proto.TraceResponse + (*ChainWatchRequest)(nil), // 3: proto.ChainWatchRequest + (*ChainWatchResponse)(nil), // 4: proto.ChainWatchResponse + (*BlockStub)(nil), // 5: proto.BlockStub + (*PeersAddRequest)(nil), // 6: proto.PeersAddRequest + (*PeersAddResponse)(nil), // 7: proto.PeersAddResponse + (*PeersRemoveRequest)(nil), // 8: proto.PeersRemoveRequest + (*PeersRemoveResponse)(nil), // 9: proto.PeersRemoveResponse + (*PeersListRequest)(nil), // 10: proto.PeersListRequest + (*PeersListResponse)(nil), // 11: proto.PeersListResponse + (*PeersStatusRequest)(nil), // 12: proto.PeersStatusRequest + (*PeersStatusResponse)(nil), // 13: proto.PeersStatusResponse + (*Peer)(nil), // 14: proto.Peer + (*ChainSetHeadRequest)(nil), // 15: proto.ChainSetHeadRequest + (*ChainSetHeadResponse)(nil), // 16: proto.ChainSetHeadResponse + (*StatusResponse)(nil), // 17: proto.StatusResponse + (*Header)(nil), // 18: proto.Header + (*DebugPprofRequest)(nil), // 19: proto.DebugPprofRequest + (*DebugBlockRequest)(nil), // 20: proto.DebugBlockRequest + (*DebugFileResponse)(nil), // 21: proto.DebugFileResponse + (*StatusResponse_Fork)(nil), // 22: proto.StatusResponse.Fork + (*StatusResponse_Syncing)(nil), // 23: proto.StatusResponse.Syncing + (*DebugFileResponse_Open)(nil), // 24: proto.DebugFileResponse.Open + (*DebugFileResponse_Input)(nil), // 25: proto.DebugFileResponse.Input + nil, // 26: proto.DebugFileResponse.Open.HeadersEntry + (*emptypb.Empty)(nil), // 27: google.protobuf.Empty } var file_internal_cli_server_proto_server_proto_depIdxs = []int32{ - 3, // 0: proto.ChainWatchResponse.oldchain:type_name -> proto.BlockStub - 3, // 1: proto.ChainWatchResponse.newchain:type_name -> proto.BlockStub - 12, // 2: proto.PeersListResponse.peers:type_name -> proto.Peer - 12, // 3: proto.PeersStatusResponse.peer:type_name -> proto.Peer - 16, // 4: proto.StatusResponse.currentBlock:type_name -> proto.Header - 16, // 5: proto.StatusResponse.currentHeader:type_name -> proto.Header - 20, // 6: proto.StatusResponse.syncing:type_name -> proto.StatusResponse.Syncing - 19, // 7: proto.StatusResponse.forks:type_name -> proto.StatusResponse.Fork - 0, // 8: proto.PprofRequest.type:type_name -> proto.PprofRequest.Type - 21, // 9: proto.PprofResponse.open:type_name -> proto.PprofResponse.Open - 22, // 10: proto.PprofResponse.input:type_name -> proto.PprofResponse.Input - 24, // 11: proto.PprofResponse.eof:type_name -> google.protobuf.Empty - 23, // 12: proto.PprofResponse.Open.headers:type_name -> proto.PprofResponse.Open.HeadersEntry - 17, // 13: proto.Bor.Pprof:input_type -> proto.PprofRequest - 4, // 14: proto.Bor.PeersAdd:input_type -> proto.PeersAddRequest - 6, // 15: proto.Bor.PeersRemove:input_type -> proto.PeersRemoveRequest - 8, // 16: proto.Bor.PeersList:input_type -> proto.PeersListRequest - 10, // 17: proto.Bor.PeersStatus:input_type -> proto.PeersStatusRequest - 13, // 18: proto.Bor.ChainSetHead:input_type -> proto.ChainSetHeadRequest - 24, // 19: proto.Bor.Status:input_type -> google.protobuf.Empty - 1, // 20: proto.Bor.ChainWatch:input_type -> proto.ChainWatchRequest - 18, // 21: proto.Bor.Pprof:output_type -> proto.PprofResponse - 5, // 22: proto.Bor.PeersAdd:output_type -> proto.PeersAddResponse - 7, // 23: proto.Bor.PeersRemove:output_type -> proto.PeersRemoveResponse - 9, // 24: proto.Bor.PeersList:output_type -> proto.PeersListResponse - 11, // 25: proto.Bor.PeersStatus:output_type -> proto.PeersStatusResponse - 14, // 26: proto.Bor.ChainSetHead:output_type -> proto.ChainSetHeadResponse - 15, // 27: proto.Bor.Status:output_type -> proto.StatusResponse - 2, // 28: proto.Bor.ChainWatch:output_type -> proto.ChainWatchResponse - 21, // [21:29] is the sub-list for method output_type - 13, // [13:21] is the sub-list for method input_type + 5, // 0: proto.ChainWatchResponse.oldchain:type_name -> proto.BlockStub + 5, // 1: proto.ChainWatchResponse.newchain:type_name -> proto.BlockStub + 14, // 2: proto.PeersListResponse.peers:type_name -> proto.Peer + 14, // 3: proto.PeersStatusResponse.peer:type_name -> proto.Peer + 18, // 4: proto.StatusResponse.currentBlock:type_name -> proto.Header + 18, // 5: proto.StatusResponse.currentHeader:type_name -> proto.Header + 23, // 6: proto.StatusResponse.syncing:type_name -> proto.StatusResponse.Syncing + 22, // 7: proto.StatusResponse.forks:type_name -> proto.StatusResponse.Fork + 0, // 8: proto.DebugPprofRequest.type:type_name -> proto.DebugPprofRequest.Type + 24, // 9: proto.DebugFileResponse.open:type_name -> proto.DebugFileResponse.Open + 25, // 10: proto.DebugFileResponse.input:type_name -> proto.DebugFileResponse.Input + 27, // 11: proto.DebugFileResponse.eof:type_name -> google.protobuf.Empty + 26, // 12: proto.DebugFileResponse.Open.headers:type_name -> proto.DebugFileResponse.Open.HeadersEntry + 6, // 13: proto.Bor.PeersAdd:input_type -> proto.PeersAddRequest + 8, // 14: proto.Bor.PeersRemove:input_type -> proto.PeersRemoveRequest + 10, // 15: proto.Bor.PeersList:input_type -> proto.PeersListRequest + 12, // 16: proto.Bor.PeersStatus:input_type -> proto.PeersStatusRequest + 15, // 17: proto.Bor.ChainSetHead:input_type -> proto.ChainSetHeadRequest + 27, // 18: proto.Bor.Status:input_type -> google.protobuf.Empty + 3, // 19: proto.Bor.ChainWatch:input_type -> proto.ChainWatchRequest + 19, // 20: proto.Bor.DebugPprof:input_type -> proto.DebugPprofRequest + 20, // 21: proto.Bor.DebugBlock:input_type -> proto.DebugBlockRequest + 7, // 22: proto.Bor.PeersAdd:output_type -> proto.PeersAddResponse + 9, // 23: proto.Bor.PeersRemove:output_type -> proto.PeersRemoveResponse + 11, // 24: proto.Bor.PeersList:output_type -> proto.PeersListResponse + 13, // 25: proto.Bor.PeersStatus:output_type -> proto.PeersStatusResponse + 16, // 26: proto.Bor.ChainSetHead:output_type -> proto.ChainSetHeadResponse + 17, // 27: proto.Bor.Status:output_type -> proto.StatusResponse + 4, // 28: proto.Bor.ChainWatch:output_type -> proto.ChainWatchResponse + 21, // 29: proto.Bor.DebugPprof:output_type -> proto.DebugFileResponse + 21, // 30: proto.Bor.DebugBlock:output_type -> proto.DebugFileResponse + 22, // [22:31] is the sub-list for method output_type + 13, // [13:22] is the sub-list for method input_type 13, // [13:13] is the sub-list for extension type_name 13, // [13:13] is the sub-list for extension extendee 0, // [0:13] is the sub-list for field type_name @@ -1549,7 +1685,7 @@ func file_internal_cli_server_proto_server_proto_init() { } if !protoimpl.UnsafeEnabled { file_internal_cli_server_proto_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainWatchRequest); i { + switch v := v.(*TraceRequest); i { case 0: return &v.state case 1: @@ -1561,7 +1697,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainWatchResponse); i { + switch v := v.(*TraceResponse); i { case 0: return &v.state case 1: @@ -1573,7 +1709,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlockStub); i { + switch v := v.(*ChainWatchRequest); i { case 0: return &v.state case 1: @@ -1585,7 +1721,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeersAddRequest); i { + switch v := v.(*ChainWatchResponse); i { case 0: return &v.state case 1: @@ -1597,7 +1733,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeersAddResponse); i { + switch v := v.(*BlockStub); i { case 0: return &v.state case 1: @@ -1609,7 +1745,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeersRemoveRequest); i { + switch v := v.(*PeersAddRequest); i { case 0: return &v.state case 1: @@ -1621,7 +1757,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeersRemoveResponse); i { + switch v := v.(*PeersAddResponse); i { case 0: return &v.state case 1: @@ -1633,7 +1769,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeersListRequest); i { + switch v := v.(*PeersRemoveRequest); i { case 0: return &v.state case 1: @@ -1645,7 +1781,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeersListResponse); i { + switch v := v.(*PeersRemoveResponse); i { case 0: return &v.state case 1: @@ -1657,7 +1793,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeersStatusRequest); i { + switch v := v.(*PeersListRequest); i { case 0: return &v.state case 1: @@ -1669,7 +1805,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeersStatusResponse); i { + switch v := v.(*PeersListResponse); i { case 0: return &v.state case 1: @@ -1681,7 +1817,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Peer); i { + switch v := v.(*PeersStatusRequest); i { case 0: return &v.state case 1: @@ -1693,7 +1829,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainSetHeadRequest); i { + switch v := v.(*PeersStatusResponse); i { case 0: return &v.state case 1: @@ -1705,7 +1841,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainSetHeadResponse); i { + switch v := v.(*Peer); i { case 0: return &v.state case 1: @@ -1717,7 +1853,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StatusResponse); i { + switch v := v.(*ChainSetHeadRequest); i { case 0: return &v.state case 1: @@ -1729,7 +1865,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Header); i { + switch v := v.(*ChainSetHeadResponse); i { case 0: return &v.state case 1: @@ -1741,7 +1877,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PprofRequest); i { + switch v := v.(*StatusResponse); i { case 0: return &v.state case 1: @@ -1753,7 +1889,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PprofResponse); i { + switch v := v.(*Header); i { case 0: return &v.state case 1: @@ -1765,7 +1901,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StatusResponse_Fork); i { + switch v := v.(*DebugPprofRequest); i { case 0: return &v.state case 1: @@ -1777,7 +1913,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StatusResponse_Syncing); i { + switch v := v.(*DebugBlockRequest); i { case 0: return &v.state case 1: @@ -1789,7 +1925,7 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PprofResponse_Open); i { + switch v := v.(*DebugFileResponse); i { case 0: return &v.state case 1: @@ -1801,7 +1937,43 @@ func file_internal_cli_server_proto_server_proto_init() { } } file_internal_cli_server_proto_server_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PprofResponse_Input); i { + switch v := v.(*StatusResponse_Fork); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_cli_server_proto_server_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StatusResponse_Syncing); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_cli_server_proto_server_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DebugFileResponse_Open); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_cli_server_proto_server_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DebugFileResponse_Input); i { case 0: return &v.state case 1: @@ -1813,10 +1985,10 @@ func file_internal_cli_server_proto_server_proto_init() { } } } - file_internal_cli_server_proto_server_proto_msgTypes[17].OneofWrappers = []interface{}{ - (*PprofResponse_Open_)(nil), - (*PprofResponse_Input_)(nil), - (*PprofResponse_Eof)(nil), + file_internal_cli_server_proto_server_proto_msgTypes[20].OneofWrappers = []interface{}{ + (*DebugFileResponse_Open_)(nil), + (*DebugFileResponse_Input_)(nil), + (*DebugFileResponse_Eof)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -1824,7 +1996,7 @@ func file_internal_cli_server_proto_server_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_cli_server_proto_server_proto_rawDesc, NumEnums: 1, - NumMessages: 23, + NumMessages: 26, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/cli/server/proto/server.proto b/internal/cli/server/proto/server.proto index 7259e7dacb..1520ab6536 100644 --- a/internal/cli/server/proto/server.proto +++ b/internal/cli/server/proto/server.proto @@ -7,8 +7,6 @@ import "google/protobuf/empty.proto"; option go_package = "/internal/cli/server/proto"; service Bor { - rpc Pprof(PprofRequest) returns (stream PprofResponse); - rpc PeersAdd(PeersAddRequest) returns (PeersAddResponse); rpc PeersRemove(PeersRemoveRequest) returns (PeersRemoveResponse); @@ -20,8 +18,20 @@ service Bor { rpc ChainSetHead(ChainSetHeadRequest) returns (ChainSetHeadResponse); rpc Status(google.protobuf.Empty) returns (StatusResponse); - + rpc ChainWatch(ChainWatchRequest) returns (stream ChainWatchResponse); + + rpc DebugPprof(DebugPprofRequest) returns (stream DebugFileResponse); + + rpc DebugBlock(DebugBlockRequest) returns (stream DebugFileResponse); +} + +message TraceRequest { + int64 number = 1; +} + +message TraceResponse { + } message ChainWatchRequest { @@ -113,7 +123,7 @@ message Header { uint64 number = 2; } -message PprofRequest { +message DebugPprofRequest { Type type = 1; string profile = 2; @@ -127,7 +137,11 @@ message PprofRequest { } } -message PprofResponse { +message DebugBlockRequest { + int64 number = 1; +} + +message DebugFileResponse { oneof event { Open open = 1; Input input = 2; @@ -136,7 +150,6 @@ message PprofResponse { message Open { map headers = 1; - int64 size = 2; } message Input { diff --git a/internal/cli/server/proto/server_grpc.pb.go b/internal/cli/server/proto/server_grpc.pb.go index b3a6244c18..63f1fa6187 100644 --- a/internal/cli/server/proto/server_grpc.pb.go +++ b/internal/cli/server/proto/server_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.19.3 +// source: internal/cli/server/proto/server.proto package proto @@ -19,7 +23,6 @@ const _ = grpc.SupportPackageIsVersion7 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type BorClient interface { - Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (Bor_PprofClient, error) PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error) PeersRemove(ctx context.Context, in *PeersRemoveRequest, opts ...grpc.CallOption) (*PeersRemoveResponse, error) PeersList(ctx context.Context, in *PeersListRequest, opts ...grpc.CallOption) (*PeersListResponse, error) @@ -27,6 +30,8 @@ type BorClient interface { ChainSetHead(ctx context.Context, in *ChainSetHeadRequest, opts ...grpc.CallOption) (*ChainSetHeadResponse, error) Status(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StatusResponse, error) ChainWatch(ctx context.Context, in *ChainWatchRequest, opts ...grpc.CallOption) (Bor_ChainWatchClient, error) + DebugPprof(ctx context.Context, in *DebugPprofRequest, opts ...grpc.CallOption) (Bor_DebugPprofClient, error) + DebugBlock(ctx context.Context, in *DebugBlockRequest, opts ...grpc.CallOption) (Bor_DebugBlockClient, error) } type borClient struct { @@ -37,38 +42,6 @@ func NewBorClient(cc grpc.ClientConnInterface) BorClient { return &borClient{cc} } -func (c *borClient) Pprof(ctx context.Context, in *PprofRequest, opts ...grpc.CallOption) (Bor_PprofClient, error) { - stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[0], "/proto.Bor/Pprof", opts...) - if err != nil { - return nil, err - } - x := &borPprofClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type Bor_PprofClient interface { - Recv() (*PprofResponse, error) - grpc.ClientStream -} - -type borPprofClient struct { - grpc.ClientStream -} - -func (x *borPprofClient) Recv() (*PprofResponse, error) { - m := new(PprofResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - func (c *borClient) PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error) { out := new(PeersAddResponse) err := c.cc.Invoke(ctx, "/proto.Bor/PeersAdd", in, out, opts...) @@ -124,7 +97,7 @@ func (c *borClient) Status(ctx context.Context, in *emptypb.Empty, opts ...grpc. } func (c *borClient) ChainWatch(ctx context.Context, in *ChainWatchRequest, opts ...grpc.CallOption) (Bor_ChainWatchClient, error) { - stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[1], "/proto.Bor/ChainWatch", opts...) + stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[0], "/proto.Bor/ChainWatch", opts...) if err != nil { return nil, err } @@ -155,11 +128,74 @@ func (x *borChainWatchClient) Recv() (*ChainWatchResponse, error) { return m, nil } +func (c *borClient) DebugPprof(ctx context.Context, in *DebugPprofRequest, opts ...grpc.CallOption) (Bor_DebugPprofClient, error) { + stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[1], "/proto.Bor/DebugPprof", opts...) + if err != nil { + return nil, err + } + x := &borDebugPprofClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Bor_DebugPprofClient interface { + Recv() (*DebugFileResponse, error) + grpc.ClientStream +} + +type borDebugPprofClient struct { + grpc.ClientStream +} + +func (x *borDebugPprofClient) Recv() (*DebugFileResponse, error) { + m := new(DebugFileResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *borClient) DebugBlock(ctx context.Context, in *DebugBlockRequest, opts ...grpc.CallOption) (Bor_DebugBlockClient, error) { + stream, err := c.cc.NewStream(ctx, &Bor_ServiceDesc.Streams[2], "/proto.Bor/DebugBlock", opts...) + if err != nil { + return nil, err + } + x := &borDebugBlockClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Bor_DebugBlockClient interface { + Recv() (*DebugFileResponse, error) + grpc.ClientStream +} + +type borDebugBlockClient struct { + grpc.ClientStream +} + +func (x *borDebugBlockClient) Recv() (*DebugFileResponse, error) { + m := new(DebugFileResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // BorServer is the server API for Bor service. // All implementations must embed UnimplementedBorServer // for forward compatibility type BorServer interface { - Pprof(*PprofRequest, Bor_PprofServer) error PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error) PeersRemove(context.Context, *PeersRemoveRequest) (*PeersRemoveResponse, error) PeersList(context.Context, *PeersListRequest) (*PeersListResponse, error) @@ -167,6 +203,8 @@ type BorServer interface { ChainSetHead(context.Context, *ChainSetHeadRequest) (*ChainSetHeadResponse, error) Status(context.Context, *emptypb.Empty) (*StatusResponse, error) ChainWatch(*ChainWatchRequest, Bor_ChainWatchServer) error + DebugPprof(*DebugPprofRequest, Bor_DebugPprofServer) error + DebugBlock(*DebugBlockRequest, Bor_DebugBlockServer) error mustEmbedUnimplementedBorServer() } @@ -174,9 +212,6 @@ type BorServer interface { type UnimplementedBorServer struct { } -func (UnimplementedBorServer) Pprof(*PprofRequest, Bor_PprofServer) error { - return status.Errorf(codes.Unimplemented, "method Pprof not implemented") -} func (UnimplementedBorServer) PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PeersAdd not implemented") } @@ -198,6 +233,12 @@ func (UnimplementedBorServer) Status(context.Context, *emptypb.Empty) (*StatusRe func (UnimplementedBorServer) ChainWatch(*ChainWatchRequest, Bor_ChainWatchServer) error { return status.Errorf(codes.Unimplemented, "method ChainWatch not implemented") } +func (UnimplementedBorServer) DebugPprof(*DebugPprofRequest, Bor_DebugPprofServer) error { + return status.Errorf(codes.Unimplemented, "method DebugPprof not implemented") +} +func (UnimplementedBorServer) DebugBlock(*DebugBlockRequest, Bor_DebugBlockServer) error { + return status.Errorf(codes.Unimplemented, "method DebugBlock not implemented") +} func (UnimplementedBorServer) mustEmbedUnimplementedBorServer() {} // UnsafeBorServer may be embedded to opt out of forward compatibility for this service. @@ -211,27 +252,6 @@ func RegisterBorServer(s grpc.ServiceRegistrar, srv BorServer) { s.RegisterService(&Bor_ServiceDesc, srv) } -func _Bor_Pprof_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(PprofRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BorServer).Pprof(m, &borPprofServer{stream}) -} - -type Bor_PprofServer interface { - Send(*PprofResponse) error - grpc.ServerStream -} - -type borPprofServer struct { - grpc.ServerStream -} - -func (x *borPprofServer) Send(m *PprofResponse) error { - return x.ServerStream.SendMsg(m) -} - func _Bor_PeersAdd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(PeersAddRequest) if err := dec(in); err != nil { @@ -361,6 +381,48 @@ func (x *borChainWatchServer) Send(m *ChainWatchResponse) error { return x.ServerStream.SendMsg(m) } +func _Bor_DebugPprof_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(DebugPprofRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(BorServer).DebugPprof(m, &borDebugPprofServer{stream}) +} + +type Bor_DebugPprofServer interface { + Send(*DebugFileResponse) error + grpc.ServerStream +} + +type borDebugPprofServer struct { + grpc.ServerStream +} + +func (x *borDebugPprofServer) Send(m *DebugFileResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _Bor_DebugBlock_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(DebugBlockRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(BorServer).DebugBlock(m, &borDebugBlockServer{stream}) +} + +type Bor_DebugBlockServer interface { + Send(*DebugFileResponse) error + grpc.ServerStream +} + +type borDebugBlockServer struct { + grpc.ServerStream +} + +func (x *borDebugBlockServer) Send(m *DebugFileResponse) error { + return x.ServerStream.SendMsg(m) +} + // Bor_ServiceDesc is the grpc.ServiceDesc for Bor service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -395,13 +457,18 @@ var Bor_ServiceDesc = grpc.ServiceDesc{ }, Streams: []grpc.StreamDesc{ { - StreamName: "Pprof", - Handler: _Bor_Pprof_Handler, + StreamName: "ChainWatch", + Handler: _Bor_ChainWatch_Handler, ServerStreams: true, }, { - StreamName: "ChainWatch", - Handler: _Bor_ChainWatch_Handler, + StreamName: "DebugPprof", + Handler: _Bor_DebugPprof_Handler, + ServerStreams: true, + }, + { + StreamName: "DebugBlock", + Handler: _Bor_DebugBlock_Handler, ServerStreams: true, }, }, diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go index 371e588d02..3d0b55e094 100644 --- a/internal/cli/server/server.go +++ b/internal/cli/server/server.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "math/big" "net" "net/http" "os" @@ -43,6 +44,9 @@ type Server struct { grpcServer *grpc.Server tracer *sdktrace.TracerProvider config *Config + + // tracerAPI to trace block executions + tracerAPI *tracers.API } func NewServer(config *Config) (*Server, error) { @@ -162,6 +166,7 @@ func NewServer(config *Config) (*Server, error) { // debug tracing is enabled by default stack.RegisterAPIs(tracers.APIs(srv.backend.APIBackend)) + srv.tracerAPI = tracers.NewAPI(srv.backend.APIBackend) // graphql is started from another place if config.JsonRPC.Graphql.Enabled { @@ -200,6 +205,7 @@ func NewServer(config *Config) (*Server, error) { func (s *Server) Stop() { s.node.Close() + s.grpcServer.Stop() // shutdown the tracer if s.tracer != nil { @@ -354,3 +360,11 @@ func setupLogger(logLevel string) { } log.Root().SetHandler(glogger) } + +func (s *Server) GetLatestBlockNumber() *big.Int { + return s.backend.BlockChain().CurrentBlock().Number() +} + +func (s *Server) GetGrpcAddr() string { + return s.config.GRPC.Addr[1:] +} diff --git a/internal/cli/server/server_test.go b/internal/cli/server/server_test.go index 070739c687..a0b6dee2e3 100644 --- a/internal/cli/server/server_test.go +++ b/internal/cli/server/server_test.go @@ -1,14 +1,33 @@ package server import ( + "fmt" + "net" + "sync/atomic" "testing" "time" + "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/assert" ) -func TestServer_DeveloperMode(t *testing.T) { +var initialPort uint64 = 61000 + +// nextPort gives the next available port starting from 60000 +func nextPort() uint64 { + log.Info("Checking for new port", "current", initialPort) + port := atomic.AddUint64(&initialPort, 1) + addr := fmt.Sprintf("localhost:%d", port) + lis, err := net.Listen("tcp", addr) + if err == nil { + lis.Close() + return port + } else { + return nextPort() + } +} +func TestServer_DeveloperMode(t *testing.T) { // get the default config config := DefaultConfig() @@ -16,17 +35,16 @@ func TestServer_DeveloperMode(t *testing.T) { config.Developer.Enabled = true config.Developer.Period = 2 // block time - // start the server - server, err1 := NewServer(config) - if err1 != nil { - t.Fatalf("failed to start server: %v", err1) - } + // start the mock server + server, err := CreateMockServer(config) + assert.NoError(t, err) + defer CloseMockServer(server) // record the initial block number blockNumber := server.backend.BlockChain().CurrentBlock().Header().Number.Int64() var i int64 = 0 - for i = 0; i < 10; i++ { + for i = 0; i < 3; i++ { // We expect the node to mine blocks every `config.Developer.Period` time period time.Sleep(time.Duration(config.Developer.Period) * time.Second) currBlock := server.backend.BlockChain().CurrentBlock().Header().Number.Int64() @@ -35,7 +53,4 @@ func TestServer_DeveloperMode(t *testing.T) { break } } - - // stop the server - server.Stop() } diff --git a/internal/cli/server/service.go b/internal/cli/server/service.go index e8e3928581..304b61b7d0 100644 --- a/internal/cli/server/service.go +++ b/internal/cli/server/service.go @@ -2,6 +2,7 @@ package server import ( "context" + "encoding/json" "fmt" "math/big" "reflect" @@ -9,6 +10,8 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/internal/cli/server/pprof" "github.com/ethereum/go-ethereum/internal/cli/server/proto" "github.com/ethereum/go-ethereum/p2p" @@ -18,30 +21,14 @@ import ( grpc_net_conn "github.com/mitchellh/go-grpc-net-conn" ) -func (s *Server) Pprof(req *proto.PprofRequest, stream proto.Bor_PprofServer) error { - var payload []byte - var headers map[string]string - var err error - - ctx := context.Background() - switch req.Type { - case proto.PprofRequest_CPU: - payload, headers, err = pprof.CPUProfile(ctx, int(req.Seconds)) - case proto.PprofRequest_TRACE: - payload, headers, err = pprof.Trace(ctx, int(req.Seconds)) - case proto.PprofRequest_LOOKUP: - payload, headers, err = pprof.Profile(req.Profile, 0, 0) - } - if err != nil { - return err - } +const chunkSize = 1024 * 1024 * 1024 +func sendStreamDebugFile(stream proto.Bor_DebugPprofServer, headers map[string]string, data []byte) error { // open the stream and send the headers - err = stream.Send(&proto.PprofResponse{ - Event: &proto.PprofResponse_Open_{ - Open: &proto.PprofResponse_Open{ + err := stream.Send(&proto.DebugFileResponse{ + Event: &proto.DebugFileResponse_Open_{ + Open: &proto.DebugFileResponse_Open{ Headers: headers, - Size: int64(len(payload)), }, }, }) @@ -50,24 +37,51 @@ func (s *Server) Pprof(req *proto.PprofRequest, stream proto.Bor_PprofServer) er } // Wrap our conn around the response. + encoder := grpc_net_conn.SimpleEncoder(func(msg gproto.Message) *[]byte { + return &msg.(*proto.DebugFileResponse_Input).Data + }) conn := &grpc_net_conn.Conn{ Stream: stream, - Request: &proto.PprofResponse_Input{}, - Encode: grpc_net_conn.SimpleEncoder(func(msg gproto.Message) *[]byte { - return &msg.(*proto.PprofResponse_Input).Data - }), + Request: &proto.DebugFileResponse_Input{}, + Encode: grpc_net_conn.ChunkedEncoder(encoder, chunkSize), } - if _, err := conn.Write(payload); err != nil { + if _, err := conn.Write(data); err != nil { return err } // send the eof - err = stream.Send(&proto.PprofResponse{ - Event: &proto.PprofResponse_Eof{}, + err = stream.Send(&proto.DebugFileResponse{ + Event: &proto.DebugFileResponse_Eof{}, }) if err != nil { return err } + + return nil +} + +func (s *Server) DebugPprof(req *proto.DebugPprofRequest, stream proto.Bor_DebugPprofServer) error { + var payload []byte + var headers map[string]string + var err error + + ctx := context.Background() + switch req.Type { + case proto.DebugPprofRequest_CPU: + payload, headers, err = pprof.CPUProfile(ctx, int(req.Seconds)) + case proto.DebugPprofRequest_TRACE: + payload, headers, err = pprof.Trace(ctx, int(req.Seconds)) + case proto.DebugPprofRequest_LOOKUP: + payload, headers, err = pprof.Profile(req.Profile, 0, 0) + } + if err != nil { + return err + } + + // send the file on a grpc stream + if err := sendStreamDebugFile(stream, headers, payload); err != nil { + return err + } return nil } @@ -169,6 +183,32 @@ func headerToProtoHeader(h *types.Header) *proto.Header { } } +func (s *Server) DebugBlock(req *proto.DebugBlockRequest, stream proto.Bor_DebugBlockServer) error { + traceReq := &tracers.TraceBlockRequest{ + Number: req.Number, + Config: &tracers.TraceConfig{ + Config: &logger.Config{ + EnableMemory: true, + }, + }, + } + res, err := s.tracerAPI.TraceBorBlock(traceReq) + if err != nil { + return err + } + + // this is memory heavy + data, err := json.Marshal(res) + if err != nil { + return err + } + if err := sendStreamDebugFile(stream, map[string]string{}, data); err != nil { + return err + } + + return nil +} + var bigIntT = reflect.TypeOf(new(big.Int)).Kind() // gatherForks gathers all the fork numbers via reflection From 9c8bf51f578e4736854937eb903dd82c7d2f0432 Mon Sep 17 00:00:00 2001 From: Evgeny Danilenko <6655321@bk.ru> Date: Wed, 8 Jun 2022 16:39:30 +0300 Subject: [PATCH 78/80] Prepare Bor package for testing (#416) * Limit state sync by gas * Added logging for state-sync total gas usage * Added number of event-records in log * Minor Changes * Minor Fix * Adding individual gasUsed * Minor Fix * it works * fix tests * log wiggle and delay with block number * log delays as numbers * linters * fix tests * restore linters for the project * fix linters * fix * fix * fix * linters * generation * fix tests * remove heimdall wrapper response * linters * remove possible collisions * remove possible collisions * remove possible collisions * tests for unique address generation * generalize set * bor miner tests got restored * fixes after CR * final step and mining test * fix * fix e2e * more tests for Heimdall requests * fix linters Co-authored-by: Ferran Co-authored-by: Shivam Sharma --- .golangci.yml | 3 +- Makefile | 20 +- cmd/clidoc/main.go | 12 +- common/debug/debug.go | 28 ++ common/set/slice.go | 11 + consensus/bor/abi/interface.go | 6 + consensus/bor/api.go | 7 +- consensus/bor/api/caller.go | 14 + consensus/bor/api/caller_mock.go | 53 +++ consensus/bor/bor.go | 416 +++++-------------- consensus/bor/{ => clerk}/clerk.go | 9 +- consensus/bor/contract/client.go | 133 ++++++ consensus/bor/errors.go | 35 +- consensus/bor/genesis.go | 16 + consensus/bor/genesis_contract_mock.go | 69 +++ consensus/bor/genesis_contracts_client.go | 113 ----- consensus/bor/heimdall.go | 13 + consensus/bor/heimdall/client.go | 222 ++++++++++ consensus/bor/heimdall/client_test.go | 35 ++ consensus/bor/heimdall/span/span.go | 20 + consensus/bor/heimdall/span/spanner.go | 200 +++++++++ consensus/bor/rest.go | 177 -------- consensus/bor/snapshot.go | 22 +- consensus/bor/snapshot_test.go | 83 +++- consensus/bor/span.go | 25 +- consensus/bor/span_mock.go | 84 ++++ consensus/bor/statefull/processor.go | 93 +++++ consensus/bor/validators_getter.go | 11 + consensus/bor/validators_getter_mock.go | 51 +++ consensus/bor/valset/error.go | 32 ++ consensus/bor/{ => valset}/validator.go | 3 +- consensus/bor/{ => valset}/validator_set.go | 10 +- consensus/merger.go | 2 + core/bench_test.go | 3 +- core/blockchain.go | 9 +- core/blockchain_reader.go | 16 + core/blockchain_test.go | 2 +- core/chain_makers.go | 16 +- core/state_processor_test.go | 5 +- core/{ => tests}/blockchain_repair_test.go | 136 +++++- core/{ => tests}/blockchain_sethead_test.go | 49 ++- core/{ => tests}/blockchain_snapshot_test.go | 95 +++-- eth/backend.go | 14 +- eth/ethconfig/config.go | 8 +- eth/tracers/api_bor.go | 7 + go.mod | 79 +++- go.sum | 75 +--- internal/cli/flagset/flagset.go | 21 +- internal/cli/server/chains/chain.go | 11 +- internal/cli/server/chains/chain_test.go | 8 + internal/cli/server/command.go | 1 + internal/cli/server/config.go | 53 ++- internal/cli/server/config_test.go | 13 + internal/cli/server/helper.go | 17 +- internal/cli/server/server.go | 39 +- internal/cli/server/server_test.go | 6 + internal/cli/server/service.go | 21 +- miner/fake_miner.go | 233 +++++++++++ miner/miner_test.go | 204 ++++----- miner/unconfirmed_test.go | 7 + miner/worker.go | 4 + miner/worker_test.go | 163 ++++++-- params/config.go | 38 +- tests/bor/bor_test.go | 107 +++-- tests/bor/helper.go | 57 ++- tests/bor/mocks/IHeimdallClient.go | 125 +++--- tests/deps/fake.go | 7 + trie/hasher.go | 3 +- 68 files changed, 2508 insertions(+), 1172 deletions(-) create mode 100644 common/debug/debug.go create mode 100644 common/set/slice.go create mode 100644 consensus/bor/abi/interface.go create mode 100644 consensus/bor/api/caller.go create mode 100644 consensus/bor/api/caller_mock.go rename consensus/bor/{ => clerk}/clerk.go (85%) create mode 100644 consensus/bor/contract/client.go create mode 100644 consensus/bor/genesis.go create mode 100644 consensus/bor/genesis_contract_mock.go delete mode 100644 consensus/bor/genesis_contracts_client.go create mode 100644 consensus/bor/heimdall.go create mode 100644 consensus/bor/heimdall/client.go create mode 100644 consensus/bor/heimdall/client_test.go create mode 100644 consensus/bor/heimdall/span/span.go create mode 100644 consensus/bor/heimdall/span/spanner.go delete mode 100644 consensus/bor/rest.go create mode 100644 consensus/bor/span_mock.go create mode 100644 consensus/bor/statefull/processor.go create mode 100644 consensus/bor/validators_getter.go create mode 100644 consensus/bor/validators_getter_mock.go create mode 100644 consensus/bor/valset/error.go rename consensus/bor/{ => valset}/validator.go (99%) rename consensus/bor/{ => valset}/validator_set.go (99%) rename core/{ => tests}/blockchain_repair_test.go (93%) rename core/{ => tests}/blockchain_sethead_test.go (98%) rename core/{ => tests}/blockchain_snapshot_test.go (87%) create mode 100644 miner/fake_miner.go create mode 100644 tests/deps/fake.go diff --git a/.golangci.yml b/.golangci.yml index b063984061..89a9e328b8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,7 @@ # This file configures github.com/golangci/golangci-lint. run: + go: '1.18' timeout: 20m tests: true # default is true. Enables skipping of directories: @@ -183,4 +184,4 @@ issues: max-issues-per-linter: 0 max-same-issues: 0 #new: true - # new-from-rev: origin/master \ No newline at end of file + new-from-rev: origin/master \ No newline at end of file diff --git a/Makefile b/Makefile index 53b3cd9fdb..46ecdec886 100644 --- a/Makefile +++ b/Makefile @@ -65,9 +65,7 @@ escape: cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out lint: - @./build/bin/golangci-lint run --config ./.golangci.yml \ - internal/cli \ - consensus/bor + @./build/bin/golangci-lint run --config ./.golangci.yml lintci-deps: rm -f ./build/bin/golangci-lint @@ -87,16 +85,20 @@ clean: # You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'. devtools: - env GOBIN= go install golang.org/x/tools/cmd/stringer@latest - env GOBIN= go install github.com/kevinburke/go-bindata/go-bindata@latest - env GOBIN= go install github.com/fjl/gencodec@latest - env GOBIN= go install github.com/golang/protobuf/protoc-gen-go@latest - env GOBIN= go install ./cmd/abigen + # Notice! If you adding new binary - add it also to tests/deps/fake.go file + $(GOBUILD) -o $(GOBIN)/stringer github.com/golang.org/x/tools/cmd/stringer + $(GOBUILD) -o $(GOBIN)/go-bindata github.com/kevinburke/go-bindata/go-bindata + $(GOBUILD) -o $(GOBIN)/codecgen github.com/ugorji/go/codec/codecgen + $(GOBUILD) -o $(GOBIN)/abigen ./cmd/abigen + $(GOBUILD) -o $(GOBIN)/mockgen github.com/golang/mock/mockgen + $(GOBUILD) -o $(GOBIN)/protoc-gen-go github.com/golang/protobuf/protoc-gen-go + PATH=$(GOBIN):$(PATH) go generate ./common + PATH=$(GOBIN):$(PATH) go generate ./core/types + PATH=$(GOBIN):$(PATH) go generate ./consensus/bor @type "solc" 2> /dev/null || echo 'Please install solc' @type "protoc" 2> /dev/null || echo 'Please install protoc' # Cross Compilation Targets (xgo) - geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios @echo "Full cross compilation done:" @ls -ld $(GOBIN)/geth-* diff --git a/cmd/clidoc/main.go b/cmd/clidoc/main.go index 70ad35501b..07efc04556 100644 --- a/cmd/clidoc/main.go +++ b/cmd/clidoc/main.go @@ -17,7 +17,6 @@ const ( ) func main() { - commands := cli.Commands() dest := flag.String("d", DefaultDir, "Destination directory where the docs will be generated") @@ -35,10 +34,12 @@ func main() { keys := make([]string, len(commands)) i := 0 + for k := range commands { keys[i] = k i++ } + sort.Strings(keys) for _, name := range keys { @@ -60,12 +61,17 @@ func main() { func overwriteFile(filePath string, text string) { log.Printf("Writing to page: %s\n", filePath) + f, err := os.Create(filePath) if err != nil { log.Fatalln(err) } - f.WriteString(text) - if err := f.Close(); err != nil { + + if _, err = f.WriteString(text); err != nil { + log.Fatalln(err) + } + + if err = f.Close(); err != nil { log.Fatalln(err) } } diff --git a/common/debug/debug.go b/common/debug/debug.go new file mode 100644 index 0000000000..6a677e495d --- /dev/null +++ b/common/debug/debug.go @@ -0,0 +1,28 @@ +package debug + +import ( + "runtime" +) + +// Callers returns given number of callers with packages +func Callers(show int) []string { + fpcs := make([]uintptr, show) + + n := runtime.Callers(2, fpcs) + if n == 0 { + return nil + } + + callers := make([]string, 0, len(fpcs)) + + for _, p := range fpcs { + caller := runtime.FuncForPC(p - 1) + if caller == nil { + continue + } + + callers = append(callers, caller.Name()) + } + + return callers +} diff --git a/common/set/slice.go b/common/set/slice.go new file mode 100644 index 0000000000..36f11e67fe --- /dev/null +++ b/common/set/slice.go @@ -0,0 +1,11 @@ +package set + +func New[T comparable](slice []T) map[T]struct{} { + m := make(map[T]struct{}, len(slice)) + + for _, el := range slice { + m[el] = struct{}{} + } + + return m +} diff --git a/consensus/bor/abi/interface.go b/consensus/bor/abi/interface.go new file mode 100644 index 0000000000..bb05bf0b23 --- /dev/null +++ b/consensus/bor/abi/interface.go @@ -0,0 +1,6 @@ +package abi + +type ABI interface { + Pack(name string, args ...interface{}) ([]byte, error) + UnpackIntoInterface(v interface{}, name string, data []byte) error +} diff --git a/consensus/bor/api.go b/consensus/bor/api.go index 364fc448b8..26d1efdaf1 100644 --- a/consensus/bor/api.go +++ b/consensus/bor/api.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" @@ -206,10 +207,10 @@ func (api *API) GetCurrentProposer() (common.Address, error) { } // GetCurrentValidators gets the current validators -func (api *API) GetCurrentValidators() ([]*Validator, error) { +func (api *API) GetCurrentValidators() ([]*valset.Validator, error) { snap, err := api.GetSnapshot(nil) if err != nil { - return make([]*Validator, 0), err + return make([]*valset.Validator, 0), err } return snap.ValidatorSet.Validators, nil @@ -236,7 +237,7 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) { currentHeaderNumber := api.chain.CurrentHeader().Number.Uint64() if start > end || end > currentHeaderNumber { - return "", &InvalidStartEndBlockError{start, end, currentHeaderNumber} + return "", &valset.InvalidStartEndBlockError{Start: start, End: end, CurrentHeader: currentHeaderNumber} } blockHeaders := make([]*types.Header, end-start+1) diff --git a/consensus/bor/api/caller.go b/consensus/bor/api/caller.go new file mode 100644 index 0000000000..d5fe259c97 --- /dev/null +++ b/consensus/bor/api/caller.go @@ -0,0 +1,14 @@ +package api + +import ( + "context" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/rpc" +) + +//go:generate mockgen -destination=./caller_mock.go -package=api . Caller +type Caller interface { + Call(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *ethapi.StateOverride) (hexutil.Bytes, error) +} diff --git a/consensus/bor/api/caller_mock.go b/consensus/bor/api/caller_mock.go new file mode 100644 index 0000000000..940c99d178 --- /dev/null +++ b/consensus/bor/api/caller_mock.go @@ -0,0 +1,53 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ethereum/go-ethereum/consensus/bor/api (interfaces: Caller) + +// Package api is a generated GoMock package. +package api + +import ( + context "context" + reflect "reflect" + + hexutil "github.com/ethereum/go-ethereum/common/hexutil" + ethapi "github.com/ethereum/go-ethereum/internal/ethapi" + rpc "github.com/ethereum/go-ethereum/rpc" + gomock "github.com/golang/mock/gomock" +) + +// MockCaller is a mock of Caller interface. +type MockCaller struct { + ctrl *gomock.Controller + recorder *MockCallerMockRecorder +} + +// MockCallerMockRecorder is the mock recorder for MockCaller. +type MockCallerMockRecorder struct { + mock *MockCaller +} + +// NewMockCaller creates a new mock instance. +func NewMockCaller(ctrl *gomock.Controller) *MockCaller { + mock := &MockCaller{ctrl: ctrl} + mock.recorder = &MockCallerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockCaller) EXPECT() *MockCallerMockRecorder { + return m.recorder +} + +// Call mocks base method. +func (m *MockCaller) Call(arg0 context.Context, arg1 ethapi.TransactionArgs, arg2 rpc.BlockNumberOrHash, arg3 *ethapi.StateOverride) (hexutil.Bytes, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Call", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(hexutil.Bytes) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Call indicates an expected call of Call. +func (mr *MockCallerMockRecorder) Call(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockCaller)(nil).Call), arg0, arg1, arg2, arg3) +} diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 9e43e67037..2f087af787 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -2,37 +2,34 @@ package bor import ( "bytes" - "context" "encoding/hex" "encoding/json" "errors" "fmt" "io" - "math" "math/big" "sort" "strconv" - "strings" "sync" "time" lru "github.com/hashicorp/golang-lru" "golang.org/x/crypto/sha3" - ethereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/bor/api" + "github.com/ethereum/go-ethereum/consensus/bor/clerk" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" + "github.com/ethereum/go-ethereum/consensus/bor/statefull" + "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -56,7 +53,6 @@ var ( uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. validatorHeaderBytesLength = common.AddressLength + 20 // address + power - systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") ) // Various error messages to mark blocks invalid. These should be private to @@ -100,9 +96,6 @@ var ( // errOutOfRangeChain is returned if an authorization list is attempted to // be modified via out-of-range or non-contiguous headers. errOutOfRangeChain = errors.New("out of range or non-contiguous chain") - - // errShutdownDetected is returned if a shutdown was detected - errShutdownDetected = errors.New("shutdown detected") ) // SignerFn is a signer callback function to request a header to be signed by a @@ -220,24 +213,25 @@ type Bor struct { signFn SignerFn // Signer function to authorize hashes with lock sync.RWMutex // Protects the signer fields - ethAPI *ethapi.PublicBlockChainAPI - GenesisContractsClient *GenesisContractsClient - validatorSetABI abi.ABI - stateReceiverABI abi.ABI + ethAPI api.Caller + spanner Spanner + GenesisContractsClient GenesisContract HeimdallClient IHeimdallClient - WithoutHeimdall bool // The fields below are for testing only fakeDiff bool // Skip difficulty verifications + + closeOnce sync.Once } // New creates a Matic Bor consensus engine. func New( chainConfig *params.ChainConfig, db ethdb.Database, - ethAPI *ethapi.PublicBlockChainAPI, - heimdallURL string, - withoutHeimdall bool, + ethAPI api.Caller, + spanner Spanner, + heimdallClient IHeimdallClient, + genesisContracts GenesisContract, ) *Bor { // get bor config borConfig := chainConfig.Bor @@ -246,14 +240,10 @@ func New( if borConfig != nil && borConfig.Sprint == 0 { borConfig.Sprint = defaultSprintLength } - // Allocate the snapshot caches and create the engine recents, _ := lru.NewARC(inmemorySnapshots) signatures, _ := lru.NewARC(inmemorySignatures) - vABI, _ := abi.JSON(strings.NewReader(validatorsetABI)) - sABI, _ := abi.JSON(strings.NewReader(stateReceiverABI)) - heimdallClient, _ := NewHeimdallClient(heimdallURL) - genesisContractsClient := NewGenesisContractsClient(chainConfig, borConfig.ValidatorContract, borConfig.StateReceiverContract, ethAPI) + c := &Bor{ chainConfig: chainConfig, config: borConfig, @@ -261,11 +251,9 @@ func New( ethAPI: ethAPI, recents: recents, signatures: signatures, - validatorSetABI: vABI, - stateReceiverABI: sABI, - GenesisContractsClient: genesisContractsClient, + spanner: spanner, + GenesisContractsClient: genesisContracts, HeimdallClient: heimdallClient, - WithoutHeimdall: withoutHeimdall, } // make sure we can decode all the GenesisAlloc in the BorConfig. @@ -332,7 +320,7 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head } // check extr adata - isSprintEnd := (number+1)%c.config.Sprint == 0 + isSprintEnd := IsSprintStart(number+1, c.config.Sprint) // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise signersBytes := len(header.Extra) - extraVanity - extraSeal @@ -441,19 +429,18 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t // Retrieve the snapshot needed to verify this header and cache it snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) - if err != nil { return err } // verify the validator list in the last sprint block - if isSprintStart(number, c.config.Sprint) { + if IsSprintStart(number, c.config.Sprint) { parentValidatorBytes := parent.Extra[extraVanity : len(parent.Extra)-extraSeal] validatorsBytes := make([]byte, len(snap.ValidatorSet.Validators)*validatorHeaderBytesLength) currentValidators := snap.ValidatorSet.Copy().Validators // sort validator by address - sort.Sort(ValidatorsByAddress(currentValidators)) + sort.Sort(valset.ValidatorsByAddress(currentValidators)) for i, validator := range currentValidators { copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes()) @@ -487,7 +474,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co // If an on-disk checkpoint snapshot can be found, use that if number%checkpointInterval == 0 { - if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil { + if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil { log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) snap = s @@ -509,13 +496,13 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co hash := checkpoint.Hash() // get validators and current span - validators, err := c.GetCurrentValidators(hash, number+1) + validators, err := c.spanner.GetCurrentValidators(hash, number+1) if err != nil { return nil, err } // new snap shot - snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI) + snap = newSnapshot(c.config, c.signatures, number, hash, validators) if err := snap.store(c.db); err != nil { return nil, err } @@ -674,14 +661,14 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e header.Extra = header.Extra[:extraVanity] // get validator set if number - if (number+1)%c.config.Sprint == 0 { - newValidators, err := c.GetCurrentValidators(header.ParentHash, number+1) + if IsSprintStart(number+1, c.config.Sprint) { + newValidators, err := c.spanner.GetCurrentValidators(header.ParentHash, number+1) if err != nil { return errors.New("unknown validators") } // sort validator by address - sort.Sort(ValidatorsByAddress(newValidators)) + sort.Sort(valset.ValidatorsByAddress(newValidators)) for _, validator := range newValidators { header.Extra = append(header.Extra, validator.HeaderBytes()...) @@ -727,14 +714,14 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, headerNumber := header.Number.Uint64() if headerNumber%c.config.Sprint == 0 { - cx := chainContext{Chain: chain, Bor: c} + cx := statefull.ChainContext{Chain: chain, Bor: c} // check and commit span if err := c.checkAndCommitSpan(state, header, cx); err != nil { log.Error("Error while committing span", "error", err) return } - if !c.WithoutHeimdall { + if c.HeimdallClient != nil { // commit statees stateSyncData, err = c.CommitStates(state, header, cx) if err != nil { @@ -762,7 +749,6 @@ func decodeGenesisAlloc(i interface{}) (core.GenesisAlloc, error) { var alloc core.GenesisAlloc b, err := json.Marshal(i) - if err != nil { return nil, err } @@ -800,7 +786,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ headerNumber := header.Number.Uint64() if headerNumber%c.config.Sprint == 0 { - cx := chainContext{Chain: chain, Bor: c} + cx := statefull.ChainContext{Chain: chain, Bor: c} // check and commit span err := c.checkAndCommitSpan(state, header, cx) @@ -809,7 +795,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ return nil, err } - if !c.WithoutHeimdall { + if c.HeimdallClient != nil { // commit states stateSyncData, err = c.CommitStates(state, header, cx) if err != nil { @@ -832,7 +818,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ block := types.NewBlock(header, txs, nil, receipts, new(trie.Trie)) // set state sync - bc := chain.(*core.BlockChain) + bc := chain.(core.BorStateSyncer) bc.SetStateSync(stateSyncData) // return the final block for sealing @@ -890,15 +876,13 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result wiggle := time.Duration(successionNumber) * time.Duration(c.config.CalculateBackupMultiplier(number)) * time.Second // Sign all the things! - sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header, c.config)) + err = Sign(signFn, signer, header, c.config) if err != nil { return err } - copy(header.Extra[len(header.Extra)-extraSeal:], sighash) - // Wait until sealing is terminated or delay timeout. - log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) + log.Info("Waiting for slot to sign and propagate", "number", number, "hash", header.Hash, "delay-in-sec", uint(delay), "delay", common.PrettyDuration(delay)) go func() { select { @@ -910,6 +894,8 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result log.Info( "Sealing out-of-turn", "number", number, + "hash", header.Hash, + "wiggle-in-sec", uint(wiggle), "wiggle", common.PrettyDuration(wiggle), "in-turn-signer", snap.ValidatorSet.GetProposer().Address.Hex(), ) @@ -932,6 +918,17 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result return nil } +func Sign(signFn SignerFn, signer common.Address, header *types.Header, c *params.BorConfig) error { + sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header, c)) + if err != nil { + return err + } + + copy(header.Extra[len(header.Extra)-extraSeal:], sighash) + + return nil +} + // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty // that a new block should have based on the previous blocks in the chain and the // current signer. @@ -962,114 +959,11 @@ func (c *Bor) APIs(chain consensus.ChainHeaderReader) []rpc.API { // Close implements consensus.Engine. It's a noop for bor as there are no background threads. func (c *Bor) Close() error { - c.HeimdallClient.Close() - return nil -} - -// GetCurrentSpan get current span from contract -func (c *Bor) GetCurrentSpan(headerHash common.Hash) (*Span, error) { - // block - blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false) - - // method - method := "getCurrentSpan" - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - data, err := c.validatorSetABI.Pack(method) - if err != nil { - log.Error("Unable to pack tx for getCurrentSpan", "error", err) - return nil, err - } - - msgData := (hexutil.Bytes)(data) - toAddress := common.HexToAddress(c.config.ValidatorContract) - gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) - result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ - Gas: &gas, - To: &toAddress, - Data: &msgData, - }, blockNr, nil) - - if err != nil { - return nil, err - } - - // span result - ret := new(struct { - Number *big.Int - StartBlock *big.Int - EndBlock *big.Int + c.closeOnce.Do(func() { + c.HeimdallClient.Close() }) - if err := c.validatorSetABI.UnpackIntoInterface(ret, method, result); err != nil { - return nil, err - } - - // create new span - span := Span{ - ID: ret.Number.Uint64(), - StartBlock: ret.StartBlock.Uint64(), - EndBlock: ret.EndBlock.Uint64(), - } - - return &span, nil -} - -// GetCurrentValidators get current validators -func (c *Bor) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*Validator, error) { - // block - blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false) - - // method - method := "getBorValidators" - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - data, err := c.validatorSetABI.Pack(method, big.NewInt(0).SetUint64(blockNumber)) - if err != nil { - log.Error("Unable to pack tx for getValidator", "error", err) - return nil, err - } - - // call - msgData := (hexutil.Bytes)(data) - toAddress := common.HexToAddress(c.config.ValidatorContract) - gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) - result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ - Gas: &gas, - To: &toAddress, - Data: &msgData, - }, blockNr, nil) - - if err != nil { - panic(err) - } - - var ( - ret0 = new([]common.Address) - ret1 = new([]*big.Int) - ) - - out := &[]interface{}{ - ret0, - ret1, - } - - if err := c.validatorSetABI.UnpackIntoInterface(out, method, result); err != nil { - return nil, err - } - - valz := make([]*Validator, len(*ret0)) - for i, a := range *ret0 { - valz[i] = &Validator{ - Address: a, - VotingPower: (*ret1)[i].Int64(), - } - } - return valz, nil + return nil } func (c *Bor) checkAndCommitSpan( @@ -1078,21 +972,20 @@ func (c *Bor) checkAndCommitSpan( chain core.ChainContext, ) error { headerNumber := header.Number.Uint64() - span, err := c.GetCurrentSpan(header.ParentHash) + span, err := c.spanner.GetCurrentSpan(header.ParentHash) if err != nil { return err } if c.needToCommitSpan(span, headerNumber) { - err := c.fetchAndCommitSpan(span.ID+1, state, header, chain) - return err + return c.FetchAndCommitSpan(span.ID+1, state, header, chain) } return nil } -func (c *Bor) needToCommitSpan(span *Span, headerNumber uint64) bool { +func (c *Bor) needToCommitSpan(span *span.Span, headerNumber uint64) bool { // if span is nil if span == nil { return false @@ -1111,15 +1004,16 @@ func (c *Bor) needToCommitSpan(span *Span, headerNumber uint64) bool { return false } -func (c *Bor) fetchAndCommitSpan( +func (c *Bor) FetchAndCommitSpan( newSpanID uint64, state *state.StateDB, header *types.Header, chain core.ChainContext, ) error { - var heimdallSpan HeimdallSpan + var heimdallSpan span.HeimdallSpan - if c.WithoutHeimdall { + if c.HeimdallClient == nil { + // fixme: move to a new mock or fake and remove c.HeimdallClient completely s, err := c.getNextHeimdallSpanForTest(newSpanID, header, chain) if err != nil { return err @@ -1127,105 +1021,51 @@ func (c *Bor) fetchAndCommitSpan( heimdallSpan = *s } else { - response, err := c.HeimdallClient.FetchWithRetry(fmt.Sprintf("bor/span/%d", newSpanID), "") + response, err := c.HeimdallClient.Span(newSpanID) if err != nil { return err } - if err := json.Unmarshal(response.Result, &heimdallSpan); err != nil { - return err - } + heimdallSpan = *response } - // check if chain id matches with heimdall span + // check if chain id matches with Heimdall span if heimdallSpan.ChainID != c.chainConfig.ChainID.String() { return fmt.Errorf( - "Chain id proposed span, %s, and bor chain id, %s, doesn't match", + "chain id proposed span, %s, and bor chain id, %s, doesn't match", heimdallSpan.ChainID, c.chainConfig.ChainID, ) } - // get validators bytes - validators := make([]MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators)) - for _, val := range heimdallSpan.ValidatorSet.Validators { - validators = append(validators, val.MinimalVal()) - } - - validatorBytes, err := rlp.EncodeToBytes(validators) - - if err != nil { - return err - } - - // get producers bytes - producers := make([]MinimalVal, 0, len(heimdallSpan.SelectedProducers)) - for _, val := range heimdallSpan.SelectedProducers { - producers = append(producers, val.MinimalVal()) - } - - producerBytes, err := rlp.EncodeToBytes(producers) - - if err != nil { - return err - } - - // method - method := "commitSpan" - - log.Info("✅ Committing new span", - "id", heimdallSpan.ID, - "startBlock", heimdallSpan.StartBlock, - "endBlock", heimdallSpan.EndBlock, - "validatorBytes", hex.EncodeToString(validatorBytes), - "producerBytes", hex.EncodeToString(producerBytes), - ) - - // get packed data - data, err := c.validatorSetABI.Pack(method, - big.NewInt(0).SetUint64(heimdallSpan.ID), - big.NewInt(0).SetUint64(heimdallSpan.StartBlock), - big.NewInt(0).SetUint64(heimdallSpan.EndBlock), - validatorBytes, - producerBytes, - ) - if err != nil { - log.Error("Unable to pack tx for commitSpan", "error", err) - return err - } - - // get system message - msg := getSystemMessage(common.HexToAddress(c.config.ValidatorContract), data) - - // apply message - return applyMessage(msg, state, header, c.chainConfig, chain) + return c.spanner.CommitSpan(heimdallSpan, state, header, chain) } // CommitStates commit states func (c *Bor) CommitStates( state *state.StateDB, header *types.Header, - chain chainContext, + chain statefull.ChainContext, ) ([]*types.StateSyncData, error) { stateSyncs := make([]*types.StateSyncData, 0) number := header.Number.Uint64() - _lastStateID, err := c.GenesisContractsClient.LastStateId(number - 1) + _lastStateID, err := c.GenesisContractsClient.LastStateId(number - 1) if err != nil { return nil, err } to := time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.Sprint).Time), 0) lastStateID := _lastStateID.Uint64() + log.Info( "Fetching state updates from Heimdall", "fromID", lastStateID+1, "to", to.Format(time.RFC3339)) - eventRecords, err := c.HeimdallClient.FetchStateSyncEvents(lastStateID+1, to.Unix()) - + eventRecords, err := c.HeimdallClient.StateSyncEvents(lastStateID+1, to.Unix()) if err != nil { - log.Error("Error occurred when fetching state sync events", err) + log.Error("Error occurred when fetching state sync events", "stateID", lastStateID+1, "error", err) } if c.config.OverrideStateSyncRecords != nil { @@ -1234,6 +1074,8 @@ func (c *Bor) CommitStates( } } + totalGas := 0 /// limit on gas for state sync per block + chainID := c.chainConfig.ChainID.String() for _, eventRecord := range eventRecords { @@ -1242,7 +1084,7 @@ func (c *Bor) CommitStates( } if err := validateEventRecord(eventRecord, number, to, lastStateID, chainID); err != nil { - log.Error(err.Error()) + log.Error("while validating event record", "block", number, "to", to, "stateID", lastStateID, "error", err.Error()) break } @@ -1252,18 +1094,23 @@ func (c *Bor) CommitStates( Data: hex.EncodeToString(eventRecord.Data), TxHash: eventRecord.TxHash, } + stateSyncs = append(stateSyncs, &stateData) - if err := c.GenesisContractsClient.CommitState(eventRecord, state, header, chain); err != nil { + gasUsed, err := c.GenesisContractsClient.CommitState(eventRecord, state, header, chain) + if err != nil { return nil, err } + + totalGas += int(gasUsed) + lastStateID++ } return stateSyncs, nil } -func validateEventRecord(eventRecord *EventRecordWithTime, number uint64, to time.Time, lastStateID uint64, chainID string) error { +func validateEventRecord(eventRecord *clerk.EventRecordWithTime, number uint64, to time.Time, lastStateID uint64, chainID string) error { // event id should be sequential and event.Time should lie in the range [from, to) if lastStateID+1 != eventRecord.ID || eventRecord.ChainID != chainID || !eventRecord.Time.Before(to) { return &InvalidStateReceivedError{number, lastStateID, &to, eventRecord} @@ -1276,6 +1123,10 @@ func (c *Bor) SetHeimdallClient(h IHeimdallClient) { c.HeimdallClient = h } +func (c *Bor) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) { + return c.spanner.GetCurrentValidators(headerHash, blockNumber) +} + // // Private methods // @@ -1284,16 +1135,16 @@ func (c *Bor) getNextHeimdallSpanForTest( newSpanID uint64, header *types.Header, chain core.ChainContext, -) (*HeimdallSpan, error) { +) (*span.HeimdallSpan, error) { headerNumber := header.Number.Uint64() - span, err := c.GetCurrentSpan(header.ParentHash) + spanBor, err := c.spanner.GetCurrentSpan(header.ParentHash) if err != nil { return nil, err } // get local chain context object - localContext := chain.(chainContext) + localContext := chain.(statefull.ChainContext) // Retrieve the snapshot needed to verify this header and cache it snap, err := c.snapshot(localContext.Chain, headerNumber-1, header.ParentHash, nil) if err != nil { @@ -1301,22 +1152,22 @@ func (c *Bor) getNextHeimdallSpanForTest( } // new span - span.ID = newSpanID - if span.EndBlock == 0 { - span.StartBlock = 256 + spanBor.ID = newSpanID + if spanBor.EndBlock == 0 { + spanBor.StartBlock = 256 } else { - span.StartBlock = span.EndBlock + 1 + spanBor.StartBlock = spanBor.EndBlock + 1 } - span.EndBlock = span.StartBlock + (100 * c.config.Sprint) - 1 + spanBor.EndBlock = spanBor.StartBlock + (100 * c.config.Sprint) - 1 - selectedProducers := make([]Validator, len(snap.ValidatorSet.Validators)) + selectedProducers := make([]valset.Validator, len(snap.ValidatorSet.Validators)) for i, v := range snap.ValidatorSet.Validators { selectedProducers[i] = *v } - heimdallSpan := &HeimdallSpan{ - Span: *span, + heimdallSpan := &span.HeimdallSpan{ + Span: *spanBor, ValidatorSet: *snap.ValidatorSet, SelectedProducers: selectedProducers, ChainID: c.chainConfig.ChainID.String(), @@ -1325,82 +1176,7 @@ func (c *Bor) getNextHeimdallSpanForTest( return heimdallSpan, nil } -// -// Chain context -// - -// chain context -type chainContext struct { - Chain consensus.ChainHeaderReader - Bor consensus.Engine -} - -func (c chainContext) Engine() consensus.Engine { - return c.Bor -} - -func (c chainContext) GetHeader(hash common.Hash, number uint64) *types.Header { - return c.Chain.GetHeader(hash, number) -} - -// callmsg implements core.Message to allow passing it as a transaction simulator. -type callmsg struct { - ethereum.CallMsg -} - -func (m callmsg) From() common.Address { return m.CallMsg.From } -func (m callmsg) Nonce() uint64 { return 0 } -func (m callmsg) CheckNonce() bool { return false } -func (m callmsg) To() *common.Address { return m.CallMsg.To } -func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } -func (m callmsg) Gas() uint64 { return m.CallMsg.Gas } -func (m callmsg) Value() *big.Int { return m.CallMsg.Value } -func (m callmsg) Data() []byte { return m.CallMsg.Data } - -// get system message -func getSystemMessage(toAddress common.Address, data []byte) callmsg { - return callmsg{ - ethereum.CallMsg{ - From: systemAddress, - Gas: math.MaxUint64 / 2, - GasPrice: big.NewInt(0), - Value: big.NewInt(0), - To: &toAddress, - Data: data, - }, - } -} - -// apply message -func applyMessage( - msg callmsg, - state *state.StateDB, - header *types.Header, - chainConfig *params.ChainConfig, - chainContext core.ChainContext, -) error { - // Create a new context to be used in the EVM environment - blockContext := core.NewEVMBlockContext(header, chainContext, &header.Coinbase) - // Create a new environment which holds all relevant information - // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(blockContext, vm.TxContext{}, state, chainConfig, vm.Config{}) - // Apply the transaction to the current state (included in the env) - _, _, err := vmenv.Call( - vm.AccountRef(msg.From()), - *msg.To(), - msg.Data(), - msg.Gas(), - msg.Value(), - ) - // Update the state with pending changes - if err != nil { - state.Finalise(true) - } - - return nil -} - -func validatorContains(a []*Validator, x *Validator) (*Validator, bool) { +func validatorContains(a []*valset.Validator, x *valset.Validator) (*valset.Validator, bool) { for _, n := range a { if n.Address == x.Address { return n, true @@ -1410,11 +1186,11 @@ func validatorContains(a []*Validator, x *Validator) (*Validator, bool) { return nil, false } -func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator) *ValidatorSet { +func getUpdatedValidatorSet(oldValidatorSet *valset.ValidatorSet, newVals []*valset.Validator) *valset.ValidatorSet { v := oldValidatorSet oldVals := v.Validators - changes := make([]*Validator, 0, len(oldVals)) + changes := make([]*valset.Validator, 0, len(oldVals)) for _, ov := range oldVals { if f, ok := validatorContains(newVals, ov); ok { @@ -1433,12 +1209,12 @@ func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator) } if err := v.UpdateWithChangeSet(changes); err != nil { - log.Error("Error while updating change set", err) + log.Error("Error while updating change set", "error", err) } return v } -func isSprintStart(number, sprint uint64) bool { +func IsSprintStart(number, sprint uint64) bool { return number%sprint == 0 } diff --git a/consensus/bor/clerk.go b/consensus/bor/clerk/clerk.go similarity index 85% rename from consensus/bor/clerk.go rename to consensus/bor/clerk/clerk.go index ca610282a5..fedca3df16 100644 --- a/consensus/bor/clerk.go +++ b/consensus/bor/clerk/clerk.go @@ -1,4 +1,4 @@ -package bor +package clerk import ( "fmt" @@ -23,10 +23,10 @@ type EventRecordWithTime struct { Time time.Time `json:"record_time" yaml:"record_time"` } -// String returns the string representations of span -func (e *EventRecordWithTime) String() string { +// String returns the string representation of EventRecord +func (e *EventRecordWithTime) String(gasUsed uint64) string { return fmt.Sprintf( - "id %v, contract %v, data: %v, txHash: %v, logIndex: %v, chainId: %v, time %s", + "id %v, contract %v, data: %v, txHash: %v, logIndex: %v, chainId: %v, time %s, gasUsed %d", e.ID, e.Contract.String(), e.Data.String(), @@ -34,6 +34,7 @@ func (e *EventRecordWithTime) String() string { e.LogIndex, e.ChainID, e.Time.Format(time.RFC3339), + gasUsed, ) } diff --git a/consensus/bor/contract/client.go b/consensus/bor/contract/client.go new file mode 100644 index 0000000000..d65fb5bb15 --- /dev/null +++ b/consensus/bor/contract/client.go @@ -0,0 +1,133 @@ +package contract + +import ( + "context" + "math" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus/bor/api" + "github.com/ethereum/go-ethereum/consensus/bor/clerk" + "github.com/ethereum/go-ethereum/consensus/bor/statefull" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" +) + +var ( + vABI, _ = abi.JSON(strings.NewReader(validatorsetABI)) + sABI, _ = abi.JSON(strings.NewReader(stateReceiverABI)) +) + +func ValidatorSet() abi.ABI { + return vABI +} + +func StateReceiver() abi.ABI { + return sABI +} + +type GenesisContractsClient struct { + validatorSetABI abi.ABI + stateReceiverABI abi.ABI + ValidatorContract string + StateReceiverContract string + chainConfig *params.ChainConfig + ethAPI api.Caller +} + +const ( + validatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]` + stateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]` +) + +func NewGenesisContractsClient( + chainConfig *params.ChainConfig, + validatorContract, + stateReceiverContract string, + ethAPI api.Caller, +) *GenesisContractsClient { + return &GenesisContractsClient{ + validatorSetABI: ValidatorSet(), + stateReceiverABI: StateReceiver(), + ValidatorContract: validatorContract, + StateReceiverContract: stateReceiverContract, + chainConfig: chainConfig, + ethAPI: ethAPI, + } +} + +func (gc *GenesisContractsClient) CommitState( + event *clerk.EventRecordWithTime, + state *state.StateDB, + header *types.Header, + chCtx statefull.ChainContext, +) (uint64, error) { + eventRecord := event.BuildEventRecord() + + recordBytes, err := rlp.EncodeToBytes(eventRecord) + if err != nil { + return 0, err + } + + const method = "commitState" + + t := event.Time.Unix() + + data, err := gc.stateReceiverABI.Pack(method, big.NewInt(0).SetInt64(t), recordBytes) + if err != nil { + log.Error("Unable to pack tx for commitState", "error", err) + return 0, err + } + + msg := statefull.GetSystemMessage(common.HexToAddress(gc.StateReceiverContract), data) + gasUsed, err := statefull.ApplyMessage(msg, state, header, gc.chainConfig, chCtx) + + // Logging event log with time and individual gasUsed + log.Info("→ committing new state", "eventRecord", event.String(gasUsed)) + + if err != nil { + return 0, err + } + + return gasUsed, nil +} + +func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, error) { + blockNr := rpc.BlockNumber(snapshotNumber) + method := "lastStateId" + + data, err := gc.stateReceiverABI.Pack(method) + if err != nil { + log.Error("Unable to pack tx for LastStateId", "error", err) + + return nil, err + } + + msgData := (hexutil.Bytes)(data) + toAddress := common.HexToAddress(gc.StateReceiverContract) + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + + result, err := gc.ethAPI.Call(context.Background(), ethapi.TransactionArgs{ + Gas: &gas, + To: &toAddress, + Data: &msgData, + }, rpc.BlockNumberOrHash{BlockNumber: &blockNr}, nil) + if err != nil { + return nil, err + } + + ret := new(*big.Int) + if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil { + return nil, err + } + + return *ret, nil +} diff --git a/consensus/bor/errors.go b/consensus/bor/errors.go index a1e60d1e21..67f7ef53f3 100644 --- a/consensus/bor/errors.go +++ b/consensus/bor/errors.go @@ -3,36 +3,9 @@ package bor import ( "fmt" "time" -) - -// TotalVotingPowerExceededError is returned when the maximum allowed total voting power is exceeded -type TotalVotingPowerExceededError struct { - Sum int64 - Validators []*Validator -} - -func (e *TotalVotingPowerExceededError) Error() string { - return fmt.Sprintf( - "Total voting power should be guarded to not exceed %v; got: %v; for validator set: %v", - MaxTotalVotingPower, - e.Sum, - e.Validators, - ) -} -type InvalidStartEndBlockError struct { - Start uint64 - End uint64 - CurrentHeader uint64 -} - -func (e *InvalidStartEndBlockError) Error() string { - return fmt.Sprintf( - "Invalid parameters start: %d and end block: %d params", - e.Start, - e.End, - ) -} + "github.com/ethereum/go-ethereum/consensus/bor/clerk" +) type MaxCheckpointLengthExceededError struct { Start uint64 @@ -129,12 +102,12 @@ type InvalidStateReceivedError struct { Number uint64 LastStateID uint64 To *time.Time - Event *EventRecordWithTime + Event *clerk.EventRecordWithTime } func (e *InvalidStateReceivedError) Error() string { return fmt.Sprintf( - "Received invalid event %s at block %d. Requested events until %s. Last state id was %d", + "Received invalid event %v at block %d. Requested events until %s. Last state id was %d", e.Event, e.Number, e.To.Format(time.RFC3339), diff --git a/consensus/bor/genesis.go b/consensus/bor/genesis.go new file mode 100644 index 0000000000..33de53f9ba --- /dev/null +++ b/consensus/bor/genesis.go @@ -0,0 +1,16 @@ +package bor + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/consensus/bor/clerk" + "github.com/ethereum/go-ethereum/consensus/bor/statefull" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" +) + +//go:generate mockgen -destination=./genesis_contract_mock.go -package=bor . GenesisContract +type GenesisContract interface { + CommitState(event *clerk.EventRecordWithTime, state *state.StateDB, header *types.Header, chCtx statefull.ChainContext) (uint64, error) + LastStateId(snapshotNumber uint64) (*big.Int, error) +} diff --git a/consensus/bor/genesis_contract_mock.go b/consensus/bor/genesis_contract_mock.go new file mode 100644 index 0000000000..dfe9390509 --- /dev/null +++ b/consensus/bor/genesis_contract_mock.go @@ -0,0 +1,69 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: GenesisContract) + +// Package bor is a generated GoMock package. +package bor + +import ( + big "math/big" + reflect "reflect" + + clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk" + statefull "github.com/ethereum/go-ethereum/consensus/bor/statefull" + state "github.com/ethereum/go-ethereum/core/state" + types "github.com/ethereum/go-ethereum/core/types" + gomock "github.com/golang/mock/gomock" +) + +// MockGenesisContract is a mock of GenesisContract interface. +type MockGenesisContract struct { + ctrl *gomock.Controller + recorder *MockGenesisContractMockRecorder +} + +// MockGenesisContractMockRecorder is the mock recorder for MockGenesisContract. +type MockGenesisContractMockRecorder struct { + mock *MockGenesisContract +} + +// NewMockGenesisContract creates a new mock instance. +func NewMockGenesisContract(ctrl *gomock.Controller) *MockGenesisContract { + mock := &MockGenesisContract{ctrl: ctrl} + mock.recorder = &MockGenesisContractMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockGenesisContract) EXPECT() *MockGenesisContractMockRecorder { + return m.recorder +} + +// CommitState mocks base method. +func (m *MockGenesisContract) CommitState(arg0 *clerk.EventRecordWithTime, arg1 *state.StateDB, arg2 *types.Header, arg3 statefull.ChainContext) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CommitState", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CommitState indicates an expected call of CommitState. +func (mr *MockGenesisContractMockRecorder) CommitState(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitState", reflect.TypeOf((*MockGenesisContract)(nil).CommitState), arg0, arg1, arg2, arg3) +} + +// LastStateId mocks base method. +func (m *MockGenesisContract) LastStateId(arg0 uint64) (*big.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LastStateId", arg0) + ret0, _ := ret[0].(*big.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// LastStateId indicates an expected call of LastStateId. +func (mr *MockGenesisContractMockRecorder) LastStateId(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastStateId", reflect.TypeOf((*MockGenesisContract)(nil).LastStateId), arg0) +} diff --git a/consensus/bor/genesis_contracts_client.go b/consensus/bor/genesis_contracts_client.go deleted file mode 100644 index 2b36b6e5e0..0000000000 --- a/consensus/bor/genesis_contracts_client.go +++ /dev/null @@ -1,113 +0,0 @@ -package bor - -import ( - "context" - "math" - "math/big" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" -) - -type GenesisContractsClient struct { - validatorSetABI abi.ABI - stateReceiverABI abi.ABI - ValidatorContract string - StateReceiverContract string - chainConfig *params.ChainConfig - ethAPI *ethapi.PublicBlockChainAPI -} - -const validatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]` -const stateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]` - -func NewGenesisContractsClient( - chainConfig *params.ChainConfig, - validatorContract, - stateReceiverContract string, - ethAPI *ethapi.PublicBlockChainAPI, -) *GenesisContractsClient { - vABI, _ := abi.JSON(strings.NewReader(validatorsetABI)) - sABI, _ := abi.JSON(strings.NewReader(stateReceiverABI)) - - return &GenesisContractsClient{ - validatorSetABI: vABI, - stateReceiverABI: sABI, - ValidatorContract: validatorContract, - StateReceiverContract: stateReceiverContract, - chainConfig: chainConfig, - ethAPI: ethAPI, - } -} - -func (gc *GenesisContractsClient) CommitState( - event *EventRecordWithTime, - state *state.StateDB, - header *types.Header, - chCtx chainContext, -) error { - eventRecord := event.BuildEventRecord() - recordBytes, err := rlp.EncodeToBytes(eventRecord) - - if err != nil { - return err - } - - method := "commitState" - t := event.Time.Unix() - data, err := gc.stateReceiverABI.Pack(method, big.NewInt(0).SetInt64(t), recordBytes) - - if err != nil { - log.Error("Unable to pack tx for commitState", "error", err) - return err - } - - log.Info("→ committing new state", "eventRecord", event.String()) - - msg := getSystemMessage(common.HexToAddress(gc.StateReceiverContract), data) - if err := applyMessage(msg, state, header, gc.chainConfig, chCtx); err != nil { - return err - } - - return nil -} - -func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, error) { - blockNr := rpc.BlockNumber(snapshotNumber) - method := "lastStateId" - data, err := gc.stateReceiverABI.Pack(method) - - if err != nil { - log.Error("Unable to pack tx for LastStateId", "error", err) - return nil, err - } - - msgData := (hexutil.Bytes)(data) - toAddress := common.HexToAddress(gc.StateReceiverContract) - gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) - result, err := gc.ethAPI.Call(context.Background(), ethapi.TransactionArgs{ - Gas: &gas, - To: &toAddress, - Data: &msgData, - }, rpc.BlockNumberOrHash{BlockNumber: &blockNr}, nil) - - if err != nil { - return nil, err - } - - var ret = new(*big.Int) - if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil { - return nil, err - } - - return *ret, nil -} diff --git a/consensus/bor/heimdall.go b/consensus/bor/heimdall.go new file mode 100644 index 0000000000..c97a3cda11 --- /dev/null +++ b/consensus/bor/heimdall.go @@ -0,0 +1,13 @@ +package bor + +import ( + "github.com/ethereum/go-ethereum/consensus/bor/clerk" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" +) + +//go:generate mockgen -destination=../../tests/bor/mocks/IHeimdallClient.go -package=mocks . IHeimdallClient +type IHeimdallClient interface { + StateSyncEvents(fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) + Span(spanID uint64) (*span.HeimdallSpan, error) + Close() +} diff --git a/consensus/bor/heimdall/client.go b/consensus/bor/heimdall/client.go new file mode 100644 index 0000000000..c5e1dfb4cf --- /dev/null +++ b/consensus/bor/heimdall/client.go @@ -0,0 +1,222 @@ +package heimdall + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "sort" + "time" + + "github.com/ethereum/go-ethereum/consensus/bor/clerk" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" + "github.com/ethereum/go-ethereum/log" +) + +// errShutdownDetected is returned if a shutdown was detected +var errShutdownDetected = errors.New("shutdown detected") + +const ( + stateFetchLimit = 50 + apiHeimdallTimeout = 5 * time.Second +) + +type StateSyncEventsResponse struct { + Height string `json:"height"` + Result []*clerk.EventRecordWithTime `json:"result"` +} + +type SpanResponse struct { + Height string `json:"height"` + Result span.HeimdallSpan `json:"result"` +} + +type HeimdallClient struct { + urlString string + client http.Client + closeCh chan struct{} +} + +func NewHeimdallClient(urlString string) *HeimdallClient { + return &HeimdallClient{ + urlString: urlString, + client: http.Client{ + Timeout: apiHeimdallTimeout, + }, + closeCh: make(chan struct{}), + } +} + +const ( + fetchStateSyncEventsFormat = "from-id=%d&to-time=%d&limit=%d" + fetchStateSyncEventsPath = "clerk/event-record/list" + + fetchSpanFormat = "bor/span/%d" +) + +func (h *HeimdallClient) StateSyncEvents(fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) { + eventRecords := make([]*clerk.EventRecordWithTime, 0) + + for { + url, err := stateSyncURL(h.urlString, fromID, to) + if err != nil { + return nil, err + } + + log.Info("Fetching state sync events", "queryParams", url.RawQuery) + + response, err := FetchWithRetry[StateSyncEventsResponse](h.client, url, h.closeCh) + if err != nil { + return nil, err + } + + if response == nil || response.Result == nil { + // status 204 + break + } + + eventRecords = append(eventRecords, response.Result...) + + if len(response.Result) < stateFetchLimit { + break + } + + fromID += uint64(stateFetchLimit) + } + + sort.SliceStable(eventRecords, func(i, j int) bool { + return eventRecords[i].ID < eventRecords[j].ID + }) + + return eventRecords, nil +} + +func (h *HeimdallClient) Span(spanID uint64) (*span.HeimdallSpan, error) { + url, err := spanURL(h.urlString, spanID) + if err != nil { + return nil, err + } + + response, err := FetchWithRetry[SpanResponse](h.client, url, h.closeCh) + if err != nil { + return nil, err + } + + return &response.Result, nil +} + +// FetchWithRetry returns data from heimdall with retry +func FetchWithRetry[T any](client http.Client, url *url.URL, closeCh chan struct{}) (*T, error) { + // attempt counter + attempt := 1 + result := new(T) + + ctx, cancel := context.WithTimeout(context.Background(), apiHeimdallTimeout) + + // request data once + body, err := internalFetch(ctx, client, url) + + cancel() + + if err == nil && body != nil { + err = json.Unmarshal(body, result) + if err != nil { + return nil, err + } + + return result, nil + } + + // create a new ticker for retrying the request + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + + for { + log.Info("Retrying again in 5 seconds to fetch data from Heimdall", "path", url.Path, "attempt", attempt) + attempt++ + select { + case <-closeCh: + log.Debug("Shutdown detected, terminating request") + + return nil, errShutdownDetected + case <-ticker.C: + ctx, cancel = context.WithTimeout(context.Background(), apiHeimdallTimeout) + + body, err = internalFetch(ctx, client, url) + + cancel() + + if err == nil && body != nil { + err = json.Unmarshal(body, result) + if err != nil { + return nil, err + } + + return result, nil + } + } + } +} + +func spanURL(urlString string, spanID uint64) (*url.URL, error) { + return makeURL(urlString, fmt.Sprintf(fetchSpanFormat, spanID), "") +} + +func stateSyncURL(urlString string, fromID uint64, to int64) (*url.URL, error) { + queryParams := fmt.Sprintf(fetchStateSyncEventsFormat, fromID, to, stateFetchLimit) + + return makeURL(urlString, fetchStateSyncEventsPath, queryParams) +} + +func makeURL(urlString, rawPath, rawQuery string) (*url.URL, error) { + u, err := url.Parse(urlString) + if err != nil { + return nil, err + } + + u.Path = rawPath + u.RawQuery = rawQuery + + return u, err +} + +// internal fetch method +func internalFetch(ctx context.Context, client http.Client, u *url.URL) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) + if err != nil { + return nil, err + } + + res, err := client.Do(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + // check status code + if res.StatusCode != 200 && res.StatusCode != 204 { + return nil, fmt.Errorf("Error while fetching data from Heimdall") + } + + // unmarshall data from buffer + if res.StatusCode == 204 { + return nil, nil + } + + // get response + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return nil, err + } + + return body, nil +} + +// Close sends a signal to stop the running process +func (h *HeimdallClient) Close() { + close(h.closeCh) + h.client.CloseIdleConnections() +} diff --git a/consensus/bor/heimdall/client_test.go b/consensus/bor/heimdall/client_test.go new file mode 100644 index 0000000000..c423a6f659 --- /dev/null +++ b/consensus/bor/heimdall/client_test.go @@ -0,0 +1,35 @@ +package heimdall + +import ( + "testing" +) + +func TestSpanURL(t *testing.T) { + t.Parallel() + + url, err := spanURL("http://bor0", 1) + if err != nil { + t.Fatal("got an error", err) + } + + const expected = "http://bor0/bor/span/1" + + if url.String() != expected { + t.Fatalf("expected URL %q, got %q", url.String(), expected) + } +} + +func TestStateSyncURL(t *testing.T) { + t.Parallel() + + url, err := stateSyncURL("http://bor0", 10, 100) + if err != nil { + t.Fatal("got an error", err) + } + + const expected = "http://bor0/clerk/event-record/list?from-id=10&to-time=100&limit=50" + + if url.String() != expected { + t.Fatalf("expected URL %q, got %q", url.String(), expected) + } +} diff --git a/consensus/bor/heimdall/span/span.go b/consensus/bor/heimdall/span/span.go new file mode 100644 index 0000000000..5bf85fb341 --- /dev/null +++ b/consensus/bor/heimdall/span/span.go @@ -0,0 +1,20 @@ +package span + +import ( + "github.com/ethereum/go-ethereum/consensus/bor/valset" +) + +// Span Bor represents a current bor span +type Span struct { + ID uint64 `json:"span_id" yaml:"span_id"` + StartBlock uint64 `json:"start_block" yaml:"start_block"` + EndBlock uint64 `json:"end_block" yaml:"end_block"` +} + +// HeimdallSpan represents span from heimdall APIs +type HeimdallSpan struct { + Span + ValidatorSet valset.ValidatorSet `json:"validator_set" yaml:"validator_set"` + SelectedProducers []valset.Validator `json:"selected_producers" yaml:"selected_producers"` + ChainID string `json:"bor_chain_id" yaml:"bor_chain_id"` +} diff --git a/consensus/bor/heimdall/span/spanner.go b/consensus/bor/heimdall/span/spanner.go new file mode 100644 index 0000000000..7bf6e350ee --- /dev/null +++ b/consensus/bor/heimdall/span/spanner.go @@ -0,0 +1,200 @@ +package span + +import ( + "context" + "encoding/hex" + "math" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus/bor/abi" + "github.com/ethereum/go-ethereum/consensus/bor/api" + "github.com/ethereum/go-ethereum/consensus/bor/statefull" + "github.com/ethereum/go-ethereum/consensus/bor/valset" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" +) + +type ChainSpanner struct { + ethAPI api.Caller + validatorSet abi.ABI + chainConfig *params.ChainConfig + validatorContractAddress common.Address +} + +func NewChainSpanner(ethAPI api.Caller, validatorSet abi.ABI, chainConfig *params.ChainConfig, validatorContractAddress common.Address) *ChainSpanner { + return &ChainSpanner{ + ethAPI: ethAPI, + validatorSet: validatorSet, + chainConfig: chainConfig, + validatorContractAddress: validatorContractAddress, + } +} + +// GetCurrentSpan get current span from contract +func (c *ChainSpanner) GetCurrentSpan(headerHash common.Hash) (*Span, error) { + // block + blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false) + + // method + method := "getCurrentSpan" + + data, err := c.validatorSet.Pack(method) + if err != nil { + log.Error("Unable to pack tx for getCurrentSpan", "error", err) + + return nil, err + } + + msgData := (hexutil.Bytes)(data) + toAddress := c.validatorContractAddress + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + + // todo: would we like to have a timeout here? + result, err := c.ethAPI.Call(context.Background(), ethapi.TransactionArgs{ + Gas: &gas, + To: &toAddress, + Data: &msgData, + }, blockNr, nil) + if err != nil { + return nil, err + } + + // span result + ret := new(struct { + Number *big.Int + StartBlock *big.Int + EndBlock *big.Int + }) + + if err := c.validatorSet.UnpackIntoInterface(ret, method, result); err != nil { + return nil, err + } + + // create new span + span := Span{ + ID: ret.Number.Uint64(), + StartBlock: ret.StartBlock.Uint64(), + EndBlock: ret.EndBlock.Uint64(), + } + + return &span, nil +} + +// GetCurrentValidators get current validators +func (c *ChainSpanner) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // method + const method = "getBorValidators" + + data, err := c.validatorSet.Pack(method, big.NewInt(0).SetUint64(blockNumber)) + if err != nil { + log.Error("Unable to pack tx for getValidator", "error", err) + return nil, err + } + + // call + msgData := (hexutil.Bytes)(data) + toAddress := c.validatorContractAddress + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + + // block + blockNr := rpc.BlockNumberOrHashWithHash(headerHash, false) + + result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ + Gas: &gas, + To: &toAddress, + Data: &msgData, + }, blockNr, nil) + if err != nil { + panic(err) + } + + var ( + ret0 = new([]common.Address) + ret1 = new([]*big.Int) + ) + + out := &[]interface{}{ + ret0, + ret1, + } + + if err := c.validatorSet.UnpackIntoInterface(out, method, result); err != nil { + return nil, err + } + + valz := make([]*valset.Validator, len(*ret0)) + for i, a := range *ret0 { + valz[i] = &valset.Validator{ + Address: a, + VotingPower: (*ret1)[i].Int64(), + } + } + + return valz, nil +} + +const method = "commitSpan" + +func (c *ChainSpanner) CommitSpan(heimdallSpan HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error { + // get validators bytes + validators := make([]valset.MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators)) + for _, val := range heimdallSpan.ValidatorSet.Validators { + validators = append(validators, val.MinimalVal()) + } + + validatorBytes, err := rlp.EncodeToBytes(validators) + if err != nil { + return err + } + + // get producers bytes + producers := make([]valset.MinimalVal, 0, len(heimdallSpan.SelectedProducers)) + for _, val := range heimdallSpan.SelectedProducers { + producers = append(producers, val.MinimalVal()) + } + + producerBytes, err := rlp.EncodeToBytes(producers) + if err != nil { + return err + } + + log.Info("✅ Committing new span", + "id", heimdallSpan.ID, + "startBlock", heimdallSpan.StartBlock, + "endBlock", heimdallSpan.EndBlock, + "validatorBytes", hex.EncodeToString(validatorBytes), + "producerBytes", hex.EncodeToString(producerBytes), + ) + + data, err := c.validatorSet.Pack(method, + big.NewInt(0).SetUint64(heimdallSpan.ID), + big.NewInt(0).SetUint64(heimdallSpan.StartBlock), + big.NewInt(0).SetUint64(heimdallSpan.EndBlock), + validatorBytes, + producerBytes, + ) + if err != nil { + log.Error("Unable to pack tx for commitSpan", "error", err) + + return err + } + + // get system message + msg := statefull.GetSystemMessage(c.validatorContractAddress, data) + + // apply message + _, err = statefull.ApplyMessage(msg, state, header, c.chainConfig, chainContext) + + return err +} diff --git a/consensus/bor/rest.go b/consensus/bor/rest.go deleted file mode 100644 index 49ecb38af5..0000000000 --- a/consensus/bor/rest.go +++ /dev/null @@ -1,177 +0,0 @@ -package bor - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "sort" - "time" - - "github.com/ethereum/go-ethereum/log" -) - -var ( - stateFetchLimit = 50 -) - -// ResponseWithHeight defines a response object type that wraps an original -// response with a height. -type ResponseWithHeight struct { - Height string `json:"height"` - Result json.RawMessage `json:"result"` -} - -type IHeimdallClient interface { - Fetch(path string, query string) (*ResponseWithHeight, error) - FetchWithRetry(path string, query string) (*ResponseWithHeight, error) - FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error) - Close() -} - -type HeimdallClient struct { - urlString string - client http.Client - closeCh chan struct{} -} - -func NewHeimdallClient(urlString string) (*HeimdallClient, error) { - h := &HeimdallClient{ - urlString: urlString, - client: http.Client{ - Timeout: 5 * time.Second, - }, - closeCh: make(chan struct{}), - } - - return h, nil -} - -func (h *HeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error) { - eventRecords := make([]*EventRecordWithTime, 0) - - for { - queryParams := fmt.Sprintf("from-id=%d&to-time=%d&limit=%d", fromID, to, stateFetchLimit) - log.Info("Fetching state sync events", "queryParams", queryParams) - response, err := h.FetchWithRetry("clerk/event-record/list", queryParams) - - if err != nil { - return nil, err - } - - var _eventRecords []*EventRecordWithTime - - if response.Result == nil { // status 204 - break - } - - if err := json.Unmarshal(response.Result, &_eventRecords); err != nil { - return nil, err - } - - eventRecords = append(eventRecords, _eventRecords...) - - if len(_eventRecords) < stateFetchLimit { - break - } - - fromID += uint64(stateFetchLimit) - } - - sort.SliceStable(eventRecords, func(i, j int) bool { - return eventRecords[i].ID < eventRecords[j].ID - }) - - return eventRecords, nil -} - -// Fetch fetches response from heimdall -func (h *HeimdallClient) Fetch(rawPath string, rawQuery string) (*ResponseWithHeight, error) { - u, err := url.Parse(h.urlString) - if err != nil { - return nil, err - } - - u.Path = rawPath - u.RawQuery = rawQuery - - return h.internalFetch(u) -} - -// FetchWithRetry returns data from heimdall with retry -func (h *HeimdallClient) FetchWithRetry(rawPath string, rawQuery string) (*ResponseWithHeight, error) { - u, err := url.Parse(h.urlString) - if err != nil { - return nil, err - } - - u.Path = rawPath - u.RawQuery = rawQuery - - // attempt counter - attempt := 1 - - // request data once - res, err := h.internalFetch(u) - if err == nil && res != nil { - return res, nil - } - - // create a new ticker for retrying the request - ticker := time.NewTicker(5 * time.Second) - defer ticker.Stop() - - for { - log.Info("Retrying again in 5 seconds to fetch data from Heimdall", "path", u.Path, "attempt", attempt) - attempt++ - select { - case <-h.closeCh: - log.Debug("Shutdown detected, terminating request") - return nil, errShutdownDetected - case <-ticker.C: - res, err := h.internalFetch(u) - if err == nil && res != nil { - return res, nil - } - } - } -} - -// internal fetch method -func (h *HeimdallClient) internalFetch(u *url.URL) (*ResponseWithHeight, error) { - res, err := h.client.Get(u.String()) // nolint: noctx - if err != nil { - return nil, err - } - defer res.Body.Close() - - // check status code - if res.StatusCode != 200 && res.StatusCode != 204 { - return nil, fmt.Errorf("Error while fetching data from Heimdall") - } - - // unmarshall data from buffer - var response ResponseWithHeight - if res.StatusCode == 204 { - return &response, nil - } - - // get response - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, err - } - - if err := json.Unmarshal(body, &response); err != nil { - return nil, err - } - - return &response, nil -} - -// Close sends a signal to stop the running process -func (h *HeimdallClient) Close() { - close(h.closeCh) - h.client.CloseIdleConnections() -} diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go index 606c28340b..f71ceae0ad 100644 --- a/consensus/bor/snapshot.go +++ b/consensus/bor/snapshot.go @@ -3,24 +3,24 @@ package bor import ( "encoding/json" + "github.com/ethereum/go-ethereum/consensus/bor/valset" + lru "github.com/hashicorp/golang-lru" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" ) // Snapshot is the state of the authorization voting at a given point in time. type Snapshot struct { config *params.BorConfig // Consensus engine parameters to fine tune behavior - ethAPI *ethapi.PublicBlockChainAPI - sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover + sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover Number uint64 `json:"number"` // Block number where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created - ValidatorSet *ValidatorSet `json:"validatorSet"` // Validator set at this moment + ValidatorSet *valset.ValidatorSet `json:"validatorSet"` // Validator set at this moment Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections } @@ -32,16 +32,14 @@ func newSnapshot( sigcache *lru.ARCCache, number uint64, hash common.Hash, - validators []*Validator, - ethAPI *ethapi.PublicBlockChainAPI, + validators []*valset.Validator, ) *Snapshot { snap := &Snapshot{ config: config, - ethAPI: ethAPI, sigcache: sigcache, Number: number, Hash: hash, - ValidatorSet: NewValidatorSet(validators), + ValidatorSet: valset.NewValidatorSet(validators), Recents: make(map[uint64]common.Address), } @@ -49,7 +47,7 @@ func newSnapshot( } // loadSnapshot loads an existing snapshot from the database. -func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash, ethAPI *ethapi.PublicBlockChainAPI) (*Snapshot, error) { +func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) { blob, err := db.Get(append([]byte("bor-"), hash[:]...)) if err != nil { return nil, err @@ -63,10 +61,9 @@ func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Dat snap.config = config snap.sigcache = sigcache - snap.ethAPI = ethAPI // update total voting power - if err := snap.ValidatorSet.updateTotalVotingPower(); err != nil { + if err := snap.ValidatorSet.UpdateTotalVotingPower(); err != nil { return nil, err } @@ -87,7 +84,6 @@ func (s *Snapshot) store(db ethdb.Database) error { func (s *Snapshot) copy() *Snapshot { cpy := &Snapshot{ config: s.config, - ethAPI: s.ethAPI, sigcache: s.sigcache, Number: s.Number, Hash: s.Hash, @@ -155,7 +151,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal] // get validators from headers and use that for new validator set - newVals, _ := ParseValidators(validatorBytes) + newVals, _ := valset.ParseValidators(validatorBytes) v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals) v.IncrementProposerPriority(1) snap.ValidatorSet = v diff --git a/consensus/bor/snapshot_test.go b/consensus/bor/snapshot_test.go index 2bbbc32123..1a3e967613 100644 --- a/consensus/bor/snapshot_test.go +++ b/consensus/bor/snapshot_test.go @@ -7,8 +7,11 @@ import ( "time" "github.com/stretchr/testify/assert" + "pgregory.net/rapid" "github.com/ethereum/go-ethereum/common" + unique "github.com/ethereum/go-ethereum/common/set" + "github.com/ethereum/go-ethereum/consensus/bor/valset" ) const ( @@ -19,7 +22,7 @@ func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) { t.Parallel() validators := buildRandomValidatorSet(numVals) - validatorSet := NewValidatorSet(validators) + validatorSet := valset.NewValidatorSet(validators) snap := Snapshot{ ValidatorSet: validatorSet, } @@ -27,7 +30,6 @@ func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) { // proposer is signer signer := validatorSet.Proposer.Address successionNumber, err := snap.GetSignerSuccessionNumber(signer) - if err != nil { t.Fatalf("%s", err) } @@ -41,20 +43,19 @@ func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) { validators := buildRandomValidatorSet(numVals) // sort validators by address, which is what NewValidatorSet also does - sort.Sort(ValidatorsByAddress(validators)) + sort.Sort(valset.ValidatorsByAddress(validators)) proposerIndex := 32 signerIndex := 56 // give highest ProposerPriority to a particular val, so that they become the proposer validators[proposerIndex].VotingPower = 200 snap := Snapshot{ - ValidatorSet: NewValidatorSet(validators), + ValidatorSet: valset.NewValidatorSet(validators), } // choose a signer at an index greater than proposer index signer := snap.ValidatorSet.Validators[signerIndex].Address successionNumber, err := snap.GetSignerSuccessionNumber(signer) - if err != nil { t.Fatalf("%s", err) } @@ -71,13 +72,12 @@ func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) { // give highest ProposerPriority to a particular val, so that they become the proposer validators[proposerIndex].VotingPower = 200 snap := Snapshot{ - ValidatorSet: NewValidatorSet(validators), + ValidatorSet: valset.NewValidatorSet(validators), } // choose a signer at an index greater than proposer index signer := snap.ValidatorSet.Validators[signerIndex].Address successionNumber, err := snap.GetSignerSuccessionNumber(signer) - if err != nil { t.Fatalf("%s", err) } @@ -90,14 +90,18 @@ func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) { validators := buildRandomValidatorSet(numVals) snap := Snapshot{ - ValidatorSet: NewValidatorSet(validators), + ValidatorSet: valset.NewValidatorSet(validators), } + dummyProposerAddress := randomAddress() - snap.ValidatorSet.Proposer = &Validator{Address: dummyProposerAddress} + snap.ValidatorSet.Proposer = &valset.Validator{Address: dummyProposerAddress} + // choose any signer signer := snap.ValidatorSet.Validators[3].Address + _, err := snap.GetSignerSuccessionNumber(signer) assert.NotNil(t, err) + e, ok := err.(*UnauthorizedProposerError) assert.True(t, ok) assert.Equal(t, dummyProposerAddress.Bytes(), e.Proposer) @@ -108,7 +112,7 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { validators := buildRandomValidatorSet(numVals) snap := Snapshot{ - ValidatorSet: NewValidatorSet(validators), + ValidatorSet: valset.NewValidatorSet(validators), } dummySignerAddress := randomAddress() _, err := snap.GetSignerSuccessionNumber(dummySignerAddress) @@ -119,21 +123,22 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { } // nolint: unparam -func buildRandomValidatorSet(numVals int) []*Validator { +func buildRandomValidatorSet(numVals int) []*valset.Validator { rand.Seed(time.Now().Unix()) - validators := make([]*Validator, numVals) + validators := make([]*valset.Validator, numVals) + valAddrs := randomAddresses(numVals) for i := 0; i < numVals; i++ { - validators[i] = &Validator{ - Address: randomAddress(), + validators[i] = &valset.Validator{ + Address: valAddrs[i], // cannot process validators with voting power 0, hence +1 VotingPower: int64(rand.Intn(99) + 1), } } // sort validators by address, which is what NewValidatorSet also does - sort.Sort(ValidatorsByAddress(validators)) + sort.Sort(valset.ValidatorsByAddress(validators)) return validators } @@ -144,3 +149,51 @@ func randomAddress() common.Address { return common.BytesToAddress(bytes) } + +func randomAddresses(n int) []common.Address { + if n <= 0 { + return []common.Address{} + } + + addrs := make([]common.Address, 0, n) + addrsSet := make(map[common.Address]struct{}, n) + + var ( + addr common.Address + exist bool + ) + + bytes := make([]byte, 32) + + for { + rand.Read(bytes) + + addr = common.BytesToAddress(bytes) + + _, exist = addrsSet[addr] + if !exist { + addrs = append(addrs, addr) + + addrsSet[addr] = struct{}{} + } + + if len(addrs) == n { + return addrs + } + } +} + +func TestRandomAddresses(t *testing.T) { + t.Parallel() + + rapid.Check(t, func(t *rapid.T) { + length := rapid.IntMax(100).Draw(t, "length").(int) + + addrs := randomAddresses(length) + addressSet := unique.New(addrs) + + if len(addrs) != len(addressSet) { + t.Fatalf("length of unique addresses %d, expected %d", len(addressSet), len(addrs)) + } + }) +} diff --git a/consensus/bor/span.go b/consensus/bor/span.go index 2fd0cf1079..4867635b8e 100644 --- a/consensus/bor/span.go +++ b/consensus/bor/span.go @@ -1,16 +1,17 @@ package bor -// Span represents a current bor span -type Span struct { - ID uint64 `json:"span_id" yaml:"span_id"` - StartBlock uint64 `json:"start_block" yaml:"start_block"` - EndBlock uint64 `json:"end_block" yaml:"end_block"` -} +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" + "github.com/ethereum/go-ethereum/consensus/bor/valset" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" +) -// HeimdallSpan represents span from heimdall APIs -type HeimdallSpan struct { - Span - ValidatorSet ValidatorSet `json:"validator_set" yaml:"validator_set"` - SelectedProducers []Validator `json:"selected_producers" yaml:"selected_producers"` - ChainID string `json:"bor_chain_id" yaml:"bor_chain_id"` +//go:generate mockgen -destination=./span_mock.go -package=bor . Spanner +type Spanner interface { + GetCurrentSpan(headerHash common.Hash) (*span.Span, error) + GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) + CommitSpan(heimdallSpan span.HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error } diff --git a/consensus/bor/span_mock.go b/consensus/bor/span_mock.go new file mode 100644 index 0000000000..12ed945234 --- /dev/null +++ b/consensus/bor/span_mock.go @@ -0,0 +1,84 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: Spanner) + +// Package bor is a generated GoMock package. +package bor + +import ( + reflect "reflect" + + common "github.com/ethereum/go-ethereum/common" + span "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" + valset "github.com/ethereum/go-ethereum/consensus/bor/valset" + core "github.com/ethereum/go-ethereum/core" + state "github.com/ethereum/go-ethereum/core/state" + types "github.com/ethereum/go-ethereum/core/types" + gomock "github.com/golang/mock/gomock" +) + +// MockSpanner is a mock of Spanner interface. +type MockSpanner struct { + ctrl *gomock.Controller + recorder *MockSpannerMockRecorder +} + +// MockSpannerMockRecorder is the mock recorder for MockSpanner. +type MockSpannerMockRecorder struct { + mock *MockSpanner +} + +// NewMockSpanner creates a new mock instance. +func NewMockSpanner(ctrl *gomock.Controller) *MockSpanner { + mock := &MockSpanner{ctrl: ctrl} + mock.recorder = &MockSpannerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSpanner) EXPECT() *MockSpannerMockRecorder { + return m.recorder +} + +// CommitSpan mocks base method. +func (m *MockSpanner) CommitSpan(arg0 span.HeimdallSpan, arg1 *state.StateDB, arg2 *types.Header, arg3 core.ChainContext) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// CommitSpan indicates an expected call of CommitSpan. +func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3) +} + +// GetCurrentSpan mocks base method. +func (m *MockSpanner) GetCurrentSpan(arg0 common.Hash) (*span.Span, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentSpan", arg0) + ret0, _ := ret[0].(*span.Span) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentSpan indicates an expected call of GetCurrentSpan. +func (mr *MockSpannerMockRecorder) GetCurrentSpan(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSpan", reflect.TypeOf((*MockSpanner)(nil).GetCurrentSpan), arg0) +} + +// GetCurrentValidators mocks base method. +func (m *MockSpanner) GetCurrentValidators(arg0 common.Hash, arg1 uint64) ([]*valset.Validator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentValidators", arg0, arg1) + ret0, _ := ret[0].([]*valset.Validator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentValidators indicates an expected call of GetCurrentValidators. +func (mr *MockSpannerMockRecorder) GetCurrentValidators(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidators", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidators), arg0, arg1) +} diff --git a/consensus/bor/statefull/processor.go b/consensus/bor/statefull/processor.go new file mode 100644 index 0000000000..e30fb4fd21 --- /dev/null +++ b/consensus/bor/statefull/processor.go @@ -0,0 +1,93 @@ +package statefull + +import ( + "math" + "math/big" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/params" +) + +var systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") + +type ChainContext struct { + Chain consensus.ChainHeaderReader + Bor consensus.Engine +} + +func (c ChainContext) Engine() consensus.Engine { + return c.Bor +} + +func (c ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header { + return c.Chain.GetHeader(hash, number) +} + +// callmsg implements core.Message to allow passing it as a transaction simulator. +type callmsg struct { + ethereum.CallMsg +} + +func (m callmsg) From() common.Address { return m.CallMsg.From } +func (m callmsg) Nonce() uint64 { return 0 } +func (m callmsg) CheckNonce() bool { return false } +func (m callmsg) To() *common.Address { return m.CallMsg.To } +func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } +func (m callmsg) Gas() uint64 { return m.CallMsg.Gas } +func (m callmsg) Value() *big.Int { return m.CallMsg.Value } +func (m callmsg) Data() []byte { return m.CallMsg.Data } + +// get system message +func GetSystemMessage(toAddress common.Address, data []byte) callmsg { + return callmsg{ + ethereum.CallMsg{ + From: systemAddress, + Gas: math.MaxUint64 / 2, + GasPrice: big.NewInt(0), + Value: big.NewInt(0), + To: &toAddress, + Data: data, + }, + } +} + +// apply message +func ApplyMessage( + msg callmsg, + state *state.StateDB, + header *types.Header, + chainConfig *params.ChainConfig, + chainContext core.ChainContext, +) (uint64, error) { + initialGas := msg.Gas() + + // Create a new context to be used in the EVM environment + blockContext := core.NewEVMBlockContext(header, chainContext, &header.Coinbase) + + // Create a new environment which holds all relevant information + // about the transaction and calling mechanisms. + vmenv := vm.NewEVM(blockContext, vm.TxContext{}, state, chainConfig, vm.Config{}) + + // Apply the transaction to the current state (included in the env) + _, gasLeft, err := vmenv.Call( + vm.AccountRef(msg.From()), + *msg.To(), + msg.Data(), + msg.Gas(), + msg.Value(), + ) + // Update the state with pending changes + if err != nil { + state.Finalise(true) + } + + gasUsed := initialGas - gasLeft + + return gasUsed, nil +} diff --git a/consensus/bor/validators_getter.go b/consensus/bor/validators_getter.go new file mode 100644 index 0000000000..90d1fccf6e --- /dev/null +++ b/consensus/bor/validators_getter.go @@ -0,0 +1,11 @@ +package bor + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/bor/valset" +) + +//go:generate mockgen -destination=./validators_getter_mock.go -package=bor . ValidatorsGetter +type ValidatorsGetter interface { + GetCurrentValidators(headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) +} diff --git a/consensus/bor/validators_getter_mock.go b/consensus/bor/validators_getter_mock.go new file mode 100644 index 0000000000..ad99489d8e --- /dev/null +++ b/consensus/bor/validators_getter_mock.go @@ -0,0 +1,51 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: ValidatorsGetter) + +// Package bor is a generated GoMock package. +package bor + +import ( + reflect "reflect" + + common "github.com/ethereum/go-ethereum/common" + valset "github.com/ethereum/go-ethereum/consensus/bor/valset" + gomock "github.com/golang/mock/gomock" +) + +// MockValidatorsGetter is a mock of ValidatorsGetter interface. +type MockValidatorsGetter struct { + ctrl *gomock.Controller + recorder *MockValidatorsGetterMockRecorder +} + +// MockValidatorsGetterMockRecorder is the mock recorder for MockValidatorsGetter. +type MockValidatorsGetterMockRecorder struct { + mock *MockValidatorsGetter +} + +// NewMockValidatorsGetter creates a new mock instance. +func NewMockValidatorsGetter(ctrl *gomock.Controller) *MockValidatorsGetter { + mock := &MockValidatorsGetter{ctrl: ctrl} + mock.recorder = &MockValidatorsGetterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockValidatorsGetter) EXPECT() *MockValidatorsGetterMockRecorder { + return m.recorder +} + +// GetCurrentValidators mocks base method. +func (m *MockValidatorsGetter) GetCurrentValidators(arg0 common.Hash, arg1 uint64) ([]*valset.Validator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentValidators", arg0, arg1) + ret0, _ := ret[0].([]*valset.Validator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentValidators indicates an expected call of GetCurrentValidators. +func (mr *MockValidatorsGetterMockRecorder) GetCurrentValidators(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidators", reflect.TypeOf((*MockValidatorsGetter)(nil).GetCurrentValidators), arg0, arg1) +} diff --git a/consensus/bor/valset/error.go b/consensus/bor/valset/error.go new file mode 100644 index 0000000000..37add21683 --- /dev/null +++ b/consensus/bor/valset/error.go @@ -0,0 +1,32 @@ +package valset + +import "fmt" + +// TotalVotingPowerExceededError is returned when the maximum allowed total voting power is exceeded +type TotalVotingPowerExceededError struct { + Sum int64 + Validators []*Validator +} + +func (e *TotalVotingPowerExceededError) Error() string { + return fmt.Sprintf( + "Total voting power should be guarded to not exceed %v; got: %v; for validator set: %v", + MaxTotalVotingPower, + e.Sum, + e.Validators, + ) +} + +type InvalidStartEndBlockError struct { + Start uint64 + End uint64 + CurrentHeader uint64 +} + +func (e *InvalidStartEndBlockError) Error() string { + return fmt.Sprintf( + "Invalid parameters start: %d and end block: %d params", + e.Start, + e.End, + ) +} diff --git a/consensus/bor/validator.go b/consensus/bor/valset/validator.go similarity index 99% rename from consensus/bor/validator.go rename to consensus/bor/valset/validator.go index 57905fdf89..250206c1f3 100644 --- a/consensus/bor/validator.go +++ b/consensus/bor/valset/validator.go @@ -1,8 +1,7 @@ -package bor +package valset import ( "bytes" - // "encoding/json" "errors" "fmt" "math/big" diff --git a/consensus/bor/validator_set.go b/consensus/bor/valset/validator_set.go similarity index 99% rename from consensus/bor/validator_set.go rename to consensus/bor/valset/validator_set.go index ee14ef2cb1..19e6c681fe 100644 --- a/consensus/bor/validator_set.go +++ b/consensus/bor/valset/validator_set.go @@ -1,4 +1,4 @@ -package bor +package valset // Tendermint leader selection algorithm @@ -55,8 +55,8 @@ type ValidatorSet struct { // function panics. func NewValidatorSet(valz []*Validator) *ValidatorSet { vals := &ValidatorSet{} - err := vals.updateWithChangeSet(valz, false) + err := vals.updateWithChangeSet(valz, false) if err != nil { panic(fmt.Sprintf("cannot create validator set: %s", err)) } @@ -281,7 +281,7 @@ func (vals *ValidatorSet) Size() int { } // Force recalculation of the set's total voting power. -func (vals *ValidatorSet) updateTotalVotingPower() error { +func (vals *ValidatorSet) UpdateTotalVotingPower() error { sum := int64(0) for _, val := range vals.Validators { // mind overflow @@ -302,7 +302,7 @@ func (vals *ValidatorSet) TotalVotingPower() int64 { if vals.totalVotingPower == 0 { log.Info("invoking updateTotalVotingPower before returning it") - if err := vals.updateTotalVotingPower(); err != nil { + if err := vals.UpdateTotalVotingPower(); err != nil { // Can/should we do better? panic(err) } @@ -602,7 +602,7 @@ func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes vals.applyUpdates(updates) vals.applyRemovals(deletes) - if err := vals.updateTotalVotingPower(); err != nil { + if err := vals.UpdateTotalVotingPower(); err != nil { return err } diff --git a/consensus/merger.go b/consensus/merger.go index ffbcbf2b85..c435ecf91e 100644 --- a/consensus/merger.go +++ b/consensus/merger.go @@ -45,12 +45,14 @@ type Merger struct { // NewMerger creates a new Merger which stores its transition status in the provided db. func NewMerger(db ethdb.KeyValueStore) *Merger { var status transitionStatus + blob := rawdb.ReadTransitionStatus(db) if len(blob) != 0 { if err := rlp.DecodeBytes(blob, &status); err != nil { log.Crit("Failed to decode the transition status", "err", err) } } + return &Merger{ db: db, status: status, diff --git a/core/bench_test.go b/core/bench_test.go index 959979763d..ad6179d0a8 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -305,7 +305,8 @@ func benchReadChain(b *testing.B, full bool, count uint64) { } makeChainForBench(db, full, count) db.Close() - cacheConfig := *defaultCacheConfig + + cacheConfig := *DefaultCacheConfig cacheConfig.TrieDirtyDisabled = true b.ReportAllocs() diff --git a/core/blockchain.go b/core/blockchain.go index 1b11c781c5..8a4c581f66 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -27,6 +27,8 @@ import ( "sync/atomic" "time" + lru "github.com/hashicorp/golang-lru" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/prque" @@ -43,7 +45,6 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" - lru "github.com/hashicorp/golang-lru" ) var ( @@ -133,9 +134,9 @@ type CacheConfig struct { SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it } -// defaultCacheConfig are the default caching values if none are specified by the +// DefaultCacheConfig are the default caching values if none are specified by the // user (also used during testing). -var defaultCacheConfig = &CacheConfig{ +var DefaultCacheConfig = &CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, @@ -222,7 +223,7 @@ type BlockChain struct { // and Processor. func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64) (*BlockChain, error) { if cacheConfig == nil { - cacheConfig = defaultCacheConfig + cacheConfig = DefaultCacheConfig } bodyCache, _ := lru.New(bodyCacheLimit) bodyRLPCache, _ := lru.New(bodyCacheLimit) diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index b93444b8cd..f61f930496 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -397,10 +398,25 @@ func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscr return bc.scope.Track(bc.blockProcFeed.Subscribe(ch)) } +// Snaps retrieves the snapshot tree. +func (bc *BlockChain) Snaps() *snapshot.Tree { + return bc.snaps +} + +// DB retrieves the blockchain database. +func (bc *BlockChain) DB() ethdb.Database { + return bc.db +} + // // Bor related changes // +type BorStateSyncer interface { + SetStateSync(stateData []*types.StateSyncData) + SubscribeStateSyncEvent(ch chan<- StateSyncEvent) event.Subscription +} + // SetStateSync set sync data in state_data func (bc *BlockChain) SetStateSync(stateData []*types.StateSyncData) { bc.stateSyncData = stateData diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 37a1a42d0c..de97000918 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -920,7 +920,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { archiveDb, delfn := makeDb() defer delfn() - archiveCaching := *defaultCacheConfig + archiveCaching := *DefaultCacheConfig archiveCaching.TrieDirtyDisabled = true archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) diff --git a/core/chain_makers.go b/core/chain_makers.go index c7bf60a4b0..4b2d2082df 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" ) @@ -334,7 +335,10 @@ func makeBlockChain(parent *types.Block, n int, engine consensus.Engine, db ethd } type fakeChainReader struct { - config *params.ChainConfig + config *params.ChainConfig + stateSyncData []*types.StateSyncData + stateSyncFeed event.Feed + scope event.SubscriptionScope } // Config returns the chain configuration. @@ -348,3 +352,13 @@ func (cr *fakeChainReader) GetHeaderByHash(hash common.Hash) *types.Header func (cr *fakeChainReader) GetHeader(hash common.Hash, number uint64) *types.Header { return nil } func (cr *fakeChainReader) GetBlock(hash common.Hash, number uint64) *types.Block { return nil } func (cr *fakeChainReader) GetTd(hash common.Hash, number uint64) *big.Int { return nil } + +// SetStateSync set sync data in state_data +func (cr *fakeChainReader) SetStateSync(stateData []*types.StateSyncData) { + cr.stateSyncData = stateData +} + +// SubscribeStateSyncEvent registers a subscription of StateSyncEvent. +func (cr *fakeChainReader) SubscribeStateSyncEvent(ch chan<- StateSyncEvent) event.Subscription { + return cr.scope.Track(cr.stateSyncFeed.Subscribe(ch)) +} diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 7d6939e1dc..158e8c1eeb 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -21,6 +21,8 @@ import ( "math/big" "testing" + "golang.org/x/crypto/sha3" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" @@ -32,7 +34,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" - "golang.org/x/crypto/sha3" ) // TestStateProcessorErrors tests the output from the 'core' errors @@ -308,7 +309,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr header := &types.Header{ ParentHash: parent.Hash(), Coinbase: parent.Coinbase(), - Difficulty: engine.CalcDifficulty(&fakeChainReader{config}, parent.Time()+10, &types.Header{ + Difficulty: engine.CalcDifficulty(&fakeChainReader{config: config}, parent.Time()+10, &types.Header{ Number: parent.Number(), Time: parent.Time(), Difficulty: parent.Difficulty(), diff --git a/core/blockchain_repair_test.go b/core/tests/blockchain_repair_test.go similarity index 93% rename from core/blockchain_repair_test.go rename to core/tests/blockchain_repair_test.go index 9133671796..b52bf76fd9 100644 --- a/core/blockchain_repair_test.go +++ b/core/tests/blockchain_repair_test.go @@ -18,7 +18,7 @@ // the database in some strange state with gaps in the chain, nor with block data // dangling in the future. -package core +package tests import ( "io/ioutil" @@ -27,12 +27,22 @@ import ( "testing" "time" + "github.com/golang/mock/gomock" + + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/consensus/bor/api" + "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/tests/bor/mocks" ) // Tests a recovery for a short canonical chain where a recent block was already @@ -1750,7 +1760,17 @@ func testLongReorgedSnapSyncingDeepRepair(t *testing.T, snapshots bool) { }, snapshots) } +var ( + testKey1, _ = crypto.GenerateKey() + testAddress1 = crypto.PubkeyToAddress(testKey1.PublicKey) + + testKey2, _ = crypto.GenerateKey() + testAddress2 = crypto.PubkeyToAddress(testKey2.PublicKey) //nolint:unused,varcheck +) + func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { + t.Skip("need to add a proper signer for Bor consensus") + // It's hard to follow the test case, visualize the input //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) // fmt.Println(tt.dump(true)) @@ -1768,47 +1788,104 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { } defer db.Close() // Might double close, should be fine + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ethAPIMock := api.NewMockCaller(ctrl) + ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + + spanner := bor.NewMockSpanner(ctrl) + spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{ + { + ID: 0, + Address: common.Address{0x1}, + VotingPower: 100, + ProposerPriority: 0, + }, + }, nil).AnyTimes() + + heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl) + heimdallClientMock.EXPECT().Close().Times(1) + + contractMock := bor.NewMockGenesisContract(ctrl) + // Initialize a fresh chain var ( - genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) - engine = ethash.NewFullFaker() - config = &CacheConfig{ + gspec = &core.Genesis{ + Config: params.BorUnittestChainConfig, + BaseFee: big.NewInt(params.InitialBaseFee), + } + config = &core.CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, // Disable snapshot by default } ) + + engine := miner.NewFakeBor(t, db, params.BorUnittestChainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) defer engine.Close() + + engineBorInternal, ok := engine.(*bor.Bor) + if ok { + gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) + copy(gspec.ExtraData[32:32+common.AddressLength], testAddress1.Bytes()) + + engineBorInternal.Authorize(testAddress1, func(account accounts.Account, s string, data []byte) ([]byte, error) { + return crypto.Sign(crypto.Keccak256(data), testKey1) + }) + } + + genesis := gspec.MustCommit(db) + if snapshots { config.SnapshotLimit = 256 config.SnapshotWait = true } - chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + + chain, err := core.NewBlockChain(db, config, params.BorUnittestChainConfig, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } + // If sidechain blocks are needed, make a light chain and import it var sideblocks types.Blocks if tt.sidechainBlocks > 0 { - sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{0x01}) + sideblocks, _ = core.GenerateChain(params.BorUnittestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *core.BlockGen) { + b.SetCoinbase(testAddress1) + + if bor.IsSprintStart(b.Number().Uint64(), params.BorUnittestChainConfig.Bor.Sprint) { + b.SetExtra(gspec.ExtraData) + } else { + b.SetExtra(make([]byte, 32+crypto.SignatureLength)) + } }) if _, err := chain.InsertChain(sideblocks); err != nil { t.Fatalf("Failed to import side chain: %v", err) } } - canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { + + canonblocks, _ := core.GenerateChain(params.BorUnittestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *core.BlockGen) { b.SetCoinbase(common.Address{0x02}) b.SetDifficulty(big.NewInt(1000000)) + + if bor.IsSprintStart(b.Number().Uint64(), params.BorUnittestChainConfig.Bor.Sprint) { + b.SetExtra(gspec.ExtraData) + } else { + b.SetExtra(make([]byte, 32+crypto.SignatureLength)) + } }) if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } if tt.commitBlock > 0 { - chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + err = chain.StateCache().TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + if err != nil { + t.Fatal("on trieDB.Commit", err) + } + if snapshots { - if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { + if err := chain.Snaps().Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { t.Fatalf("Failed to flatten snapshots: %v", err) } } @@ -1837,7 +1914,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { } defer db.Close() - newChain, err := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + newChain, err := core.NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -1888,19 +1965,21 @@ func TestIssue23496(t *testing.T) { if err != nil { t.Fatalf("Failed to create temporary datadir: %v", err) } + os.RemoveAll(datadir) db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false) if err != nil { t.Fatalf("Failed to create persistent database: %v", err) } + defer db.Close() // Might double close, should be fine // Initialize a fresh chain var ( - genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) + genesis = (&core.Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) engine = ethash.NewFullFaker() - config = &CacheConfig{ + config = &core.CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, @@ -1908,11 +1987,13 @@ func TestIssue23496(t *testing.T) { SnapshotWait: true, } ) - chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + + chain, err := core.NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } - blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), 4, func(i int, b *BlockGen) { + + blocks, _ := core.GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), 4, func(i int, b *core.BlockGen) { b.SetCoinbase(common.Address{0x02}) b.SetDifficulty(big.NewInt(1000000)) }) @@ -1921,13 +2002,18 @@ func TestIssue23496(t *testing.T) { if _, err := chain.InsertChain(blocks[:1]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } - chain.stateCache.TrieDB().Commit(blocks[0].Root(), true, nil) + + err = chain.StateCache().TrieDB().Commit(blocks[0].Root(), true, nil) + if err != nil { + t.Fatal("on trieDB.Commit", err) + } // Insert block B2 and commit the snapshot into disk if _, err := chain.InsertChain(blocks[1:2]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } - if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil { + + if err := chain.Snaps().Cap(blocks[1].Root(), 0); err != nil { t.Fatalf("Failed to flatten snapshots: %v", err) } @@ -1935,7 +2021,11 @@ func TestIssue23496(t *testing.T) { if _, err := chain.InsertChain(blocks[2:3]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } - chain.stateCache.TrieDB().Commit(blocks[2].Root(), true, nil) + + err = chain.StateCache().TrieDB().Commit(blocks[2].Root(), true, nil) + if err != nil { + t.Fatal("on trieDB.Commit", err) + } // Insert the remaining blocks if _, err := chain.InsertChain(blocks[3:]); err != nil { @@ -1950,20 +2040,24 @@ func TestIssue23496(t *testing.T) { if err != nil { t.Fatalf("Failed to reopen persistent database: %v", err) } + defer db.Close() - chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + chain, err = core.NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } + defer chain.Stop() if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) } + if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) { t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) } + if head := chain.CurrentBlock(); head.NumberU64() != uint64(1) { t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(1)) } @@ -1972,15 +2066,19 @@ func TestIssue23496(t *testing.T) { if _, err := chain.InsertChain(blocks[1:]); err != nil { t.Fatalf("Failed to import canonical chain tail: %v", err) } + if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) } + if head := chain.CurrentFastBlock(); head.NumberU64() != uint64(4) { t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) } + if head := chain.CurrentBlock(); head.NumberU64() != uint64(4) { t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), uint64(4)) } + if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil { t.Error("Failed to regenerate the snapshot of known state") } diff --git a/core/blockchain_sethead_test.go b/core/tests/blockchain_sethead_test.go similarity index 98% rename from core/blockchain_sethead_test.go rename to core/tests/blockchain_sethead_test.go index b2b3a058a4..3a2d87c4eb 100644 --- a/core/blockchain_sethead_test.go +++ b/core/tests/blockchain_sethead_test.go @@ -17,7 +17,7 @@ // Tests that setting the chain head backwards doesn't leave the database in some // strange state with gaps in the chain, nor with block data dangling in the future. -package core +package tests import ( "fmt" @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -1959,79 +1960,98 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { if err != nil { t.Fatalf("Failed to create temporary datadir: %v", err) } + os.RemoveAll(datadir) db, err := rawdb.NewLevelDBDatabaseWithFreezer(datadir, 0, 0, datadir, "", false) if err != nil { t.Fatalf("Failed to create persistent database: %v", err) } + defer db.Close() // Initialize a fresh chain var ( - genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) + genesis = (&core.Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) engine = ethash.NewFullFaker() - config = &CacheConfig{ + config = &core.CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, // Disable snapshot } ) + if snapshots { config.SnapshotLimit = 256 config.SnapshotWait = true } - chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + + chain, err := core.NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } + // If sidechain blocks are needed, make a light chain and import it var sideblocks types.Blocks if tt.sidechainBlocks > 0 { - sideblocks, _ = GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { + sideblocks, _ = core.GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *core.BlockGen) { b.SetCoinbase(common.Address{0x01}) }) + if _, err := chain.InsertChain(sideblocks); err != nil { t.Fatalf("Failed to import side chain: %v", err) } } - canonblocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { + + canonblocks, _ := core.GenerateChain(params.TestChainConfig, genesis, engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *core.BlockGen) { b.SetCoinbase(common.Address{0x02}) b.SetDifficulty(big.NewInt(1000000)) }) + if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } + if tt.commitBlock > 0 { - chain.stateCache.TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + err = chain.StateCache().TrieDB().Commit(canonblocks[tt.commitBlock-1].Root(), true, nil) + if err != nil { + t.Fatal("on trieDB.Commit", err) + } + if snapshots { - if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { + if err := chain.Snaps().Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { t.Fatalf("Failed to flatten snapshots: %v", err) } } } + if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { t.Fatalf("Failed to import canonical chain tail: %v", err) } + // Manually dereference anything not committed to not have to work with 128+ tries for _, block := range sideblocks { - chain.stateCache.TrieDB().Dereference(block.Root()) + chain.StateCache().TrieDB().Dereference(block.Root()) } + for _, block := range canonblocks { - chain.stateCache.TrieDB().Dereference(block.Root()) + chain.StateCache().TrieDB().Dereference(block.Root()) } + // Force run a freeze cycle type freezer interface { Freeze(threshold uint64) error Ancients() (uint64, error) } + db.(freezer).Freeze(tt.freezeThreshold) // Set the simulated pivot block if tt.pivotBlock != nil { rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) } + // Set the head of the chain back to the requested number chain.SetHead(tt.setheadBlock) @@ -2044,12 +2064,15 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) } + if head := chain.CurrentFastBlock(); head.NumberU64() != tt.expHeadFastBlock { t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadFastBlock) } + if head := chain.CurrentBlock(); head.NumberU64() != tt.expHeadBlock { t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), tt.expHeadBlock) } + if frozen, err := db.(freezer).Ancients(); err != nil { t.Errorf("Failed to retrieve ancient count: %v\n", err) } else if int(frozen) != tt.expFrozen { @@ -2059,7 +2082,8 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { // verifyNoGaps checks that there are no gaps after the initial set of blocks in // the database and errors if found. -func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks) { +//nolint:gocognit +func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks) { t.Helper() var end uint64 @@ -2111,7 +2135,8 @@ func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted type // verifyCutoff checks that there are no chain data available in the chain after // the specified limit, but that it is available before. -func verifyCutoff(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks, head int) { +//nolint:gocognit +func verifyCutoff(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks, head int) { t.Helper() for i := 1; i <= len(inserted); i++ { diff --git a/core/blockchain_snapshot_test.go b/core/tests/blockchain_snapshot_test.go similarity index 87% rename from core/blockchain_snapshot_test.go rename to core/tests/blockchain_snapshot_test.go index a8044ecb4d..fb4c09867c 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/tests/blockchain_snapshot_test.go @@ -17,7 +17,7 @@ // Tests that abnormal program termination (i.e.crash) and restart can recovery // the snapshot properly if the snapshot is enabled. -package core +package tests import ( "bytes" @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -57,7 +58,9 @@ type snapshotTestBasic struct { engine consensus.Engine } -func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Block) { +func (basic *snapshotTestBasic) prepare(t *testing.T) (*core.BlockChain, []*types.Block) { + t.Helper() + // Create a temporary persistent database datadir, err := ioutil.TempDir("", "") if err != nil { @@ -71,20 +74,22 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo } // Initialize a fresh chain var ( - genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) + genesis = (&core.Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) engine = ethash.NewFullFaker() gendb = rawdb.NewMemoryDatabase() // Snapshot is enabled, the first snapshot is created from the Genesis. // The snapshot memory allowance is 256MB, it means no snapshot flush // will happen during the block insertion. - cacheConfig = defaultCacheConfig + cacheConfig = core.DefaultCacheConfig ) - chain, err := NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) + + chain, err := core.NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to create chain: %v", err) } - blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, gendb, basic.chainBlocks, func(i int, b *BlockGen) {}) + + blocks, _ := core.GenerateChain(params.TestChainConfig, genesis, engine, gendb, basic.chainBlocks, func(i int, b *core.BlockGen) {}) // Insert the blocks with configured settings. var breakpoints []uint64 @@ -93,27 +98,39 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo } else { breakpoints = append(breakpoints, basic.commitBlock, basic.snapshotBlock) } + var startPoint uint64 + for _, point := range breakpoints { if _, err := chain.InsertChain(blocks[startPoint:point]); err != nil { t.Fatalf("Failed to import canonical chain start: %v", err) } + startPoint = point if basic.commitBlock > 0 && basic.commitBlock == point { - chain.stateCache.TrieDB().Commit(blocks[point-1].Root(), true, nil) + err = chain.StateCache().TrieDB().Commit(blocks[point-1].Root(), true, nil) + if err != nil { + t.Fatal("on trieDB.Commit", err) + } } + if basic.snapshotBlock > 0 && basic.snapshotBlock == point { // Flushing the entire snap tree into the disk, the // relevant (a) snapshot root and (b) snapshot generator // will be persisted atomically. - chain.snaps.Cap(blocks[point-1].Root(), 0) - diskRoot, blockRoot := chain.snaps.DiskRoot(), blocks[point-1].Root() + err = chain.Snaps().Cap(blocks[point-1].Root(), 0) + if err != nil { + t.Fatal("on Snaps.Cap", err) + } + + diskRoot, blockRoot := chain.Snaps().DiskRoot(), blocks[point-1].Root() if !bytes.Equal(diskRoot.Bytes(), blockRoot.Bytes()) { t.Fatalf("Failed to flush disk layer change, want %x, got %x", blockRoot, diskRoot) } } } + if _, err := chain.InsertChain(blocks[startPoint:]); err != nil { t.Fatalf("Failed to import canonical chain tail: %v", err) } @@ -123,10 +140,13 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo basic.db = db basic.gendb = gendb basic.engine = engine + return chain, blocks } -func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks []*types.Block) { +func (basic *snapshotTestBasic) verify(t *testing.T, chain *core.BlockChain, blocks []*types.Block) { + t.Helper() + // Iterate over all the remaining blocks and ensure there are no gaps verifyNoGaps(t, chain, true, blocks) verifyCutoff(t, chain, true, blocks, basic.expCanonicalBlocks) @@ -134,9 +154,11 @@ func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks [ if head := chain.CurrentHeader(); head.Number.Uint64() != basic.expHeadHeader { t.Errorf("Head header mismatch: have %d, want %d", head.Number, basic.expHeadHeader) } + if head := chain.CurrentFastBlock(); head.NumberU64() != basic.expHeadFastBlock { t.Errorf("Head fast block mismatch: have %d, want %d", head.NumberU64(), basic.expHeadFastBlock) } + if head := chain.CurrentBlock(); head.NumberU64() != basic.expHeadBlock { t.Errorf("Head block mismatch: have %d, want %d", head.NumberU64(), basic.expHeadBlock) } @@ -145,12 +167,12 @@ func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks [ block := chain.GetBlockByNumber(basic.expSnapshotBottom) if block == nil { t.Errorf("The correspnding block[%d] of snapshot disk layer is missing", basic.expSnapshotBottom) - } else if !bytes.Equal(chain.snaps.DiskRoot().Bytes(), block.Root().Bytes()) { - t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.snaps.DiskRoot()) + } else if !bytes.Equal(chain.Snaps().DiskRoot().Bytes(), block.Root().Bytes()) { + t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.Snaps().DiskRoot()) } // Check the snapshot, ensure it's integrated - if err := chain.snaps.Verify(block.Root()); err != nil { + if err := chain.Snaps().Verify(block.Root()); err != nil { t.Errorf("The disk layer is not integrated %v", err) } } @@ -223,10 +245,12 @@ func (snaptest *snapshotTest) test(t *testing.T) { // Restart the chain normally chain.Stop() - newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + + newchain, err := core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } + defer newchain.Stop() snaptest.verify(t, newchain, blocks) @@ -245,7 +269,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) { chain, blocks := snaptest.prepare(t) // Pull the plug on the database, simulating a hard crash - db := chain.db + db := chain.DB() db.Close() // Start a new blockchain back up and see where the repair leads us @@ -259,13 +283,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) { // the crash, we do restart twice here: one after the crash and one // after the normal stop. It's used to ensure the broken snapshot // can be detected all the time. - newchain, err := NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + newchain, err := core.NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } newchain.Stop() - newchain, err = NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + newchain, err = core.NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -292,27 +316,31 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) { // Insert blocks without enabling snapshot if gapping is required. chain.Stop() - gappedBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.gapped, func(i int, b *BlockGen) {}) + + gappedBlocks, _ := core.GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.gapped, func(i int, b *core.BlockGen) {}) // Insert a few more blocks without enabling snapshot - var cacheConfig = &CacheConfig{ + var cacheConfig = &core.CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, } - newchain, err := NewBlockChain(snaptest.db, cacheConfig, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + + newchain, err := core.NewBlockChain(snaptest.db, cacheConfig, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } + newchain.InsertChain(gappedBlocks) newchain.Stop() // Restart the chain with enabling the snapshot - newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + newchain, err = core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } + defer newchain.Stop() snaptest.verify(t, newchain, blocks) @@ -337,7 +365,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) { chain.SetHead(snaptest.setHead) chain.Stop() - newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + newchain, err := core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -368,11 +396,12 @@ func (snaptest *restartCrashSnapshotTest) test(t *testing.T) { // and state committed. chain.Stop() - newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + newchain, err := core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } - newBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.newBlocks, func(i int, b *BlockGen) {}) + + newBlocks, _ := core.GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.newBlocks, func(i int, b *core.BlockGen) {}) newchain.InsertChain(newBlocks) // Commit the entire snapshot into the disk if requested. Note only @@ -385,7 +414,7 @@ func (snaptest *restartCrashSnapshotTest) test(t *testing.T) { // journal and latest state will be committed // Restart the chain after the crash - newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + newchain, err = core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -414,38 +443,42 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) { // and state committed. chain.Stop() - config := &CacheConfig{ + config := &core.CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, } - newchain, err := NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + + newchain, err := core.NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } - newBlocks, _ := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.newBlocks, func(i int, b *BlockGen) {}) + + newBlocks, _ := core.GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.gendb, snaptest.newBlocks, func(i int, b *core.BlockGen) {}) newchain.InsertChain(newBlocks) newchain.Stop() // Restart the chain, the wiper should starts working - config = &CacheConfig{ + config = &core.CacheConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 256, SnapshotWait: false, // Don't wait rebuild } - newchain, err = NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + + _, err = core.NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } // Simulate the blockchain crash. - newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) + newchain, err = core.NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } + snaptest.verify(t, newchain, blocks) } diff --git a/eth/backend.go b/eth/backend.go index f40e011f8d..03419cde45 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -183,7 +183,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { // END: Bor changes bcVersion := rawdb.ReadDatabaseVersion(chainDb) - var dbVer = "" + dbVer := "" if bcVersion != nil { dbVer = fmt.Sprintf("%d", *bcVersion) } @@ -471,8 +471,10 @@ func (s *Ethereum) StartMining(threads int) error { if threads == 0 { threads = -1 // Disable the miner from within } + th.SetThreads(threads) } + // If the miner was not running, initialize it if !s.IsMining() { // Propagate the initial price point to the transaction pool @@ -485,6 +487,7 @@ func (s *Ethereum) StartMining(threads int) error { eb, err := s.Etherbase() if err != nil { log.Error("Cannot start mining without etherbase", "err", err) + return fmt.Errorf("etherbase missing: %v", err) } @@ -499,20 +502,26 @@ func (s *Ethereum) StartMining(threads int) error { cli = c } } + if cli != nil { wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) if wallet == nil || err != nil { log.Error("Etherbase account unavailable locally", "err", err) + return fmt.Errorf("signer missing: %v", err) } + cli.Authorize(eb, wallet.SignData) } + if bor, ok := s.engine.(*bor.Bor); ok { wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) if wallet == nil || err != nil { log.Error("Etherbase account unavailable locally", "err", err) + return fmt.Errorf("signer missing: %v", err) } + bor.Authorize(eb, wallet.SignData) } } @@ -522,6 +531,7 @@ func (s *Ethereum) StartMining(threads int) error { go s.miner.Start(eb) } + return nil } @@ -575,6 +585,7 @@ func (s *Ethereum) Protocols() []p2p.Protocol { if s.config.SnapshotCache > 0 { protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...) } + return protos } @@ -599,6 +610,7 @@ func (s *Ethereum) Start() error { } // Start the networking layer and the light server if requested s.handler.Start(maxPeers) + return nil } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 6ab43891f7..904fb2cbc2 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -29,6 +29,9 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/consensus/bor/contract" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" @@ -237,7 +240,10 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, et // In order to pass the ethereum transaction tests, we need to set the burn contract which is in the bor config // Then, bor != nil will also be enabled for ethash and clique. Only enable Bor for real if there is a validator contract present. if chainConfig.Bor != nil && chainConfig.Bor.ValidatorContract != "" { - return bor.New(chainConfig, db, blockchainAPI, ethConfig.HeimdallURL, ethConfig.WithoutHeimdall) + genesisContractsClient := contract.NewGenesisContractsClient(chainConfig, chainConfig.Bor.ValidatorContract, chainConfig.Bor.StateReceiverContract, blockchainAPI) + spanner := span.NewChainSpanner(blockchainAPI, contract.ValidatorSet(), chainConfig, common.HexToAddress(chainConfig.Bor.ValidatorContract)) + + return bor.New(chainConfig, db, blockchainAPI, spanner, heimdall.NewHeimdallClient(ethConfig.HeimdallURL), genesisContractsClient) } else { switch config.PowMode { case ethash.ModeFake: diff --git a/eth/tracers/api_bor.go b/eth/tracers/api_bor.go index 7f5e2c34d6..6ab1a4290a 100644 --- a/eth/tracers/api_bor.go +++ b/eth/tracers/api_bor.go @@ -47,16 +47,19 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T if err != nil { return nil, err } + res.Block = blockFields parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) if err != nil { return nil, err } + reexec := defaultTraceReexec if config != nil && config.Reexec != nil { reexec = *config.Reexec } + // TODO: discuss consequences of setting preferDisk false. statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) if err != nil { @@ -96,6 +99,7 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T if len(execRes.Revert()) > 0 { returnVal = fmt.Sprintf("%x", execRes.Revert()) } + result := ðapi.ExecutionResult{ Gas: execRes.UsedGas, Failed: execRes.Failed(), @@ -106,12 +110,14 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T Result: result, IntermediateHash: statedb.IntermediateRoot(deleteEmptyObjects), } + return res } for indx, tx := range txs { res.Transactions = append(res.Transactions, traceTxn(indx, tx)) } + return res, nil } @@ -139,5 +145,6 @@ func (api *API) TraceBorBlock(req *TraceBlockRequest) (*BlockTraceResult, error) if err != nil { return nil, err } + return api.traceBorBlock(ctx, block, req.Config) } diff --git a/go.mod b/go.mod index 5e3a8b81e9..852c895e3b 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,9 @@ module github.com/ethereum/go-ethereum -go 1.16 +go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 github.com/aws/aws-sdk-go-v2 v1.2.0 github.com/aws/aws-sdk-go-v2/config v1.1.1 @@ -16,20 +15,15 @@ require ( github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 - github.com/deepmap/oapi-codegen v1.8.2 // indirect github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48 github.com/edsrzf/mmap-go v1.0.0 github.com/fatih/color v1.7.0 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff - github.com/go-critic/go-critic v0.6.3 // indirect - github.com/go-kit/kit v0.9.0 // indirect - github.com/go-logfmt/logfmt v0.5.0 // indirect - github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-stack/stack v1.8.0 - github.com/go-toolsmith/astcopy v1.0.1 // indirect github.com/golang-jwt/jwt/v4 v4.3.0 + github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 github.com/golang/snappy v0.0.4 github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa @@ -45,25 +39,19 @@ require ( github.com/imdario/mergo v0.3.11 github.com/influxdata/influxdb v1.8.3 github.com/influxdata/influxdb-client-go/v2 v2.4.0 - github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect github.com/jackpal/go-nat-pmp v1.0.2 github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e github.com/julienschmidt/httprouter v1.3.0 github.com/karalabe/usb v0.0.2 - github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.8 github.com/mattn/go-isatty v0.0.12 github.com/mitchellh/cli v1.1.2 github.com/mitchellh/go-grpc-net-conn v0.0.0-20200427190222-eb030e4876f0 github.com/mitchellh/go-homedir v1.1.0 - github.com/naoina/go-stringutil v0.1.0 // indirect github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 - github.com/polyfloyd/go-errorlint v0.0.0-20220510153142-36539f2bdac3 // indirect github.com/prometheus/tsdb v0.7.1 - github.com/quasilyte/gogrep v0.0.0-20220429205452-5e2753ee08f9 // indirect - github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 github.com/ryanuber/columnize v2.1.2+incompatible @@ -71,24 +59,81 @@ require ( github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef github.com/xsleonard/go-merkle v1.1.0 go.opentelemetry.io/otel v1.2.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0 go.opentelemetry.io/otel/sdk v1.2.0 - go.uber.org/goleak v1.1.12 // indirect + go.uber.org/goleak v1.1.12 golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 golang.org/x/text v0.3.7 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba golang.org/x/tools v0.1.10 - golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect google.golang.org/grpc v1.42.0 google.golang.org/protobuf v1.27.1 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 gopkg.in/urfave/cli.v1 v1.20.0 + pgregory.net/rapid v0.4.7 +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect + github.com/Masterminds/goutils v1.1.0 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/Masterminds/sprig v2.22.0+incompatible // indirect + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // 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-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/bgentry/speakeasy v0.1.0 // indirect + github.com/cenkalti/backoff/v4 v4.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/deepmap/oapi-codegen v1.8.2 // indirect + github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect + github.com/go-kit/kit v0.9.0 // indirect + github.com/go-logfmt/logfmt v0.5.0 // indirect + github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/google/go-cmp v0.5.8 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-multierror v1.0.0 // indirect + github.com/huandu/xstrings v1.3.2 // indirect + github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mitchellh/copystructure v1.0.0 // indirect + github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.0 // indirect + github.com/naoina/go-stringutil v0.1.0 // indirect + github.com/opentracing/opentracing-go v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/posener/complete v1.1.1 // indirect + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect + github.com/zclconf/go-cty v1.8.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 // indirect + go.opentelemetry.io/otel/trace v1.2.0 // indirect + go.opentelemetry.io/proto/otlp v0.10.0 // indirect + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect + golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect + google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gotest.tools v2.2.0+incompatible // indirect ) diff --git a/go.sum b/go.sum index b5278c5112..374ab3066e 100644 --- a/go.sum +++ b/go.sum @@ -49,7 +49,6 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= -github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= @@ -82,14 +81,12 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2 github.com/btcsuite/btcd/btcec/v2 v2.1.2 h1:YoYoC9J0jwfukodSBMzZYUVQ8PTiYg4BnOWiJVzTmLs= github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -162,8 +159,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= -github.com/go-critic/go-critic v0.6.3 h1:abibh5XYBTASawfTQ0rA7dVtQT+6KzpGqb/J+DxRDaw= -github.com/go-critic/go-critic v0.6.3/go.mod h1:c6b3ZP1MQ7o6lPR7Rv3lEf7pYQUmAcx8ABHgdZCQt/k= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -184,25 +179,6 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= -github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= -github.com/go-toolsmith/astcopy v1.0.1 h1:l09oBhAPyV74kLJ3ZO31iBU8htZGTwr9LTjuMCyL8go= -github.com/go-toolsmith/astcopy v1.0.1/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= -github.com/go-toolsmith/astequal v1.0.2 h1:+XvaV8zNxua+9+Oa4AHmgmpo4RYAbwr/qjNppLfX2yM= -github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= -github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= -github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= -github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= -github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= -github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= -github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -216,6 +192,8 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +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.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -247,10 +225,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -429,8 +405,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE 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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v0.0.0-20220510153142-36539f2bdac3 h1:GhmKVnwiethXkJVYqq/kdcw3+u2TIuhPwmHhB+ehpIQ= -github.com/polyfloyd/go-errorlint v0.0.0-20220510153142-36539f2bdac3/go.mod h1:KZy4xxPJyy88/gldCe5OdW6OQRtNO3EZE7hXzmnebgA= github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -445,21 +419,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.16-0.20220213074421-6aa060fab41a h1:sWFavxtIctGrVs5SYZ5Ml1CvrDAs8Kf5kx2PI3C41dA= -github.com/quasilyte/go-ruleguard v0.3.16-0.20220213074421-6aa060fab41a/go.mod h1:VMX+OnnSw4LicdiEGtRSD/1X8kW7GuEscjYNr4cOIT4= -github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.16/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= -github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= -github.com/quasilyte/gogrep v0.0.0-20220429205452-5e2753ee08f9 h1:mEQjyqtrQ6eB7oW9Qm+5po33faQIbhWp3qfhxGYuHKc= -github.com/quasilyte/gogrep v0.0.0-20220429205452-5e2753ee08f9/go.mod h1:MsVMK2P94jAne/7vEaLCRmjmOL0aTGAkvVOVuT+UYww= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= -github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= -github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= @@ -488,7 +447,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -518,10 +476,8 @@ github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xsleonard/go-merkle v1.1.0 h1:fHe1fuhJjGH22ZzVTAH0jqHLhTGhOq3wQjJN+8P0jQg= github.com/xsleonard/go-merkle v1.1.0/go.mod h1:cW4z+UZ/4f2n9IJgIiyDCdYguchoDyDAPmpuOWGxdGg= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= @@ -557,9 +513,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/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-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8= golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -571,10 +525,7 @@ golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxT golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299 h1:zQpM52jfKHG6II1ISZY1ZcpygvuSFZpLwfluuF89XOg= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171 h1:DZhP7zSquENyG3Yb6ZpGqNEtgE8dfXhcLcheIF9RQHY= -golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -585,6 +536,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -592,9 +544,7 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= 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.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -615,7 +565,6 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -625,10 +574,7 @@ golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -642,7 +588,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -686,12 +631,6 @@ 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-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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/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-20211216021012-1d35b9e2eb4e/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-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -737,18 +676,14 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= 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.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -847,5 +782,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= +pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/internal/cli/flagset/flagset.go b/internal/cli/flagset/flagset.go index e04f452c1e..b57fff9996 100644 --- a/internal/cli/flagset/flagset.go +++ b/internal/cli/flagset/flagset.go @@ -19,6 +19,7 @@ func NewFlagSet(name string) *Flagset { flags: []*FlagVar{}, set: flag.NewFlagSet(name, flag.ContinueOnError), } + return f } @@ -34,10 +35,12 @@ func (f *Flagset) addFlag(fl *FlagVar) { func (f *Flagset) Help() string { str := "Options:\n\n" + items := []string{} for _, item := range f.flags { items = append(items, fmt.Sprintf(" -%s\n %s", item.Name, item.Usage)) } + return str + strings.Join(items, "\n\n") } @@ -53,25 +56,30 @@ func (f *Flagset) MarkDown() string { groups[item.Group] = append(groups[item.Group], item) } - keys := make([]string, len(groups)) i := 0 + keys := make([]string, len(groups)) + for k := range groups { keys[i] = k i++ } + sort.Strings(keys) items := []string{} + for _, k := range keys { if k == "" { - items = append(items, fmt.Sprintf("## Options")) + items = append(items, "## Options") } else { items = append(items, fmt.Sprintf("### %s Options", k)) } + for _, item := range groups[k] { items = append(items, fmt.Sprintf("- ```%s```: %s", item.Name, item.Usage)) } } + return strings.Join(items, "\n\n") } @@ -162,6 +170,7 @@ func (b *BigIntFlag) String() string { if b.Value == nil { return "" } + return b.Value.String() } @@ -174,10 +183,12 @@ func (b *BigIntFlag) Set(value string) error { } else { num, ok = num.SetString(value, 10) } + if !ok { return fmt.Errorf("failed to set big int") } b.Value = num + return nil } @@ -201,11 +212,13 @@ func (i *SliceStringFlag) String() string { if i.Value == nil { return "" } + return strings.Join(*i.Value, ",") } func (i *SliceStringFlag) Set(value string) error { *i.Value = append(*i.Value, strings.Split(value, ",")...) + return nil } @@ -246,10 +259,12 @@ func (m *MapStringFlag) String() string { if m.Value == nil { return "" } + ls := []string{} for k, v := range *m.Value { ls = append(ls, k+"="+v) } + return strings.Join(ls, ",") } @@ -257,6 +272,7 @@ func (m *MapStringFlag) Set(value string) error { if m.Value == nil { m.Value = &map[string]string{} } + for _, t := range strings.Split(value, ",") { if t != "" { kv := strings.Split(t, "=") @@ -266,6 +282,7 @@ func (m *MapStringFlag) Set(value string) error { } } } + return nil } diff --git a/internal/cli/server/chains/chain.go b/internal/cli/server/chains/chain.go index 32f5159b38..d6717f5893 100644 --- a/internal/cli/server/chains/chain.go +++ b/internal/cli/server/chains/chain.go @@ -26,18 +26,23 @@ var chains = map[string]*Chain{ } func GetChain(name string) (*Chain, error) { - var chain *Chain - var err error + var ( + chain *Chain + err error + ) + if _, fileErr := os.Stat(name); fileErr == nil { if chain, err = ImportFromFile(name); err != nil { return nil, fmt.Errorf("error importing chain from file: %v", err) } + return chain, nil } else if errors.Is(fileErr, os.ErrNotExist) { var ok bool if chain, ok = chains[name]; !ok { return nil, fmt.Errorf("chain %s not found", name) } + return chain, nil } else { return nil, fileErr @@ -62,10 +67,12 @@ func importChain(content []byte) (*Chain, error) { if chain.Genesis == nil { log.Info("Try reading as legacy genesis") + var genesis core.Genesis if err := json.Unmarshal(content, &genesis); err != nil { return nil, err } + if genesis.Config != nil { chain.Genesis = &genesis chain.NetworkId = genesis.Config.ChainID.Uint64() diff --git a/internal/cli/server/chains/chain_test.go b/internal/cli/server/chains/chain_test.go index 8f57b7d220..b372a3c4b9 100644 --- a/internal/cli/server/chains/chain_test.go +++ b/internal/cli/server/chains/chain_test.go @@ -5,9 +5,12 @@ import ( ) func TestChain_ImportFromFile(t *testing.T) { + t.Parallel() + type args struct { filename string } + tests := []struct { name string args args @@ -34,8 +37,13 @@ func TestChain_ImportFromFile(t *testing.T) { wantErr: true, }, } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + _, err := ImportFromFile(tt.args.filename) if (err != nil) != tt.wantErr { t.Errorf("ImportFromFile() error = %v, wantErr %v", err, tt.wantErr) diff --git a/internal/cli/server/command.go b/internal/cli/server/command.go index 01ce44f5ee..a0b8a6d87c 100644 --- a/internal/cli/server/command.go +++ b/internal/cli/server/command.go @@ -33,6 +33,7 @@ func (c *Command) MarkDown() string { "The ```bor server``` command runs the Bor client.", c.Flags().MarkDown(), } + return strings.Join(items, "\n\n") } diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 4c17a58fc8..137f6aed0f 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -58,7 +58,7 @@ type Config struct { // GcMode selects the garbage collection mode for the trie GcMode string `hcl:"gc-mode,optional"` - // NoSnapshot disbales the snapshot database mode + // NoSnapshot disables the snapshot database mode NoSnapshot bool `hcl:"no-snapshot,optional"` // Ethstats is the address of the ethstats server to send telemetry @@ -527,18 +527,22 @@ func (c *Config) fillBigInt() error { b := new(big.Int) var ok bool + if strings.HasPrefix(*x.str, "0x") { b, ok = b.SetString((*x.str)[2:], 16) } else { b, ok = b.SetString(*x.str, 10) } + if !ok { return fmt.Errorf("%s can't parse big int %s", x.path, *x.str) } + *x.str = "" *x.td = b } } + return nil } @@ -559,10 +563,12 @@ func (c *Config) fillTimeDurations() error { if err != nil { return fmt.Errorf("%s can't parse time duration %s", x.path, *x.str) } + *x.str = "" *x.td = d } } + return nil } @@ -574,6 +580,7 @@ func readConfigFile(path string) (*Config, error) { if err != nil { return nil, err } + return readLegacyConfig(data) } @@ -582,15 +589,19 @@ func readConfigFile(path string) (*Config, error) { Cache: &CacheConfig{}, Sealer: &SealerConfig{}, } + if err := hclsimple.DecodeFile(path, nil, config); err != nil { return nil, fmt.Errorf("failed to decode config file '%s': %v", path, err) } + if err := config.fillBigInt(); err != nil { return nil, err } + if err := config.fillTimeDurations(); err != nil { return nil, err } + return config, nil } @@ -599,6 +610,7 @@ func (c *Config) loadChain() error { if err != nil { return err } + c.chain = chain // preload some default values that depend on the chain file @@ -612,14 +624,17 @@ func (c *Config) loadChain() error { } else { c.Cache.Cache = 1024 } + return nil } +//nolint:gocognit func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (*ethconfig.Config, error) { dbHandles, err := makeDatabaseHandles() if err != nil { return nil, err } + n := ethconfig.Defaults // only update for non-developer mode as we don't yet @@ -663,6 +678,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* if !common.IsHexAddress(etherbase) { return nil, fmt.Errorf("etherbase is not an address: %s", etherbase) } + n.Miner.Etherbase = common.HexToAddress(etherbase) } } @@ -672,17 +688,24 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() { return nil, fmt.Errorf("account unlock with HTTP access is forbidden") } + ks := accountManager.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + passwords, err := MakePasswordListFromFile(c.Accounts.PasswordFile) if err != nil { return nil, err } + if len(passwords) < len(c.Accounts.Unlock) { return nil, fmt.Errorf("number of passwords provided (%v) is less than number of accounts (%v) to unlock", len(passwords), len(c.Accounts.Unlock)) } + for i, account := range c.Accounts.Unlock { - ks.Unlock(accounts.Account{Address: common.HexToAddress(account)}, passwords[i]) + err = ks.Unlock(accounts.Account{Address: common.HexToAddress(account)}, passwords[i]) + if err != nil { + return nil, fmt.Errorf("could not unlock an account %q", account) + } } } @@ -700,6 +723,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* passphrase string err error ) + // etherbase has been set above, configuring the miner address from command line flags. if n.Miner.Etherbase != (common.Address{}) { developer = accounts.Account{Address: n.Miner.Etherbase} @@ -714,6 +738,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* if err := ks.Unlock(developer, passphrase); err != nil { return nil, fmt.Errorf("failed to unlock developer account: %v", err) } + log.Info("Using developer account", "address", developer.Address) // Set the Etherbase @@ -753,10 +778,12 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* if err != nil { return nil, fmt.Errorf("invalid required block number %s: %v", k, err) } + var hash common.Hash if err = hash.UnmarshalText([]byte(v)); err != nil { return nil, fmt.Errorf("invalid required block hash %s: %v", v, err) } + n.PeerRequiredBlocks[number] = hash } } @@ -775,6 +802,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024) mem.Total = 2 * 1024 * 1024 * 1024 } + allowance := uint64(mem.Total / 1024 / 1024 / 3) if cache > allowance { log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) @@ -804,6 +832,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* } else { log.Info("Global gas cap disabled") } + n.RPCTxFeeCap = c.JsonRPC.TxFeeCap // sync mode. It can either be "fast", "full" or "snap". We disable @@ -843,6 +872,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* } n.DatabaseHandles = dbHandles + return &n, nil } @@ -906,6 +936,7 @@ func (c *Config) buildNode() (*node.Config, error) { cfg.HTTPHost = c.JsonRPC.Http.Host cfg.HTTPPort = int(c.JsonRPC.Http.Port) } + if c.JsonRPC.Ws.Enabled { cfg.WSHost = c.JsonRPC.Ws.Host cfg.WSPort = int(c.JsonRPC.Ws.Port) @@ -916,6 +947,7 @@ func (c *Config) buildNode() (*node.Config, error) { if err != nil { return nil, fmt.Errorf("wrong 'nat' flag: %v", err) } + cfg.P2P.NAT = natif // only check for non-developer modes @@ -926,21 +958,27 @@ func (c *Config) buildNode() (*node.Config, error) { if len(bootnodes) == 0 { bootnodes = c.chain.Bootnodes } + if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil { return nil, err } + if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil { return nil, err } + if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil { return nil, err } + if len(cfg.P2P.StaticNodes) == 0 { cfg.P2P.StaticNodes = cfg.StaticNodes() } + if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil { return nil, err } + if len(cfg.P2P.TrustedNodes) == 0 { cfg.P2P.TrustedNodes = cfg.TrustedNodes() } @@ -951,6 +989,7 @@ func (c *Config) buildNode() (*node.Config, error) { cfg.P2P.MaxPeers = 0 cfg.P2P.NoDiscovery = true } + return cfg, nil } @@ -960,6 +999,7 @@ func (c *Config) Merge(cc ...*Config) error { return fmt.Errorf("failed to merge configurations: %v", err) } } + return nil } @@ -968,10 +1008,12 @@ func makeDatabaseHandles() (int, error) { if err != nil { return -1, err } + raised, err := fdlimit.Raise(uint64(limit)) if err != nil { return -1, err } + return int(raised / 2), nil } @@ -986,6 +1028,7 @@ func parseBootnodes(urls []string) ([]*enode.Node, error) { dst = append(dst, node) } } + return dst, nil } @@ -996,6 +1039,7 @@ func defaultDataDir() string { // we cannot guess a stable location return "" } + switch runtime.GOOS { case "darwin": return filepath.Join(home, "Library", "Bor") @@ -1005,6 +1049,7 @@ func defaultDataDir() string { // Windows XP and below don't have LocalAppData. panic("environment variable LocalAppData is undefined") } + return filepath.Join(appdata, "Bor") default: return filepath.Join(home, ".bor") @@ -1016,6 +1061,7 @@ func Hostname() string { if err != nil { return "bor" } + return hostname } @@ -1024,10 +1070,13 @@ func MakePasswordListFromFile(path string) ([]string, error) { if err != nil { return nil, fmt.Errorf("Failed to read password file: %v", err) } + lines := strings.Split(string(text), "\n") + // Sanitise DOS line endings. for i := range lines { lines[i] = strings.TrimRight(lines[i], "\r") } + return lines, nil } diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go index 7368478123..94c4496c03 100644 --- a/internal/cli/server/config_test.go +++ b/internal/cli/server/config_test.go @@ -52,6 +52,7 @@ func TestConfigMerge(t *testing.T) { }, }, } + expected := &Config{ Chain: "1", NoSnapshot: false, @@ -69,11 +70,14 @@ func TestConfigMerge(t *testing.T) { }, }, } + assert.NoError(t, c0.Merge(c1)) assert.Equal(t, c0, expected) } func TestDefaultDatatypeOverride(t *testing.T) { + t.Parallel() + // This test is specific to `maxpeers` flag (for now) to check // if default datatype value (0 in case of uint64) is overridden. c0 := &Config{ @@ -81,16 +85,19 @@ func TestDefaultDatatypeOverride(t *testing.T) { MaxPeers: 30, }, } + c1 := &Config{ P2P: &P2PConfig{ MaxPeers: 0, }, } + expected := &Config{ P2P: &P2PConfig{ MaxPeers: 0, }, } + assert.NoError(t, c0.Merge(c1)) assert.Equal(t, c0, expected) } @@ -99,6 +106,7 @@ func TestConfigLoadFile(t *testing.T) { readFile := func(path string) { config, err := readConfigFile(path) assert.NoError(t, err) + assert.Equal(t, config, &Config{ DataDir: "./data", RequiredBlocks: map[string]string{ @@ -122,6 +130,7 @@ func TestConfigLoadFile(t *testing.T) { t.Run("hcl", func(t *testing.T) { readFile("./testdata/simple.hcl") }) + // read file in json format t.Run("json", func(t *testing.T) { readFile("./testdata/simple.json") @@ -152,7 +161,11 @@ func TestConfigBootnodesDefault(t *testing.T) { } func TestMakePasswordListFromFile(t *testing.T) { + t.Parallel() + t.Run("ReadPasswordFile", func(t *testing.T) { + t.Parallel() + result, _ := MakePasswordListFromFile("./testdata/password.txt") assert.Equal(t, []string{"test1", "test2"}, result) }) diff --git a/internal/cli/server/helper.go b/internal/cli/server/helper.go index c6831382b3..3a232d3185 100644 --- a/internal/cli/server/helper.go +++ b/internal/cli/server/helper.go @@ -17,10 +17,13 @@ func findAvailablePort(from int32, count int32) (int32, error) { if count == maxPortCheck { return 0, fmt.Errorf("no available port found") } + port := atomic.AddInt32(&from, 1) addr := fmt.Sprintf("localhost:%d", port) - lis, err := net.Listen("tcp", addr) + count++ + + lis, err := net.Listen("tcp", addr) if err == nil { lis.Close() return port, nil @@ -36,8 +39,13 @@ func CreateMockServer(config *Config) (*Server, error) { // find available port for grpc server rand.Seed(time.Now().UnixNano()) - var from int32 = 60000 // the min port to start checking from - var to int32 = 61000 // the max port to start checking from + + var ( + from int32 = 60000 // the min port to start checking from + to int32 = 61000 // the max port to start checking from + ) + + //nolint: gosec port, err := findAvailablePort(rand.Int31n(to-from+1)+from, 0) if err != nil { return nil, err @@ -53,10 +61,13 @@ func CreateMockServer(config *Config) (*Server, error) { // find available port for http server from = 8545 to = 9545 + + //nolint: gosec port, err = findAvailablePort(rand.Int31n(to-from+1)+from, 0) if err != nil { return nil, err } + config.JsonRPC.Http.Port = uint64(port) // start the server diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go index 3d0b55e094..7d5ec2c8f3 100644 --- a/internal/cli/server/server.go +++ b/internal/cli/server/server.go @@ -11,6 +11,16 @@ import ( "strings" "time" + "github.com/mattn/go-colorable" + "github.com/mattn/go-isatty" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + "google.golang.org/grpc" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/consensus/beacon" @@ -26,15 +36,6 @@ import ( "github.com/ethereum/go-ethereum/metrics/influxdb" "github.com/ethereum/go-ethereum/metrics/prometheus" "github.com/ethereum/go-ethereum/node" - "github.com/mattn/go-colorable" - "github.com/mattn/go-isatty" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" - "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" - "google.golang.org/grpc" ) type Server struct { @@ -71,6 +72,7 @@ func NewServer(config *Config) (*Server, error) { if err != nil { return nil, err } + stack, err := node.New(nodeCfg) if err != nil { return nil, err @@ -82,6 +84,7 @@ func NewServer(config *Config) (*Server, error) { // register backend to account manager with keystore for signing keydir := stack.KeyStoreDir() + n, p := keystore.StandardScryptN, keystore.StandardScryptP if config.Accounts.UseLightweightKDF { n, p = keystore.LightScryptN, keystore.LightScryptP @@ -94,6 +97,7 @@ func NewServer(config *Config) (*Server, error) { authorized := false // check if personal wallet endpoints are disabled or not + // nolint:nestif if !config.Accounts.DisableBorWallet { // add keystore globally to the node's account manager if personal wallet is enabled stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p)) @@ -103,10 +107,12 @@ func NewServer(config *Config) (*Server, error) { if err != nil { return nil, err } + backend, err := eth.New(stack, ethCfg) if err != nil { return nil, err } + srv.backend = backend } else { // register the ethereum backend (with temporary created account manager) @@ -114,10 +120,12 @@ func NewServer(config *Config) (*Server, error) { if err != nil { return nil, err } + backend, err := eth.New(stack, ethCfg) if err != nil { return nil, err } + srv.backend = backend // authorize only if mining or in developer mode @@ -126,6 +134,7 @@ func NewServer(config *Config) (*Server, error) { eb, err := srv.backend.Etherbase() if err != nil { log.Error("Cannot start mining without etherbase", "err", err) + return nil, fmt.Errorf("etherbase missing: %v", err) } @@ -142,8 +151,10 @@ func NewServer(config *Config) (*Server, error) { wallet, err := accountManager.Find(accounts.Account{Address: eb}) if wallet == nil || err != nil { log.Error("Etherbase account unavailable locally", "err", err) + return nil, fmt.Errorf("signer missing: %v", err) } + cli.Authorize(eb, wallet.SignData) authorized = true } @@ -155,6 +166,7 @@ func NewServer(config *Config) (*Server, error) { log.Error("Etherbase account unavailable locally", "err", err) return nil, fmt.Errorf("signer missing: %v", err) } + bor.Authorize(eb, wallet.SignData) authorized = true } @@ -200,6 +212,7 @@ func NewServer(config *Config) (*Server, error) { if err := srv.node.Start(); err != nil { return nil, err } + return srv, nil } @@ -238,10 +251,12 @@ func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error if v1Enabled { log.Info("Enabling metrics export to InfluxDB (v1)") + go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, cfg.Database, cfg.Username, cfg.Password, "geth.", tags) } if v2Enabled { log.Info("Enabling metrics export to InfluxDB (v2)") + go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, cfg.Token, cfg.Bucket, cfg.Organization, "geth.", tags) } } @@ -328,6 +343,7 @@ func (s *Server) setupGRPCServer(addr string) error { }() log.Info("GRPC Server started", "addr", addr) + return nil } @@ -338,16 +354,20 @@ func (s *Server) withLoggingUnaryInterceptor() grpc.ServerOption { func (s *Server) loggingServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { start := time.Now() h, err := handler(ctx, req) + log.Trace("Request", "method", info.FullMethod, "duration", time.Since(start), "error", err) + return h, err } func setupLogger(logLevel string) { output := io.Writer(os.Stderr) + usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb" if usecolor { output = colorable.NewColorableStderr() } + ostream := log.StreamHandler(output, log.TerminalFormat(usecolor)) glogger := log.NewGlogHandler(ostream) @@ -358,6 +378,7 @@ func setupLogger(logLevel string) { } else { glogger.Verbosity(log.LvlInfo) } + log.Root().SetHandler(glogger) } diff --git a/internal/cli/server/server_test.go b/internal/cli/server/server_test.go index a0b6dee2e3..c88c656b10 100644 --- a/internal/cli/server/server_test.go +++ b/internal/cli/server/server_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/assert" ) @@ -18,9 +19,11 @@ func nextPort() uint64 { log.Info("Checking for new port", "current", initialPort) port := atomic.AddUint64(&initialPort, 1) addr := fmt.Sprintf("localhost:%d", port) + lis, err := net.Listen("tcp", addr) if err == nil { lis.Close() + return port } else { return nextPort() @@ -28,6 +31,8 @@ func nextPort() uint64 { } func TestServer_DeveloperMode(t *testing.T) { + t.Parallel() + // get the default config config := DefaultConfig() @@ -38,6 +43,7 @@ func TestServer_DeveloperMode(t *testing.T) { // start the mock server server, err := CreateMockServer(config) assert.NoError(t, err) + defer CloseMockServer(server) // record the initial block number diff --git a/internal/cli/server/service.go b/internal/cli/server/service.go index 304b61b7d0..de240d5461 100644 --- a/internal/cli/server/service.go +++ b/internal/cli/server/service.go @@ -8,6 +8,10 @@ import ( "reflect" "strings" + gproto "github.com/golang/protobuf/proto" //nolint:staticcheck,typecheck + "github.com/golang/protobuf/ptypes/empty" + grpc_net_conn "github.com/mitchellh/go-grpc-net-conn" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/tracers" @@ -16,9 +20,6 @@ import ( "github.com/ethereum/go-ethereum/internal/cli/server/proto" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" - gproto "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes/empty" - grpc_net_conn "github.com/mitchellh/go-grpc-net-conn" ) const chunkSize = 1024 * 1024 * 1024 @@ -45,6 +46,7 @@ func sendStreamDebugFile(stream proto.Bor_DebugPprofServer, headers map[string]s Request: &proto.DebugFileResponse_Input{}, Encode: grpc_net_conn.ChunkedEncoder(encoder, chunkSize), } + if _, err := conn.Write(data); err != nil { return err } @@ -61,11 +63,14 @@ func sendStreamDebugFile(stream proto.Bor_DebugPprofServer, headers map[string]s } func (s *Server) DebugPprof(req *proto.DebugPprofRequest, stream proto.Bor_DebugPprofServer) error { - var payload []byte - var headers map[string]string - var err error + var ( + payload []byte + headers map[string]string + err error + ) ctx := context.Background() + switch req.Type { case proto.DebugPprofRequest_CPU: payload, headers, err = pprof.CPUProfile(ctx, int(req.Seconds)) @@ -74,6 +79,7 @@ func (s *Server) DebugPprof(req *proto.DebugPprofRequest, stream proto.Bor_Debug case proto.DebugPprofRequest_LOOKUP: payload, headers, err = pprof.Profile(req.Profile, 0, 0) } + if err != nil { return err } @@ -82,6 +88,7 @@ func (s *Server) DebugPprof(req *proto.DebugPprofRequest, stream proto.Bor_Debug if err := sendStreamDebugFile(stream, headers, payload); err != nil { return err } + return nil } @@ -192,6 +199,7 @@ func (s *Server) DebugBlock(req *proto.DebugBlockRequest, stream proto.Bor_Debug }, }, } + res, err := s.tracerAPI.TraceBorBlock(traceReq) if err != nil { return err @@ -202,6 +210,7 @@ func (s *Server) DebugBlock(req *proto.DebugBlockRequest, stream proto.Bor_Debug if err != nil { return err } + if err := sendStreamDebugFile(stream, map[string]string{}, data); err != nil { return err } diff --git a/miner/fake_miner.go b/miner/fake_miner.go new file mode 100644 index 0000000000..cbe0d9f54c --- /dev/null +++ b/miner/fake_miner.go @@ -0,0 +1,233 @@ +package miner + +import ( + "errors" + "math/big" + "testing" + "time" + + "github.com/golang/mock/gomock" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/consensus/bor/api" + "github.com/ethereum/go-ethereum/consensus/bor/valset" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/tests/bor/mocks" + "github.com/ethereum/go-ethereum/trie" +) + +type DefaultBorMiner struct { + Miner *Miner + Mux *event.TypeMux //nolint:staticcheck + Cleanup func(skipMiner bool) + + Ctrl *gomock.Controller + EthAPIMock api.Caller + HeimdallClientMock bor.IHeimdallClient + ContractMock bor.GenesisContract +} + +func NewBorDefaultMiner(t *testing.T) *DefaultBorMiner { + t.Helper() + + ctrl := gomock.NewController(t) + + ethAPI := api.NewMockCaller(ctrl) + ethAPI.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + + spanner := bor.NewMockSpanner(ctrl) + spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{ + { + ID: 0, + Address: common.Address{0x1}, + VotingPower: 100, + ProposerPriority: 0, + }, + }, nil).AnyTimes() + + heimdallClient := mocks.NewMockIHeimdallClient(ctrl) + heimdallClient.EXPECT().Close().Times(1) + + genesisContracts := bor.NewMockGenesisContract(ctrl) + + miner, mux, cleanup := createBorMiner(t, ethAPI, spanner, heimdallClient, genesisContracts) + + return &DefaultBorMiner{ + Miner: miner, + Mux: mux, + Cleanup: cleanup, + Ctrl: ctrl, + EthAPIMock: ethAPI, + HeimdallClientMock: heimdallClient, + ContractMock: genesisContracts, + } +} + +//nolint:staticcheck +func createBorMiner(t *testing.T, ethAPIMock api.Caller, spanner bor.Spanner, heimdallClientMock bor.IHeimdallClient, contractMock bor.GenesisContract) (*Miner, *event.TypeMux, func(skipMiner bool)) { + t.Helper() + + // Create Ethash config + chainDB, _, chainConfig := NewDBForFakes(t) + + engine := NewFakeBor(t, chainDB, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) + + // Create Ethereum backend + bc, err := core.NewBlockChain(chainDB, nil, chainConfig, engine, vm.Config{}, nil, nil) + if err != nil { + t.Fatalf("can't create new chain %v", err) + } + + statedb, _ := state.New(common.Hash{}, state.NewDatabase(chainDB), nil) + blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)} + + pool := core.NewTxPool(testTxPoolConfig, chainConfig, blockchain) + backend := NewMockBackend(bc, pool) + + // Create event Mux + mux := new(event.TypeMux) + + config := Config{ + Etherbase: common.HexToAddress("123456789"), + } + + // Create Miner + miner := New(backend, &config, chainConfig, mux, engine, nil) + + cleanup := func(skipMiner bool) { + bc.Stop() + engine.Close() + pool.Stop() + + if !skipMiner { + miner.Close() + } + } + + return miner, mux, cleanup +} + +func NewDBForFakes(t *testing.T) (ethdb.Database, *core.Genesis, *params.ChainConfig) { + t.Helper() + + memdb := memorydb.New() + chainDB := rawdb.NewDatabase(memdb) + genesis := core.DeveloperGenesisBlock(2, 11_500_000, common.HexToAddress("12345")) + + chainConfig, _, err := core.SetupGenesisBlock(chainDB, genesis) + if err != nil { + t.Fatalf("can't create new chain config: %v", err) + } + + chainConfig.Bor.Period = map[string]uint64{ + "0": 1, + } + + return chainDB, genesis, chainConfig +} + +func NewFakeBor(t *testing.T, chainDB ethdb.Database, chainConfig *params.ChainConfig, ethAPIMock api.Caller, spanner bor.Spanner, heimdallClientMock bor.IHeimdallClient, contractMock bor.GenesisContract) consensus.Engine { + t.Helper() + + if chainConfig.Bor == nil { + chainConfig.Bor = params.BorUnittestChainConfig.Bor + } + + return bor.New(chainConfig, chainDB, ethAPIMock, spanner, heimdallClientMock, contractMock) +} + +type mockBackend struct { + bc *core.BlockChain + txPool *core.TxPool +} + +func NewMockBackend(bc *core.BlockChain, txPool *core.TxPool) *mockBackend { + return &mockBackend{ + bc: bc, + txPool: txPool, + } +} + +func (m *mockBackend) BlockChain() *core.BlockChain { + return m.bc +} + +func (m *mockBackend) TxPool() *core.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.Block { + return types.NewBlock(&types.Header{ + GasLimit: bc.gasLimit, + }, nil, nil, nil, trie.NewStackTrie(nil)) +} + +func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { + return bc.CurrentBlock() +} + +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 core.TxPoolConfig + ethashChainConfig *params.ChainConfig + cliqueChainConfig *params.ChainConfig + + // Test accounts + testBankKey, _ = crypto.GenerateKey() + testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) + testBankFunds = big.NewInt(1000000000000000000) + + testUserKey, _ = crypto.GenerateKey() + testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey) + + // Test transactions + pendingTxs []*types.Transaction + newTxs []*types.Transaction + + testConfig = &Config{ + Recommit: time.Second, + GasCeil: params.GenesisGasLimit, + } +) + +func init() { + testTxPoolConfig = core.DefaultTxPoolConfig + testTxPoolConfig.Journal = "" + ethashChainConfig = new(params.ChainConfig) + *ethashChainConfig = *params.TestChainConfig + cliqueChainConfig = new(params.ChainConfig) + *cliqueChainConfig = *params.TestChainConfig + cliqueChainConfig.Clique = ¶ms.CliqueConfig{ + Period: 10, + Epoch: 30000, + } +} diff --git a/miner/miner_test.go b/miner/miner_test.go index 03c79cbbd5..76f61fd0d4 100644 --- a/miner/miner_test.go +++ b/miner/miner_test.go @@ -18,80 +18,32 @@ package miner import ( - "errors" "testing" "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/ethdb/memorydb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/trie" ) -type mockBackend struct { - bc *core.BlockChain - txPool *core.TxPool -} - -func NewMockBackend(bc *core.BlockChain, txPool *core.TxPool) *mockBackend { - return &mockBackend{ - bc: bc, - txPool: txPool, - } -} - -func (m *mockBackend) BlockChain() *core.BlockChain { - return m.bc -} - -func (m *mockBackend) TxPool() *core.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.Block { - return types.NewBlock(&types.Header{ - GasLimit: bc.gasLimit, - }, nil, nil, nil, trie.NewStackTrie(nil)) -} - -func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { - return bc.CurrentBlock() -} +func TestMiner(t *testing.T) { + t.Parallel() -func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { - return bc.statedb, nil -} + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() -func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { - return bc.chainHeadFeed.Subscribe(ch) -} + miner := minerBor.Miner + mux := minerBor.Mux -func TestMiner(t *testing.T) { - miner, mux, cleanup := createMiner(t) - defer cleanup(false) miner.Start(common.HexToAddress("0x12345")) waitForMiningState(t, miner, true) + // Start the downloader mux.Post(downloader.StartEvent{}) waitForMiningState(t, miner, false) + // Stop the downloader and wait for the update loop to run mux.Post(downloader.DoneEvent{}) waitForMiningState(t, miner, true) @@ -113,10 +65,20 @@ func TestMiner(t *testing.T) { // An initial FailedEvent should allow mining to stop on a subsequent // downloader StartEvent. func TestMinerDownloaderFirstFails(t *testing.T) { - miner, mux, cleanup := createMiner(t) - defer cleanup(false) + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + mux := minerBor.Mux + miner.Start(common.HexToAddress("0x12345")) waitForMiningState(t, miner, true) + // Start the downloader mux.Post(downloader.StartEvent{}) waitForMiningState(t, miner, false) @@ -145,10 +107,20 @@ func TestMinerDownloaderFirstFails(t *testing.T) { } func TestMinerStartStopAfterDownloaderEvents(t *testing.T) { - miner, mux, cleanup := createMiner(t) - defer cleanup(false) + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + mux := minerBor.Mux + miner.Start(common.HexToAddress("0x12345")) waitForMiningState(t, miner, true) + // Start the downloader mux.Post(downloader.StartEvent{}) waitForMiningState(t, miner, false) @@ -168,58 +140,104 @@ func TestMinerStartStopAfterDownloaderEvents(t *testing.T) { } func TestStartWhileDownload(t *testing.T) { - miner, mux, cleanup := createMiner(t) - defer cleanup(false) + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + mux := minerBor.Mux + waitForMiningState(t, miner, false) miner.Start(common.HexToAddress("0x12345")) waitForMiningState(t, miner, true) + // Stop the downloader and wait for the update loop to run mux.Post(downloader.StartEvent{}) waitForMiningState(t, miner, false) + // Starting the miner after the downloader should not work miner.Start(common.HexToAddress("0x12345")) waitForMiningState(t, miner, false) } func TestStartStopMiner(t *testing.T) { - miner, _, cleanup := createMiner(t) - defer cleanup(false) + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + waitForMiningState(t, miner, false) miner.Start(common.HexToAddress("0x12345")) + waitForMiningState(t, miner, true) + miner.Stop() - waitForMiningState(t, miner, false) + waitForMiningState(t, miner, false) } func TestCloseMiner(t *testing.T) { - miner, _, cleanup := createMiner(t) - defer cleanup(true) + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(true) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + waitForMiningState(t, miner, false) + miner.Start(common.HexToAddress("0x12345")) + waitForMiningState(t, miner, true) + // Terminate the miner and wait for the update loop to run miner.Close() + waitForMiningState(t, miner, false) } // TestMinerSetEtherbase checks that etherbase becomes set even if mining isn't // possible at the moment func TestMinerSetEtherbase(t *testing.T) { - miner, mux, cleanup := createMiner(t) - defer cleanup(false) + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + mux := minerBor.Mux + // Start with a 'bad' mining address miner.Start(common.HexToAddress("0xdead")) waitForMiningState(t, miner, true) + // Start the downloader mux.Post(downloader.StartEvent{}) waitForMiningState(t, miner, false) + // Now user tries to configure proper mining address miner.Start(common.HexToAddress("0x1337")) + // Stop the downloader and wait for the update loop to run mux.Post(downloader.DoneEvent{}) waitForMiningState(t, miner, true) + // The miner should now be using the good address if got, exp := miner.coinbase, common.HexToAddress("0x1337"); got != exp { t.Fatalf("Wrong coinbase, got %x expected %x", got, exp) @@ -239,46 +257,6 @@ func waitForMiningState(t *testing.T, m *Miner, mining bool) { return } } - t.Fatalf("Mining() == %t, want %t", state, mining) -} -func createMiner(t *testing.T) (*Miner, *event.TypeMux, func(skipMiner bool)) { - // Create Ethash config - config := Config{ - Etherbase: common.HexToAddress("123456789"), - } - // Create chainConfig - memdb := memorydb.New() - chainDB := rawdb.NewDatabase(memdb) - genesis := core.DeveloperGenesisBlock(15, 11_500_000, common.HexToAddress("12345")) - chainConfig, _, err := core.SetupGenesisBlock(chainDB, genesis) - if err != nil { - t.Fatalf("can't create new chain config: %v", err) - } - // Create consensus engine - engine := clique.New(chainConfig.Clique, chainDB) - // Create Ethereum backend - consensus.NewMerger(rawdb.NewMemoryDatabase()) - bc, err := core.NewBlockChain(chainDB, nil, chainConfig, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("can't create new chain %v", err) - } - statedb, _ := state.New(common.Hash{}, state.NewDatabase(chainDB), nil) - blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)} - - pool := core.NewTxPool(testTxPoolConfig, chainConfig, blockchain) - backend := NewMockBackend(bc, pool) - // Create event Mux - mux := new(event.TypeMux) - // Create Miner - miner := New(backend, &config, chainConfig, mux, engine, nil) - cleanup := func(skipMiner bool) { - bc.Stop() - engine.Close() - pool.Stop() - if !skipMiner { - miner.Close() - } - } - return miner, mux, cleanup + t.Fatalf("Mining() == %t, want %t", state, mining) } diff --git a/miner/unconfirmed_test.go b/miner/unconfirmed_test.go index dc83cb9265..70d3325506 100644 --- a/miner/unconfirmed_test.go +++ b/miner/unconfirmed_test.go @@ -44,6 +44,7 @@ func TestUnconfirmedInsertBounds(t *testing.T) { for i := 0; i < int(depth); i++ { pool.Insert(depth, [32]byte{byte(depth), byte(i)}) } + // Validate that no blocks below the depth allowance are left in pool.blocks.Do(func(block interface{}) { if block := block.(*unconfirmedBlock); block.index+uint64(limit) <= depth { @@ -64,23 +65,29 @@ func TestUnconfirmedShifts(t *testing.T) { for depth := start; depth < start+uint64(limit); depth++ { pool.Insert(depth, [32]byte{byte(depth)}) } + // Try to shift below the limit and ensure no blocks are dropped pool.Shift(start + uint64(limit) - 1) if n := pool.blocks.Len(); n != int(limit) { t.Errorf("unconfirmed count mismatch: have %d, want %d", n, limit) } + // Try to shift half the blocks out and verify remainder pool.Shift(start + uint64(limit) - 1 + uint64(limit/2)) if n := pool.blocks.Len(); n != int(limit)/2 { t.Errorf("unconfirmed count mismatch: have %d, want %d", n, limit/2) } + // Try to shift all the remaining blocks out and verify emptyness pool.Shift(start + 2*uint64(limit)) + if n := pool.blocks.Len(); n != 0 { t.Errorf("unconfirmed count mismatch: have %d, want %d", n, 0) } + // Try to shift out from the empty set and make sure it doesn't break pool.Shift(start + 3*uint64(limit)) + if n := pool.blocks.Len(); n != 0 { t.Errorf("unconfirmed count mismatch: have %d, want %d", n, 0) } diff --git a/miner/worker.go b/miner/worker.go index c3a5e1c9ba..14c5ccd1a3 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -25,6 +25,7 @@ import ( "time" mapset "github.com/deckarep/golang-set" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" @@ -393,8 +394,10 @@ func recalcRecommit(minRecommit, prev time.Duration, target float64, inc bool) t prevF = float64(prev.Nanoseconds()) next float64 ) + if inc { next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target+intervalAdjustBias) + max := float64(maxRecommitInterval.Nanoseconds()) if next > max { next = max @@ -406,6 +409,7 @@ func recalcRecommit(minRecommit, prev time.Duration, target float64, inc bool) t next = min } } + return time.Duration(int64(next)) } diff --git a/miner/worker_test.go b/miner/worker_test.go index dd029433b8..00739844f2 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -24,9 +24,14 @@ import ( "testing" "time" + "github.com/golang/mock/gomock" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/consensus/bor/api" + "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" @@ -38,6 +43,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/tests/bor/mocks" ) const ( @@ -49,43 +55,9 @@ const ( testGas = 144109 ) -var ( - // Test chain configurations - testTxPoolConfig core.TxPoolConfig - ethashChainConfig *params.ChainConfig - cliqueChainConfig *params.ChainConfig - - // Test accounts - testBankKey, _ = crypto.GenerateKey() - testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) - testBankFunds = big.NewInt(1000000000000000000) - - testUserKey, _ = crypto.GenerateKey() - testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey) - - // Test transactions - pendingTxs []*types.Transaction - newTxs []*types.Transaction - - testConfig = &Config{ - Recommit: time.Second, - GasCeil: params.GenesisGasLimit, - } -) - func init() { - testTxPoolConfig = core.DefaultTxPoolConfig - testTxPoolConfig.Journal = "" - ethashChainConfig = new(params.ChainConfig) - *ethashChainConfig = *params.TestChainConfig - cliqueChainConfig = new(params.ChainConfig) - *cliqueChainConfig = *params.TestChainConfig - cliqueChainConfig.Clique = ¶ms.CliqueConfig{ - Period: 10, - Epoch: 30000, - } - signer := types.LatestSigner(params.TestChainConfig) + tx1 := types.MustSignNewTx(testBankKey, signer, &types.AccessListTx{ ChainID: params.TestChainConfig.ChainID, Nonce: 0, @@ -94,6 +66,7 @@ func init() { Gas: params.TxGas, GasPrice: big.NewInt(params.InitialBaseFee), }) + pendingTxs = append(pendingTxs, tx1) tx2 := types.MustSignNewTx(testBankKey, signer, &types.LegacyTx{ @@ -103,6 +76,7 @@ func init() { Gas: params.TxGas, GasPrice: big.NewInt(params.InitialBaseFee), }) + newTxs = append(newTxs, tx2) rand.Seed(time.Now().UnixNano()) @@ -125,6 +99,12 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine } switch e := engine.(type) { + case *bor.Bor: + gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) + copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes()) + e.Authorize(testBankAddress, func(account accounts.Account, s string, data []byte) ([]byte, error) { + return crypto.Sign(crypto.Keccak256(data), testBankKey) + }) case *clique.Clique: gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes()) @@ -135,6 +115,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine default: t.Fatalf("unexpected consensus engine type: %T", engine) } + genesis := gspec.MustCommit(db) chain, _ := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec.Config, engine, vm.Config{}, nil, nil) @@ -149,10 +130,12 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine t.Fatalf("failed to insert origin chain: %v", err) } } + parent := genesis if n > 0 { parent = chain.GetBlockByHash(chain.CurrentBlock().ParentHash()) } + blocks, _ := core.GenerateChain(chainConfig, parent, engine, db, 1, func(i int, gen *core.BlockGen) { gen.SetCoinbase(testUserAddress) }) @@ -174,28 +157,36 @@ func (b *testWorkerBackend) StateAtBlock(block *types.Block, reexec uint64, base func (b *testWorkerBackend) newRandomUncle() *types.Block { var parent *types.Block + cur := b.chain.CurrentBlock() + if cur.NumberU64() == 0 { parent = b.chain.Genesis() } else { parent = b.chain.GetBlockByHash(b.chain.CurrentBlock().ParentHash()) } + blocks, _ := core.GenerateChain(b.chain.Config(), parent, b.chain.Engine(), b.db, 1, func(i int, gen *core.BlockGen) { var addr = make([]byte, common.AddressLength) + rand.Read(addr) gen.SetCoinbase(common.BytesToAddress(addr)) }) + return blocks[0] } func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction { var tx *types.Transaction + gasPrice := big.NewInt(10 * params.InitialBaseFee) + if creation { tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(testBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(testCode)), types.HomesteadSigner{}, testBankKey) } else { tx, _ = types.SignTx(types.NewTransaction(b.txPool.Nonce(testBankAddress), testUserAddress, big.NewInt(1000), params.TxGas, gasPrice, nil), types.HomesteadSigner{}, testBankKey) } + return tx } @@ -204,39 +195,85 @@ func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consens backend.txPool.AddLocals(pendingTxs) w := newWorker(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false) w.setEtherbase(testBankAddress) + return w, backend } func TestGenerateBlockAndImportEthash(t *testing.T) { - testGenerateBlockAndImport(t, false) + t.Parallel() + + testGenerateBlockAndImport(t, false, false) } func TestGenerateBlockAndImportClique(t *testing.T) { - testGenerateBlockAndImport(t, true) + t.Parallel() + + testGenerateBlockAndImport(t, true, false) +} + +func TestGenerateBlockAndImportBor(t *testing.T) { + t.Parallel() + + testGenerateBlockAndImport(t, false, true) } -func testGenerateBlockAndImport(t *testing.T, isClique bool) { +//nolint:thelper +func testGenerateBlockAndImport(t *testing.T, isClique bool, isBor bool) { var ( engine consensus.Engine chainConfig *params.ChainConfig db = rawdb.NewMemoryDatabase() ) - if isClique { - chainConfig = params.AllCliqueProtocolChanges - chainConfig.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000} - engine = clique.New(chainConfig.Clique, db) + + if isBor { + chainConfig = params.BorUnittestChainConfig + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ethAPIMock := api.NewMockCaller(ctrl) + ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + + spanner := bor.NewMockSpanner(ctrl) + spanner.EXPECT().GetCurrentValidators(gomock.Any(), gomock.Any()).Return([]*valset.Validator{ + { + ID: 0, + Address: testBankAddress, + VotingPower: 100, + ProposerPriority: 0, + }, + }, nil).AnyTimes() + + heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl) + heimdallClientMock.EXPECT().Close().Times(1) + + contractMock := bor.NewMockGenesisContract(ctrl) + + db, _, _ = NewDBForFakes(t) + + engine = NewFakeBor(t, db, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) } else { - chainConfig = params.AllEthashProtocolChanges - engine = ethash.NewFaker() + if isClique { + chainConfig = params.AllCliqueProtocolChanges + chainConfig.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000} + engine = clique.New(chainConfig.Clique, db) + } else { + chainConfig = params.AllEthashProtocolChanges + engine = ethash.NewFaker() + } } + defer engine.Close() + chainConfig.LondonBlock = big.NewInt(0) + w, b := newTestWorker(t, chainConfig, engine, db, 0) defer w.close() // This test chain imports the mined blocks. db2 := rawdb.NewMemoryDatabase() b.genesis.MustCommit(db2) + chain, _ := core.NewBlockChain(db2, nil, b.chain.Config(), engine, vm.Config{}, nil, nil) defer chain.Stop() @@ -287,20 +324,25 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens taskIndex int taskCh = make(chan struct{}, 2) ) + checkEqual := func(t *testing.T, task *task, index int) { // The first empty work without any txs included receiptLen, balance := 0, big.NewInt(0) + if index == 1 { // The second full work with 1 tx included receiptLen, balance = 1, big.NewInt(1000) } + if len(task.receipts) != receiptLen { t.Fatalf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen) } + if task.state.GetBalance(testUserAddress).Cmp(balance) != 0 { t.Fatalf("account balance mismatch: have %d, want %d", task.state.GetBalance(testUserAddress), balance) } } + w.newTaskHook = func(task *task) { if task.block.NumberU64() == 1 { checkEqual(t, task, taskIndex) @@ -308,11 +350,14 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens taskCh <- struct{}{} } } + w.skipSealHook = func(task *task) bool { return true } w.fullTaskHook = func() { time.Sleep(100 * time.Millisecond) } + w.start() // Start mining! + for i := 0; i < 2; i += 1 { select { case <-taskCh: @@ -344,16 +389,20 @@ func TestStreamUncleBlock(t *testing.T) { t.Errorf("uncle hash mismatch: have %s, want %s", have.Hex(), want.Hex()) } } + taskCh <- struct{}{} taskIndex += 1 } } + w.skipSealHook = func(task *task) bool { return true } + w.fullTaskHook = func() { time.Sleep(100 * time.Millisecond) } + w.start() for i := 0; i < 2; i += 1 { @@ -396,20 +445,25 @@ func testRegenerateMiningBlock(t *testing.T, chainConfig *params.ChainConfig, en // one has 1 pending tx, the third one has 2 txs if taskIndex == 2 { receiptLen, balance := 2, big.NewInt(2000) + if len(task.receipts) != receiptLen { t.Errorf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen) } + if task.state.GetBalance(testUserAddress).Cmp(balance) != 0 { t.Errorf("account balance mismatch: have %d, want %d", task.state.GetBalance(testUserAddress), balance) } } + taskCh <- struct{}{} taskIndex += 1 } } + w.skipSealHook = func(task *task) bool { return true } + w.fullTaskHook = func() { time.Sleep(100 * time.Millisecond) } @@ -423,6 +477,7 @@ func testRegenerateMiningBlock(t *testing.T, chainConfig *params.ChainConfig, en t.Error("new task timeout") } } + b.txPool.AddLocals(newTxs) time.Sleep(time.Second) @@ -459,6 +514,7 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co index = 0 start uint32 ) + w.resubmitHook = func(minInterval time.Duration, recommitInterval time.Duration) { // Short circuit if interval checking hasn't started. if atomic.LoadUint32(&start) == 0 { @@ -489,16 +545,19 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co if recommitInterval != wantRecommitInterval { t.Errorf("resubmit interval mismatch: have %v, want %v", recommitInterval, wantRecommitInterval) } + result = append(result, float64(recommitInterval.Nanoseconds())) index += 1 progress <- struct{}{} } + w.start() time.Sleep(time.Second) // Ensure two tasks have been summitted due to start opt atomic.StoreUint32(&start, 1) w.setRecommitInterval(3 * time.Second) + select { case <-progress: case <-time.NewTimer(time.Second).C: @@ -506,6 +565,7 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co } w.resubmitAdjustCh <- &intervalAdjust{inc: true, ratio: 0.8} + select { case <-progress: case <-time.NewTimer(time.Second).C: @@ -513,6 +573,7 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co } w.resubmitAdjustCh <- &intervalAdjust{inc: false} + select { case <-progress: case <-time.NewTimer(time.Second).C: @@ -520,6 +581,7 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co } w.setRecommitInterval(500 * time.Millisecond) + select { case <-progress: case <-time.NewTimer(time.Second).C: @@ -554,9 +616,11 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co w.skipSealHook = func(task *task) bool { return true } + w.fullTaskHook = func() { time.Sleep(100 * time.Millisecond) } + timestamp := uint64(time.Now().Unix()) assertBlock := func(block *types.Block, number uint64, coinbase common.Address, random common.Hash) { if block.Time() != timestamp { @@ -564,14 +628,17 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co // is even smaller than parent block's. It's OK. t.Logf("Invalid timestamp, want %d, get %d", timestamp, block.Time()) } + if len(block.Uncles()) != 0 { t.Error("Unexpected uncle block") } + _, isClique := engine.(*clique.Clique) if !isClique { if len(block.Extra()) != 0 { t.Error("Unexpected extra field") } + if block.Coinbase() != coinbase { t.Errorf("Unexpected coinbase got %x want %x", block.Coinbase(), coinbase) } @@ -580,18 +647,22 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co t.Error("Unexpected coinbase") } } + if !isClique { if block.MixDigest() != random { t.Error("Unexpected mix digest") } } + if block.Nonce() != 0 { t.Error("Unexpected block nonce") } + if block.NumberU64() != number { t.Errorf("Mismatched block number, want %d got %d", number, block.NumberU64()) } } + var cases = []struct { parent common.Hash coinbase common.Address @@ -639,6 +710,7 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co // This API should work even when the automatic sealing is not enabled for _, c := range cases { block, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random) + if c.expectErr { if err == nil { t.Error("Expect error but get nil") @@ -647,12 +719,14 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co if err != nil { t.Errorf("Unexpected error %v", err) } + assertBlock(block, c.expectNumber, c.coinbase, c.random) } } // This API should work even when the automatic sealing is enabled w.start() + for _, c := range cases { block, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random) if c.expectErr { @@ -663,6 +737,7 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co if err != nil { t.Errorf("Unexpected error %v", err) } + assertBlock(block, c.expectNumber, c.coinbase, c.random) } } diff --git a/params/config.go b/params/config.go index 47e22f986c..980250a1ec 100644 --- a/params/config.go +++ b/params/config.go @@ -23,8 +23,9 @@ import ( "sort" "strconv" - "github.com/ethereum/go-ethereum/common" "golang.org/x/crypto/sha3" + + "github.com/ethereum/go-ethereum/common" ) // Genesis hashes to enforce below configs on. @@ -289,6 +290,38 @@ var ( }, }, } + BorUnittestChainConfig = &ChainConfig{ + ChainID: big.NewInt(80001), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Hash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + Bor: &BorConfig{ + Period: map[string]uint64{ + "0": 1, + }, + ProducerDelay: 3, + Sprint: 32, + BackupMultiplier: map[string]uint64{ + "0": 2, + }, + ValidatorContract: "0x0000000000000000000000000000000000001000", + StateReceiverContract: "0x0000000000000000000000000000000000001001", + BurntContract: map[string]string{ + "0": "0x00000000000000000000000000000000000000000", + }, + }, + } // MumbaiChainConfig contains the chain parameters to run a node on the Mumbai test network. MumbaiChainConfig = &ChainConfig{ @@ -550,7 +583,9 @@ func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uin for k := range field { keys = append(keys, k) } + sort.Strings(keys) + for i := 0; i < len(keys)-1; i++ { valUint, _ := strconv.ParseUint(keys[i], 10, 64) valUintNext, _ := strconv.ParseUint(keys[i+1], 10, 64) @@ -558,6 +593,7 @@ func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uin return field[keys[i]] } } + return field[keys[len(keys)-1]] } diff --git a/tests/bor/bor_test.go b/tests/bor/bor_test.go index 3bda2ee3f4..434ad805e1 100644 --- a/tests/bor/bor_test.go +++ b/tests/bor/bor_test.go @@ -5,14 +5,17 @@ package bor import ( "encoding/hex" - "encoding/json" "io" "math/big" "testing" "time" + "github.com/golang/mock/gomock" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/consensus/bor/clerk" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" @@ -22,12 +25,12 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/tests/bor/mocks" + "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "golang.org/x/crypto/sha3" ) -var ( +const ( spanPath = "bor/span/1" clerkPath = "clerk/event-record/list" clerkQueryParams = "from-time=%d&to-time=%d&page=%d&limit=50" @@ -38,7 +41,10 @@ func TestInsertingSpanSizeBlocks(t *testing.T) { chain := init.ethereum.BlockChain() engine := init.ethereum.Engine() _bor := engine.(*bor.Bor) - h, heimdallSpan := getMockedHeimdallClient(t) + + h, heimdallSpan, ctrl := getMockedHeimdallClient(t) + defer ctrl.Finish() + _bor.SetHeimdallClient(h) db := init.ethereum.ChainDb() @@ -51,7 +57,6 @@ func TestInsertingSpanSizeBlocks(t *testing.T) { insertNewBlock(t, chain, block) } - assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, "")) validators, err := _bor.GetCurrentValidators(block.Hash(), spanSize) // check validator set at the first block of new span if err != nil { t.Fatalf("%s", err) @@ -82,8 +87,12 @@ func TestFetchStateSyncEvents(t *testing.T) { // B. Before inserting 1st block of the next sprint, mock heimdall deps // B.1 Mock /bor/span/1 res, _ := loadSpanFromFile(t) - h := &mocks.IHeimdallClient{} - h.On("FetchWithRetry", spanPath, "").Return(res, nil) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + h := mocks.NewMockIHeimdallClient(ctrl) + h.EXPECT().Span(uint64(1)).Return(&res.Result, nil).AnyTimes() // B.2 Mock State Sync events fromID := uint64(1) @@ -94,14 +103,12 @@ func TestFetchStateSyncEvents(t *testing.T) { sample := getSampleEventRecord(t) sample.Time = time.Unix(to-int64(eventCount+1), 0) // last event.Time will be just < to eventRecords := generateFakeStateSyncEvents(sample, eventCount) - h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil) + + h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes() _bor.SetHeimdallClient(h) block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor) insertNewBlock(t, chain, block) - - assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, "")) - assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to)) } func TestFetchStateSyncEvents_2(t *testing.T) { @@ -112,8 +119,12 @@ func TestFetchStateSyncEvents_2(t *testing.T) { // Mock /bor/span/1 res, _ := loadSpanFromFile(t) - h := &mocks.IHeimdallClient{} - h.On("FetchWithRetry", spanPath, "").Return(res, nil) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + h := mocks.NewMockIHeimdallClient(ctrl) + h.EXPECT().Span(uint64(1)).Return(&res.Result, nil).AnyTimes() // Mock State Sync events // at # sprintSize, events are fetched for [fromID, (block-sprint).Time) @@ -123,7 +134,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) { // First query will be from [id=1, (block-sprint).Time] // Insert 5 events in this time range - eventRecords := []*bor.EventRecordWithTime{ + eventRecords := []*clerk.EventRecordWithTime{ buildStateEvent(sample, 1, 3), // id = 1, time = 1 buildStateEvent(sample, 2, 1), // id = 2, time = 3 buildStateEvent(sample, 3, 2), // id = 3, time = 2 @@ -131,7 +142,8 @@ func TestFetchStateSyncEvents_2(t *testing.T) { buildStateEvent(sample, 4, 5), // id = 4, time = 5 buildStateEvent(sample, 6, 4), // id = 6, time = 4 } - h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil) + + h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes() _bor.SetHeimdallClient(h) // Insert blocks for 0th sprint @@ -141,25 +153,27 @@ func TestFetchStateSyncEvents_2(t *testing.T) { block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor) insertNewBlock(t, chain, block) } - assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, "")) - assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to)) + lastStateID, _ := _bor.GenesisContractsClient.LastStateId(sprintSize) + // state 6 was not written assert.Equal(t, uint64(4), lastStateID.Uint64()) // fromID = uint64(5) to = int64(chain.GetHeaderByNumber(sprintSize).Time) - eventRecords = []*bor.EventRecordWithTime{ + + eventRecords = []*clerk.EventRecordWithTime{ buildStateEvent(sample, 5, 7), buildStateEvent(sample, 6, 4), } - h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil) + h.EXPECT().StateSyncEvents(fromID, to).Return(eventRecords, nil).AnyTimes() + for i := sprintSize + 1; i <= spanSize; i++ { block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor) insertNewBlock(t, chain, block) } - assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to)) + lastStateID, _ = _bor.GenesisContractsClient.LastStateId(spanSize) assert.Equal(t, uint64(6), lastStateID.Uint64()) } @@ -169,7 +183,10 @@ func TestOutOfTurnSigning(t *testing.T) { chain := init.ethereum.BlockChain() engine := init.ethereum.Engine() _bor := engine.(*bor.Bor) - h, _ := getMockedHeimdallClient(t) + + h, _, ctrl := getMockedHeimdallClient(t) + defer ctrl.Finish() + _bor.SetHeimdallClient(h) db := init.ethereum.ChainDb() @@ -217,7 +234,10 @@ func TestSignerNotFound(t *testing.T) { chain := init.ethereum.BlockChain() engine := init.ethereum.Engine() _bor := engine.(*bor.Bor) - h, _ := getMockedHeimdallClient(t) + + h, _, ctrl := getMockedHeimdallClient(t) + defer ctrl.Finish() + _bor.SetHeimdallClient(h) db := init.ethereum.ChainDb() @@ -236,47 +256,46 @@ func TestSignerNotFound(t *testing.T) { bor.UnauthorizedSignerError{Number: 0, Signer: addr.Bytes()}) } -func getMockedHeimdallClient(t *testing.T) (*mocks.IHeimdallClient, *bor.HeimdallSpan) { - res, heimdallSpan := loadSpanFromFile(t) - h := &mocks.IHeimdallClient{} - h.On("FetchWithRetry", "bor/span/1", "").Return(res, nil) - h.On( - "FetchStateSyncEvents", - mock.AnythingOfType("uint64"), - mock.AnythingOfType("int64")).Return([]*bor.EventRecordWithTime{getSampleEventRecord(t)}, nil) - return h, heimdallSpan +func getMockedHeimdallClient(t *testing.T) (*mocks.MockIHeimdallClient, *span.HeimdallSpan, *gomock.Controller) { + ctrl := gomock.NewController(t) + h := mocks.NewMockIHeimdallClient(ctrl) + + _, heimdallSpan := loadSpanFromFile(t) + + h.EXPECT().Span(uint64(1)).Return(heimdallSpan, nil).AnyTimes() + + h.EXPECT().StateSyncEvents(gomock.Any(), gomock.Any()). + Return([]*clerk.EventRecordWithTime{getSampleEventRecord(t)}, nil).AnyTimes() + + return h, heimdallSpan, ctrl } -func generateFakeStateSyncEvents(sample *bor.EventRecordWithTime, count int) []*bor.EventRecordWithTime { - events := make([]*bor.EventRecordWithTime, count) +func generateFakeStateSyncEvents(sample *clerk.EventRecordWithTime, count int) []*clerk.EventRecordWithTime { + events := make([]*clerk.EventRecordWithTime, count) event := *sample event.ID = 1 - events[0] = &bor.EventRecordWithTime{} + events[0] = &clerk.EventRecordWithTime{} *events[0] = event for i := 1; i < count; i++ { event.ID = uint64(i) event.Time = event.Time.Add(1 * time.Second) - events[i] = &bor.EventRecordWithTime{} + events[i] = &clerk.EventRecordWithTime{} *events[i] = event } return events } -func buildStateEvent(sample *bor.EventRecordWithTime, id uint64, timeStamp int64) *bor.EventRecordWithTime { +func buildStateEvent(sample *clerk.EventRecordWithTime, id uint64, timeStamp int64) *clerk.EventRecordWithTime { event := *sample event.ID = id event.Time = time.Unix(timeStamp, 0) return &event } -func getSampleEventRecord(t *testing.T) *bor.EventRecordWithTime { - res := stateSyncEventsPayload(t) - var _eventRecords []*bor.EventRecordWithTime - if err := json.Unmarshal(res.Result, &_eventRecords); err != nil { - t.Fatalf("%s", err) - } - _eventRecords[0].Time = time.Unix(1, 0) - return _eventRecords[0] +func getSampleEventRecord(t *testing.T) *clerk.EventRecordWithTime { + eventRecords := stateSyncEventsPayload(t) + eventRecords.Result[0].Time = time.Unix(1, 0) + return eventRecords.Result[0] } // TestEIP1559Transition tests the following: diff --git a/tests/bor/helper.go b/tests/bor/helper.go index a1b6a19742..a8a3ae4ea6 100644 --- a/tests/bor/helper.go +++ b/tests/bor/helper.go @@ -11,6 +11,9 @@ import ( "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall" + "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" + "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -46,17 +49,23 @@ type initializeData struct { } func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData { + t.Helper() + genesisData, err := ioutil.ReadFile("./testdata/genesis.json") if err != nil { t.Fatalf("%s", err) } + gen := &core.Genesis{} + if err := json.Unmarshal(genesisData, gen); err != nil { t.Fatalf("%s", err) } + ethConf := ð.Config{ Genesis: gen, } + ethConf.Genesis.MustCommit(db) ethereum := utils.CreateBorEthereum(ethConf) @@ -65,6 +74,7 @@ func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData { } ethConf.Genesis.MustCommit(ethereum.ChainDb()) + return &initializeData{ genesis: gen, ethereum: ethereum, @@ -72,12 +82,16 @@ func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData { } func insertNewBlock(t *testing.T, chain *core.BlockChain, block *types.Block) { + t.Helper() + if _, err := chain.InsertChain([]*types.Block{block}); err != nil { t.Fatalf("%s", err) } } func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block *types.Block, signer []byte, borConfig *params.BorConfig) *types.Block { + t.Helper() + header := block.Header() header.Number.Add(header.Number, big.NewInt(1)) number := header.Number.Uint64() @@ -90,11 +104,12 @@ func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block * header.Time += bor.CalcProducerDelay(header.Number.Uint64(), 0, borConfig) header.Extra = make([]byte, 32+65) // vanity + extraSeal - currentValidators := []*bor.Validator{bor.NewValidator(addr, 10)} + currentValidators := []*valset.Validator{valset.NewValidator(addr, 10)} isSpanEnd := (number+1)%spanSize == 0 isSpanStart := number%spanSize == 0 isSprintEnd := (header.Number.Uint64()+1)%sprintSize == 0 + if isSpanEnd { _, heimdallSpan := loadSpanFromFile(t) // this is to stash the validator bytes in the header @@ -102,18 +117,23 @@ func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block * } else if isSpanStart { header.Difficulty = new(big.Int).SetInt64(3) } + if isSprintEnd { - sort.Sort(bor.ValidatorsByAddress(currentValidators)) + sort.Sort(valset.ValidatorsByAddress(currentValidators)) + validatorBytes := make([]byte, len(currentValidators)*validatorHeaderBytesLength) header.Extra = make([]byte, 32+len(validatorBytes)+65) // vanity + validatorBytes + extraSeal + for i, val := range currentValidators { copy(validatorBytes[i*validatorHeaderBytesLength:], val.HeaderBytes()) } + copy(header.Extra[32:], validatorBytes) } if chain.Config().IsLondon(header.Number) { header.BaseFee = misc.CalcBaseFee(chain.Config(), block.Header()) + if !chain.Config().IsLondon(block.Number()) { parentGasLimit := block.GasLimit() * params.ElasticityMultiplier header.GasLimit = core.CalcGasLimit(parentGasLimit, parentGasLimit) @@ -124,58 +144,73 @@ func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block * if err != nil { t.Fatalf("%s", err) } + _, err = _bor.FinalizeAndAssemble(chain, header, state, nil, nil, nil) if err != nil { t.Fatalf("%s", err) } + sign(t, header, signer, borConfig) + return types.NewBlockWithHeader(header) } func sign(t *testing.T, header *types.Header, signer []byte, c *params.BorConfig) { + t.Helper() + sig, err := secp256k1.Sign(crypto.Keccak256(bor.BorRLP(header, c)), signer) if err != nil { t.Fatalf("%s", err) } + copy(header.Extra[len(header.Extra)-extraSeal:], sig) } -func stateSyncEventsPayload(t *testing.T) *bor.ResponseWithHeight { +//nolint:unused,deadcode +func stateSyncEventsPayload(t *testing.T) *heimdall.StateSyncEventsResponse { + t.Helper() + stateData, err := ioutil.ReadFile("./testdata/states.json") if err != nil { t.Fatalf("%s", err) } - res := &bor.ResponseWithHeight{} + + res := &heimdall.StateSyncEventsResponse{} if err := json.Unmarshal(stateData, res); err != nil { t.Fatalf("%s", err) } + return res } -func loadSpanFromFile(t *testing.T) (*bor.ResponseWithHeight, *bor.HeimdallSpan) { +//nolint:unused,deadcode +func loadSpanFromFile(t *testing.T) (*heimdall.SpanResponse, *span.HeimdallSpan) { + t.Helper() + spanData, err := ioutil.ReadFile("./testdata/span.json") if err != nil { t.Fatalf("%s", err) } - res := &bor.ResponseWithHeight{} + + res := &heimdall.SpanResponse{} + if err := json.Unmarshal(spanData, res); err != nil { t.Fatalf("%s", err) } - heimdallSpan := &bor.HeimdallSpan{} - if err := json.Unmarshal(res.Result, heimdallSpan); err != nil { - t.Fatalf("%s", err) - } - return res, heimdallSpan + return res, &res.Result } func getSignerKey(number uint64) []byte { signerKey := privKey + isSpanStart := number%spanSize == 0 if isSpanStart { // validator set in the new span has changed signerKey = privKey2 } + _key, _ := hex.DecodeString(signerKey) + return _key } diff --git a/tests/bor/mocks/IHeimdallClient.go b/tests/bor/mocks/IHeimdallClient.go index ac89487d3b..4e4d7a3776 100644 --- a/tests/bor/mocks/IHeimdallClient.go +++ b/tests/bor/mocks/IHeimdallClient.go @@ -1,87 +1,78 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: IHeimdallClient) +// Package mocks is a generated GoMock package. package mocks import ( - bor "github.com/ethereum/go-ethereum/consensus/bor" - mock "github.com/stretchr/testify/mock" + reflect "reflect" + + clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk" + span "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" + gomock "github.com/golang/mock/gomock" ) -// IHeimdallClient is an autogenerated mock type for the IHeimdallClient type -type IHeimdallClient struct { - mock.Mock +// MockIHeimdallClient is a mock of IHeimdallClient interface. +type MockIHeimdallClient struct { + ctrl *gomock.Controller + recorder *MockIHeimdallClientMockRecorder } -// Close provides a mock function with given fields: -func (_m *IHeimdallClient) Close() { - _m.Called() +// MockIHeimdallClientMockRecorder is the mock recorder for MockIHeimdallClient. +type MockIHeimdallClientMockRecorder struct { + mock *MockIHeimdallClient } -// Fetch provides a mock function with given fields: path, query -func (_m *IHeimdallClient) Fetch(path string, query string) (*bor.ResponseWithHeight, error) { - ret := _m.Called(path, query) - - var r0 *bor.ResponseWithHeight - if rf, ok := ret.Get(0).(func(string, string) *bor.ResponseWithHeight); ok { - r0 = rf(path, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*bor.ResponseWithHeight) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(path, query) - } else { - r1 = ret.Error(1) - } - - return r0, r1 +// NewMockIHeimdallClient creates a new mock instance. +func NewMockIHeimdallClient(ctrl *gomock.Controller) *MockIHeimdallClient { + mock := &MockIHeimdallClient{ctrl: ctrl} + mock.recorder = &MockIHeimdallClientMockRecorder{mock} + return mock } -// FetchStateSyncEvents provides a mock function with given fields: fromID, to -func (_m *IHeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*bor.EventRecordWithTime, error) { - ret := _m.Called(fromID, to) - - var r0 []*bor.EventRecordWithTime - if rf, ok := ret.Get(0).(func(uint64, int64) []*bor.EventRecordWithTime); ok { - r0 = rf(fromID, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*bor.EventRecordWithTime) - } - } +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIHeimdallClient) EXPECT() *MockIHeimdallClientMockRecorder { + return m.recorder +} - var r1 error - if rf, ok := ret.Get(1).(func(uint64, int64) error); ok { - r1 = rf(fromID, to) - } else { - r1 = ret.Error(1) - } +// Close mocks base method. +func (m *MockIHeimdallClient) Close() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Close") +} - return r0, r1 +// Close indicates an expected call of Close. +func (mr *MockIHeimdallClientMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockIHeimdallClient)(nil).Close)) } -// FetchWithRetry provides a mock function with given fields: path, query -func (_m *IHeimdallClient) FetchWithRetry(path string, query string) (*bor.ResponseWithHeight, error) { - ret := _m.Called(path, query) +// Span mocks base method. +func (m *MockIHeimdallClient) Span(arg0 uint64) (*span.HeimdallSpan, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Span", arg0) + ret0, _ := ret[0].(*span.HeimdallSpan) + ret1, _ := ret[1].(error) + return ret0, ret1 +} - var r0 *bor.ResponseWithHeight - if rf, ok := ret.Get(0).(func(string, string) *bor.ResponseWithHeight); ok { - r0 = rf(path, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*bor.ResponseWithHeight) - } - } +// Span indicates an expected call of Span. +func (mr *MockIHeimdallClientMockRecorder) Span(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Span", reflect.TypeOf((*MockIHeimdallClient)(nil).Span), arg0) +} - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(path, query) - } else { - r1 = ret.Error(1) - } +// StateSyncEvents mocks base method. +func (m *MockIHeimdallClient) StateSyncEvents(arg0 uint64, arg1 int64) ([]*clerk.EventRecordWithTime, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateSyncEvents", arg0, arg1) + ret0, _ := ret[0].([]*clerk.EventRecordWithTime) + ret1, _ := ret[1].(error) + return ret0, ret1 +} - return r0, r1 +// StateSyncEvents indicates an expected call of StateSyncEvents. +func (mr *MockIHeimdallClientMockRecorder) StateSyncEvents(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSyncEvents", reflect.TypeOf((*MockIHeimdallClient)(nil).StateSyncEvents), arg0, arg1) } diff --git a/tests/deps/fake.go b/tests/deps/fake.go new file mode 100644 index 0000000000..cd04ffa070 --- /dev/null +++ b/tests/deps/fake.go @@ -0,0 +1,7 @@ +package deps + +// it is a fake file to lock deps +//nolint:typecheck +import ( + _ "github.com/golang/mock/mockgen/model" +) diff --git a/trie/hasher.go b/trie/hasher.go index 7f0748c13d..c085970a3f 100644 --- a/trie/hasher.go +++ b/trie/hasher.go @@ -19,9 +19,10 @@ package trie import ( "sync" + "golang.org/x/crypto/sha3" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/crypto/sha3" ) // hasher is a type used for the trie Hash operation. A hasher has some From 342bf3089eff489cc0059bf3e8fb2b84e571263c Mon Sep 17 00:00:00 2001 From: Evgeny Danilenko <6655321@bk.ru> Date: Wed, 15 Jun 2022 09:02:01 +0300 Subject: [PATCH 79/80] Merge develop branch into v0.3.0-dev (#430) * merge geth v1.10.15 * fix: Removed FastSync from cli server * fix: TestHeadersRLPStorage * Added t.skip(ETH2 in bor) * fix: flow in create consensus engine * bumped version * Fix typo * increase block time * remove file * bumped version * merge gethv1.10.17 * bumped version * fix failing tests * Bump Go version to v1.18 (#368) * Bump Go version to v1.18.1 * Build using netgo tag This will create a static build using Go native networking stack. Checked and it works stable for all archs and distros. * Fix meta * initial implementation for common ancestor approach * extract whitelist interface * fix types * fix tests and format * add unit tests for IsValidChain function * more tests * wip * test ErrCheckpointMismatch * minor fixes * fix test * dont panic * fmt * Limit state sync by gas * Added logging for state-sync total gas usage * Added number of event-records in log * Minor Changes * Minor Fix * Adding individual gasUsed * Minor Fix * fix: return value for no remote block * handle all errors * modularise fake chain validator in downloader * add more tests * fix tests * Modifying miner.recommit flag and its adjustment function. (#370) * changed min/max/current recommit values * Remove Hardcoded min/max * Code Sanitization * Skipping tests for constant recommit interval * Adding default miner.recommit value * Minor Change * Increased default value of rpc.txfeecap to 5 * add debug rpc endpoints for checkpoint whitelist service * minor fixes and enhancements * avoid capping warnings for gas set by internal system transactions * use typed mocks * fix * fix * fix * fix close * fix * Create stale.yml * Fix bor consensus checkpoint bug Co-authored-by: Arpit Temani Co-authored-by: Shivam Sharma Co-authored-by: Manav Darji Co-authored-by: Sandeep Sreenath Co-authored-by: Victor Castell Co-authored-by: Ferran Co-authored-by: Krishna Upadhyaya Co-authored-by: Karlo Co-authored-by: Sandeep Sreenath Co-authored-by: Jerry --- .github/workflows/stale.yml | 31 +++ consensus/bor/bor.go | 2 + consensus/bor/heimdall.go | 2 + .../bor/heimdall/checkpoint/checkpoint.go | 22 ++ consensus/bor/heimdall/client.go | 21 ++ eth/api_backend.go | 8 + eth/backend.go | 75 ++++++ eth/downloader/downloader.go | 61 ++++- eth/downloader/downloader_test.go | 219 +++++++++++++++--- eth/downloader/queue_test.go | 10 +- eth/downloader/whitelist/service.go | 126 ++++++++++ eth/downloader/whitelist/service_test.go | 107 +++++++++ eth/ethconfig/config.go | 4 +- eth/handler.go | 27 ++- eth/handler_bor.go | 75 ++++++ go.mod | 2 +- internal/ethapi/api.go | 11 + internal/ethapi/backend.go | 2 + internal/ethapi/transaction_args.go | 45 +++- internal/web3ext/web3ext.go | 10 + les/api_backend.go | 15 +- miner/worker.go | 46 ++-- miner/worker_test.go | 5 + tests/bor/bor_test.go | 42 +++- tests/bor/mocks/IHeimdallClient.go | 16 ++ 25 files changed, 898 insertions(+), 86 deletions(-) create mode 100644 .github/workflows/stale.yml create mode 100644 consensus/bor/heimdall/checkpoint/checkpoint.go create mode 100644 eth/downloader/whitelist/service.go create mode 100644 eth/downloader/whitelist/service_test.go create mode 100644 eth/handler_bor.go diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000000..5d5d221eb3 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,31 @@ +# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. +# +# You can adjust the behavior by modifying this file. +# For more information, see: +# https://github.com/actions/stale +name: Mark stale issues and pull requests + +on: + schedule: + - cron: '0 0 * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v5 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 14 days.' + stale-pr-message: 'This PR is stale because it has been open 21 days with no activity. Remove stale label or comment or this will be closed in 14 days.' + close-issue-message: 'This issue was closed because it has been stalled for 28 days with no activity.' + close-pr-message: 'This PR was closed because it has been stalled for 35 days with no activity.' + days-before-issue-stale: 14 + days-before-pr-stale: 21 + days-before-issue-close: 14 + days-before-pr-close: 14 diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 2f087af787..87770f49ab 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1107,6 +1107,8 @@ func (c *Bor) CommitStates( lastStateID++ } + log.Info("StateSyncData", "Gas", totalGas, "Block-number", number, "LastStateID", lastStateID, "TotalRecords", len(eventRecords)) + return stateSyncs, nil } diff --git a/consensus/bor/heimdall.go b/consensus/bor/heimdall.go index c97a3cda11..217de13fe9 100644 --- a/consensus/bor/heimdall.go +++ b/consensus/bor/heimdall.go @@ -2,6 +2,7 @@ package bor import ( "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/span" ) @@ -9,5 +10,6 @@ import ( type IHeimdallClient interface { StateSyncEvents(fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) Span(spanID uint64) (*span.HeimdallSpan, error) + FetchLatestCheckpoint() (*checkpoint.Checkpoint, error) Close() } diff --git a/consensus/bor/heimdall/checkpoint/checkpoint.go b/consensus/bor/heimdall/checkpoint/checkpoint.go new file mode 100644 index 0000000000..77569293ad --- /dev/null +++ b/consensus/bor/heimdall/checkpoint/checkpoint.go @@ -0,0 +1,22 @@ +package checkpoint + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +// Checkpoint defines a response object type of bor checkpoint +type Checkpoint struct { + Proposer common.Address `json:"proposer"` + StartBlock *big.Int `json:"start_block"` + EndBlock *big.Int `json:"end_block"` + RootHash common.Hash `json:"root_hash"` + BorChainID string `json:"bor_chain_id"` + Timestamp uint64 `json:"timestamp"` +} + +type CheckpointResponse struct { + Height string `json:"height"` + Result Checkpoint `json:"result"` +} diff --git a/consensus/bor/heimdall/client.go b/consensus/bor/heimdall/client.go index c5e1dfb4cf..2d42cfc31b 100644 --- a/consensus/bor/heimdall/client.go +++ b/consensus/bor/heimdall/client.go @@ -12,6 +12,7 @@ import ( "time" "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/span" "github.com/ethereum/go-ethereum/log" ) @@ -53,6 +54,7 @@ func NewHeimdallClient(urlString string) *HeimdallClient { const ( fetchStateSyncEventsFormat = "from-id=%d&to-time=%d&limit=%d" fetchStateSyncEventsPath = "clerk/event-record/list" + fetchLatestCheckpoint = "/checkpoints/latest" fetchSpanFormat = "bor/span/%d" ) @@ -108,6 +110,21 @@ func (h *HeimdallClient) Span(spanID uint64) (*span.HeimdallSpan, error) { return &response.Result, nil } +// FetchLatestCheckpoint fetches the latest bor submitted checkpoint from heimdall +func (h *HeimdallClient) FetchLatestCheckpoint() (*checkpoint.Checkpoint, error) { + url, err := latestCheckpointURL(h.urlString) + if err != nil { + return nil, err + } + + response, err := FetchWithRetry[checkpoint.CheckpointResponse](h.client, url, h.closeCh) + if err != nil { + return nil, err + } + + return &response.Result, nil +} + // FetchWithRetry returns data from heimdall with retry func FetchWithRetry[T any](client http.Client, url *url.URL, closeCh chan struct{}) (*T, error) { // attempt counter @@ -171,6 +188,10 @@ func stateSyncURL(urlString string, fromID uint64, to int64) (*url.URL, error) { return makeURL(urlString, fetchStateSyncEventsPath, queryParams) } +func latestCheckpointURL(urlString string) (*url.URL, error) { + return makeURL(urlString, fetchLatestCheckpoint, "") +} + func makeURL(urlString, rawPath, rawQuery string) (*url.URL, error) { u, err := url.Parse(urlString) if err != nil { diff --git a/eth/api_backend.go b/eth/api_backend.go index 6577ac1e1a..c33f3cf6f2 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -359,3 +359,11 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) { return b.eth.stateAtTransaction(block, txIndex, reexec) } + +func (b *EthAPIBackend) GetCheckpointWhitelist() map[uint64]common.Hash { + return b.eth.Downloader().ChainValidator.GetCheckpointWhitelist() +} + +func (b *EthAPIBackend) PurgeCheckpointWhitelist() { + b.eth.Downloader().ChainValidator.PurgeCheckpointWhitelist() +} diff --git a/eth/backend.go b/eth/backend.go index 03419cde45..0b8a956cfa 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -101,6 +101,8 @@ type Ethereum struct { lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) + closeCh chan struct{} // Channel to signal the background processes to exit + shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully } @@ -163,6 +165,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), p2pServer: stack.Server(), + closeCh: make(chan struct{}), shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), } @@ -254,6 +257,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { BloomCache: uint64(cacheLimit), EventMux: eth.eventMux, Checkpoint: checkpoint, + EthAPI: ethAPI, PeerRequiredBlocks: config.PeerRequiredBlocks, }); err != nil { return nil, err @@ -608,9 +612,77 @@ func (s *Ethereum) Start() error { } maxPeers -= s.config.LightPeers } + // Start the networking layer and the light server if requested s.handler.Start(maxPeers) + go s.startCheckpointWhitelistService() + + return nil +} + +// StartCheckpointWhitelistService starts the goroutine to fetch checkpoints and update the +// checkpoint whitelist map. +func (s *Ethereum) startCheckpointWhitelistService() { + // a shortcut helps with tests and early exit + select { + case <-s.closeCh: + return + default: + } + + // first run the checkpoint whitelist + err := s.handleWhitelistCheckpoint() + if err != nil { + if errors.Is(err, ErrBorConsensusWithoutHeimdall) || errors.Is(err, ErrNotBorConsensus) { + return + } + + log.Warn("unable to whitelist checkpoint - first run", "err", err) + } + + ticker := time.NewTicker(100 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + err := s.handleWhitelistCheckpoint() + if err != nil { + log.Warn("unable to whitelist checkpoint", "err", err) + } + case <-s.closeCh: + return + } + } +} + +var ( + ErrNotBorConsensus = errors.New("not bor consensus was given") + ErrBorConsensusWithoutHeimdall = errors.New("bor consensus without heimdall") +) + +// handleWhitelistCheckpoint handles the checkpoint whitelist mechanism. +func (s *Ethereum) handleWhitelistCheckpoint() error { + ethHandler := (*ethHandler)(s.handler) + + bor, ok := ethHandler.chain.Engine().(*bor.Bor) + if !ok { + return ErrNotBorConsensus + } + + if bor.HeimdallClient == nil { + return ErrBorConsensusWithoutHeimdall + } + + endBlockNum, endBlockHash, err := ethHandler.fetchWhitelistCheckpoint(bor) + if err != nil { + return err + } + + // Update the checkpoint whitelist map. + ethHandler.downloader.ProcessCheckpoint(endBlockNum, endBlockHash) + return nil } @@ -626,6 +698,9 @@ func (s *Ethereum) Stop() error { s.bloomIndexer.Close() close(s.closeBloomHandler) + // Close all bg processes + close(s.closeCh) + // closing consensus engine first, as miner has deps on it s.engine.Close() s.txPool.Stop() diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 1e68746f97..1a9d815ccd 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/downloader/whitelist" "github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" @@ -143,6 +144,8 @@ type Downloader struct { quitCh chan struct{} // Quit channel to signal termination quitLock sync.Mutex // Lock to prevent double closes + ChainValidator + // Testing hooks syncInitHook func(uint64, uint64) // Method to call upon initiating a new sync run bodyFetchHook func([]*types.Header) // Method to call upon starting a block body fetch @@ -150,6 +153,14 @@ type Downloader struct { chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations) } +// interface for whitelist service +type ChainValidator interface { + IsValidChain(remoteHeader *types.Header, fetchHeadersByNumber func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) + ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash) + GetCheckpointWhitelist() map[uint64]common.Hash + PurgeCheckpointWhitelist() +} + // LightChain encapsulates functions required to synchronise a light chain. type LightChain interface { // HasHeader verifies a header's presence in the local chain. @@ -204,7 +215,8 @@ type BlockChain interface { } // New creates a new downloader to fetch hashes and blocks from remote peers. -func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, success func()) *Downloader { +//nolint: staticcheck +func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, success func(), whitelistService ChainValidator) *Downloader { if lightchain == nil { lightchain = chain } @@ -221,6 +233,7 @@ func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain Bl quitCh: make(chan struct{}), SnapSyncer: snap.NewSyncer(stateDb), stateSyncStart: make(chan *stateSync), + ChainValidator: whitelistService, } dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success)) @@ -332,9 +345,11 @@ func (d *Downloader) LegacySync(id string, head common.Hash, td, ttd *big.Int, m case nil, errBusy, errCanceled: return err } + 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, 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) if d.dropPeer == nil { // The dropPeer method is nil when `--copydb` is used for a local copy. @@ -345,10 +360,17 @@ func (d *Downloader) LegacySync(id string, head common.Hash, td, ttd *big.Int, m } return err } + if errors.Is(err, ErrMergeTransition) { return err // This is an expected fault, don't keep printing it in a spin-loop } - log.Warn("Synchronisation failed, retrying", "err", err) + + if errors.Is(err, whitelist.ErrNoRemoteCheckoint) { + log.Warn("Doesn't have remote checkpoint yet", "peer", id, "err", err) + } + + log.Warn("Synchronisation failed, retrying", "peer", id, "err", err) + return err } @@ -764,12 +786,24 @@ func calculateRequestSpan(remoteHeight, localHeight uint64) (int64, int, int, ui return int64(from), count, span - 1, uint64(max) } +// curried fetchHeadersByNumber +func (d *Downloader) getFetchHeadersByNumber(p *peerConnection) func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error) { + return func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error) { + return d.fetchHeadersByNumber(p, number, amount, skip, reverse) + } +} + // findAncestor tries to locate the common ancestor link of the local chain and // a remote peers blockchain. In the general case when our node was in sync and // on the correct chain, checking the top N links should already get us a match. // 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. func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) (uint64, error) { + // Check the validity of chain to be downloaded + if _, err := d.IsValidChain(remoteHeader, d.getFetchHeadersByNumber(p)); err != nil { + return 0, err + } + // Figure out the valid ancestor range to prevent rewrite attacks var ( floor = int64(-1) @@ -1346,6 +1380,7 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode if chunkHeaders[len(chunkHeaders)-1].Number.Uint64()+uint64(fsHeaderForceVerify) > pivot { frequency = 1 } + // Although the received headers might be all valid, a legacy // PoW/PoA sync must not accept post-merge headers. Make sure // that any transition is rejected at this point. @@ -1353,13 +1388,16 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode rejected []*types.Header td *big.Int ) + if !beaconMode && ttd != nil { td = d.blockchain.GetTd(chunkHeaders[0].ParentHash, chunkHeaders[0].Number.Uint64()-1) if td == nil { // This should never really happen, but handle gracefully for now log.Error("Failed to retrieve parent header TD", "number", chunkHeaders[0].Number.Uint64()-1, "hash", chunkHeaders[0].ParentHash) + return fmt.Errorf("%w: parent TD missing", errInvalidChain) } + for i, header := range chunkHeaders { td = new(big.Int).Add(td, header.Difficulty) if td.Cmp(ttd) >= 0 { @@ -1373,10 +1411,12 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode } else { chunkHeaders, rejected = chunkHeaders[:i], chunkHeaders[i:] } + break } } } + if len(chunkHeaders) > 0 { if n, err := d.lightchain.InsertHeaderChain(chunkHeaders, frequency); err != nil { rollbackErr = err @@ -1385,12 +1425,15 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode if (mode == SnapSync || frequency > 1) && n > 0 && rollback == 0 { rollback = chunkHeaders[0].Number.Uint64() } + log.Warn("Invalid header encountered", "number", chunkHeaders[n].Number, "hash", chunkHashes[n], "parent", chunkHeaders[n].ParentHash, "err", err) + return fmt.Errorf("%w: %v", errInvalidChain, err) } // All verifications passed, track all headers within the allowed limits if mode == SnapSync { head := chunkHeaders[len(chunkHeaders)-1].Number.Uint64() + if head-rollback > uint64(fsHeaderSafetyNet) { rollback = head - uint64(fsHeaderSafetyNet) } else { @@ -1398,14 +1441,26 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode } } } + + if len(rejected) != 0 { + // Merge threshold reached, stop importing, but don't roll back + rollback = 0 + + log.Info("Legacy sync reached merge threshold", "number", rejected[0].Number, "hash", rejected[0].Hash(), "td", td, "ttd", ttd) + + return ErrMergeTransition + } + if len(rejected) != 0 { // Merge threshold reached, stop importing, but don't roll back rollback = 0 log.Info("Legacy sync reached merge threshold", "number", rejected[0].Number, "hash", rejected[0].Hash(), "td", td, "ttd", ttd) + return ErrMergeTransition } } + // Unless we're doing light chains, schedule the headers for associated content retrieval if mode == FullSync || mode == SnapSync { // If we've reached the allowed number of pending headers, stall a bit diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 6989252c11..37b07424dd 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/downloader/whitelist" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/event" @@ -42,6 +43,8 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" + + "github.com/stretchr/testify/assert" ) // downloadTester is a test simulator for mocking out local block chain. @@ -60,25 +63,35 @@ func newTester() *downloadTester { if err != nil { panic(err) } + db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false) if err != nil { panic(err) } + core.GenesisBlockForTesting(db, testAddress, big.NewInt(1000000000000000)) chain, err := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil) if err != nil { panic(err) } + tester := &downloadTester{ freezer: freezer, chain: chain, peers: make(map[string]*downloadTesterPeer), } - tester.downloader = New(0, db, new(event.TypeMux), tester.chain, nil, tester.dropPeer, nil) + + //nolint: staticcheck + tester.downloader = New(0, db, new(event.TypeMux), tester.chain, nil, tester.dropPeer, nil, whitelist.NewService(10)) + return tester } +func (dl *downloadTester) setWhitelist(w ChainValidator) { + dl.downloader.ChainValidator = w +} + // terminate aborts any operations on the embedded downloader and releases all // held resources. func (dl *downloadTester) terminate() { @@ -155,7 +168,7 @@ func (dlp *downloadTesterPeer) Head() (common.Hash, *big.Int) { } func unmarshalRlpHeaders(rlpdata []rlp.RawValue) []*types.Header { - var headers = make([]*types.Header, len(rlpdata)) + headers := make([]*types.Header, len(rlpdata)) for i, data := range rlpdata { var h types.Header if err := rlp.DecodeBytes(data, &h); err != nil { @@ -620,6 +633,7 @@ func TestBoundedHeavyForkedSync66Full(t *testing.T) { func TestBoundedHeavyForkedSync66Snap(t *testing.T) { testBoundedHeavyForkedSync(t, eth.ETH66, SnapSync) } + func TestBoundedHeavyForkedSync66Light(t *testing.T) { testBoundedHeavyForkedSync(t, eth.ETH66, LightSync) } @@ -711,7 +725,7 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) { // Create peers of every type tester.newPeer("peer 66", eth.ETH66, chain.blocks[1:]) - //tester.newPeer("peer 65", eth.ETH67, chain.blocks[1:) + // tester.newPeer("peer 65", eth.ETH67, chain.blocks[1:) // Synchronise with the requested peer and make sure all blocks were retrieved if err := tester.sync(fmt.Sprintf("peer %d", protocol), nil, mode); err != nil { @@ -916,6 +930,7 @@ func TestHighTDStarvationAttack66Full(t *testing.T) { func TestHighTDStarvationAttack66Snap(t *testing.T) { testHighTDStarvationAttack(t, eth.ETH66, SnapSync) } + func TestHighTDStarvationAttack66Light(t *testing.T) { testHighTDStarvationAttack(t, eth.ETH66, LightSync) } @@ -1268,36 +1283,45 @@ func TestRemoteHeaderRequestSpan(t *testing.T) { expected []int }{ // Remote is way higher. We should ask for the remote head and go backwards - {1500, 1000, + { + 1500, 1000, []int{1323, 1339, 1355, 1371, 1387, 1403, 1419, 1435, 1451, 1467, 1483, 1499}, }, - {15000, 13006, + { + 15000, 13006, []int{14823, 14839, 14855, 14871, 14887, 14903, 14919, 14935, 14951, 14967, 14983, 14999}, }, // Remote is pretty close to us. We don't have to fetch as many - {1200, 1150, + { + 1200, 1150, []int{1149, 1154, 1159, 1164, 1169, 1174, 1179, 1184, 1189, 1194, 1199}, }, // Remote is equal to us (so on a fork with higher td) // We should get the closest couple of ancestors - {1500, 1500, + { + 1500, 1500, []int{1497, 1499}, }, // We're higher than the remote! Odd - {1000, 1500, + { + 1000, 1500, []int{997, 999}, }, // Check some weird edgecases that it behaves somewhat rationally - {0, 1500, + { + 0, 1500, []int{0, 2}, }, - {6000000, 0, + { + 6000000, 0, []int{5999823, 5999839, 5999855, 5999871, 5999887, 5999903, 5999919, 5999935, 5999951, 5999967, 5999983, 5999999}, }, - {0, 0, + { + 0, 0, []int{0, 2}, }, } + reqs := func(from, count, span int) []int { var r []int num := from @@ -1307,32 +1331,39 @@ func TestRemoteHeaderRequestSpan(t *testing.T) { } return r } + for i, tt := range testCases { - from, count, span, max := calculateRequestSpan(tt.remoteHeight, tt.localHeight) - data := reqs(int(from), count, span) + i := i + tt := tt - if max != uint64(data[len(data)-1]) { - t.Errorf("test %d: wrong last value %d != %d", i, data[len(data)-1], max) - } - failed := false - if len(data) != len(tt.expected) { - failed = true - t.Errorf("test %d: length wrong, expected %d got %d", i, len(tt.expected), len(data)) - } else { - for j, n := range data { - if n != tt.expected[j] { - failed = true - break + t.Run("", func(t *testing.T) { + from, count, span, max := calculateRequestSpan(tt.remoteHeight, tt.localHeight) + data := reqs(int(from), count, span) + + if max != uint64(data[len(data)-1]) { + t.Errorf("test %d: wrong last value %d != %d", i, data[len(data)-1], max) + } + failed := false + if len(data) != len(tt.expected) { + failed = true + t.Errorf("test %d: length wrong, expected %d got %d", i, len(tt.expected), len(data)) + } else { + for j, n := range data { + if n != tt.expected[j] { + failed = true + break + } } } - } - if failed { - res := strings.Replace(fmt.Sprint(data), " ", ",", -1) - exp := strings.Replace(fmt.Sprint(tt.expected), " ", ",", -1) - t.Logf("got: %v\n", res) - t.Logf("exp: %v\n", exp) - t.Errorf("test %d: wrong values", i) - } + + if failed { + res := strings.Replace(fmt.Sprint(data), " ", ",", -1) + exp := strings.Replace(fmt.Sprint(tt.expected), " ", ",", -1) + t.Logf("got: %v\n", res) + t.Logf("exp: %v\n", exp) + t.Errorf("test %d: wrong values", i) + } + }) } } @@ -1359,12 +1390,134 @@ func testCheckpointEnforcement(t *testing.T, protocol uint, mode SyncMode) { if mode == SnapSync || mode == LightSync { expect = errUnsyncedPeer } + if err := tester.sync("peer", nil, mode); !errors.Is(err, expect) { t.Fatalf("block sync error mismatch: have %v, want %v", err, expect) } + if mode == SnapSync || mode == LightSync { assertOwnChain(t, tester, 1) } else { assertOwnChain(t, tester, len(chain.blocks)) } } + +// whitelistFake is a mock for the chain validator service +type whitelistFake struct { + // count denotes the number of times the validate function was called + count int + + // validate is the dynamic function to be called while syncing + validate func(count int) (bool, error) +} + +// newWhitelistFake returns a new mock whitelist +func newWhitelistFake(validate func(count int) (bool, error)) *whitelistFake { + return &whitelistFake{0, validate} +} + +// IsValidChain is the mock function which the downloader will use to validate the chain +// to be received from a peer. +func (w *whitelistFake) IsValidChain(_ *types.Header, _ func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error)) (bool, error) { + defer func() { + w.count++ + }() + + return w.validate(w.count) +} + +func (w *whitelistFake) ProcessCheckpoint(_ uint64, _ common.Hash) {} + +func (w *whitelistFake) GetCheckpointWhitelist() map[uint64]common.Hash { + return nil +} + +func (w *whitelistFake) PurgeCheckpointWhitelist() {} + +// TestFakedSyncProgress66WhitelistMismatch tests if in case of whitelisted +// checkpoint mismatch with opposite peer, the sync should fail. +func TestFakedSyncProgress66WhitelistMismatch(t *testing.T) { + t.Parallel() + + protocol := uint(eth.ETH66) + mode := FullSync + + tester := newTester() + validate := func(count int) (bool, error) { + return false, whitelist.ErrCheckpointMismatch + } + tester.downloader.ChainValidator = newWhitelistFake(validate) + + defer tester.terminate() + + chainA := testChainForkLightA.blocks + tester.newPeer("light", protocol, chainA[1:]) + + // Synchronise with the peer and make sure all blocks were retrieved + if err := tester.sync("light", nil, mode); err == nil { + t.Fatal("succeeded attacker synchronisation") + } +} + +// TestFakedSyncProgress66WhitelistMatch tests if in case of whitelisted +// checkpoint match with opposite peer, the sync should succeed. +func TestFakedSyncProgress66WhitelistMatch(t *testing.T) { + t.Parallel() + + protocol := uint(eth.ETH66) + mode := FullSync + + tester := newTester() + validate := func(count int) (bool, error) { + return true, nil + } + tester.downloader.ChainValidator = newWhitelistFake(validate) + + defer tester.terminate() + + chainA := testChainForkLightA.blocks + tester.newPeer("light", protocol, chainA[1:]) + + // Synchronise with the peer and make sure all blocks were retrieved + if err := tester.sync("light", nil, mode); err != nil { + t.Fatal("succeeded attacker synchronisation") + } +} + +// TestFakedSyncProgress66NoRemoteCheckpoint tests if in case of missing/invalid +// checkpointed blocks with opposite peer, the sync should fail initially but +// with the retry mechanism, it should succeed eventually. +func TestFakedSyncProgress66NoRemoteCheckpoint(t *testing.T) { + t.Parallel() + + protocol := uint(eth.ETH66) + mode := FullSync + + tester := newTester() + validate := func(count int) (bool, error) { + // only return the `ErrNoRemoteCheckoint` error for the first call + if count == 0 { + return false, whitelist.ErrNoRemoteCheckoint + } + + return true, nil + } + + tester.downloader.ChainValidator = newWhitelistFake(validate) + + defer tester.terminate() + + chainA := testChainForkLightA.blocks + tester.newPeer("light", protocol, chainA[1:]) + + // Synchronise with the peer and make sure all blocks were retrieved + // Should fail in first attempt + if err := tester.sync("light", nil, mode); err != nil { + assert.Equal(t, whitelist.ErrNoRemoteCheckoint, err, "failed synchronisation") + } + + // Try syncing again, should succeed + if err := tester.sync("light", nil, mode); err != nil { + t.Fatal("succeeded attacker synchronisation") + } +} diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go index f729def671..872bfcd1a9 100644 --- a/eth/downloader/queue_test.go +++ b/eth/downloader/queue_test.go @@ -64,8 +64,11 @@ type chainData struct { offset int } -var chain *chainData -var emptyChain *chainData +var ( + chain *chainData + chainLongerFork *chainData + emptyChain *chainData +) func init() { // Create a chain of blocks to import @@ -75,6 +78,9 @@ func init() { blocks, _ = makeChain(targetBlocks, 0, genesis, true) emptyChain = &chainData{blocks, 0} + + chainLongerForkBlocks, _ := makeChain(1024, 0, blocks[len(blocks)-1], false) + chainLongerFork = &chainData{chainLongerForkBlocks, 0} } func (chain *chainData) headers() []*types.Header { diff --git a/eth/downloader/whitelist/service.go b/eth/downloader/whitelist/service.go new file mode 100644 index 0000000000..7036f24a8f --- /dev/null +++ b/eth/downloader/whitelist/service.go @@ -0,0 +1,126 @@ +package whitelist + +import ( + "errors" + "fmt" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" +) + +// 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 +} + +func NewService(maxCapacity uint) *Service { + return &Service{ + checkpointWhitelist: make(map[uint64]common.Hash), + checkpointOrder: []uint64{}, + maxCapacity: maxCapacity, + } +} + +var ( + ErrCheckpointMismatch = errors.New("checkpoint mismatch") + ErrNoRemoteCheckoint = errors.New("remote peer doesn't have a checkoint") +) + +// IsValidChain checks if the chain we're about to receive from this peer is valid or not +// in terms of reorgs. We won't reorg beyond the last bor checkpoint submitted to mainchain. +func (w *Service) IsValidChain(remoteHeader *types.Header, 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 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", ErrNoRemoteCheckoint, lastCheckpointBlockNum, err) + } + + if len(headers) == 0 { + return false, fmt.Errorf("%w: last checkpoint %d", ErrNoRemoteCheckoint, 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 +} + +func (w *Service) ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash) { + w.m.Lock() + defer w.m.Unlock() + + w.enqueueCheckpointWhitelist(endBlockNum, endBlockHash) + // If size of checkpoint whitelist map is greater than 10, remove the oldest entry. + + if w.length() > int(w.maxCapacity) { + w.dequeueCheckpointWhitelist() + } +} + +// GetCheckpointWhitelist returns the existing whitelisted +// 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 +} + +// PurgeCheckpointWhitelist purges data from checkpoint whitelist map +func (w *Service) PurgeCheckpointWhitelist() { + w.m.Lock() + 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 +func (w *Service) dequeueCheckpointWhitelist() { + 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]) + w.checkpointOrder = w.checkpointOrder[1:] + } +} + +// length returns the len of the whitelist. +func (w *Service) length() int { + return len(w.checkpointWhitelist) +} diff --git a/eth/downloader/whitelist/service_test.go b/eth/downloader/whitelist/service_test.go new file mode 100644 index 0000000000..ca202cc3ad --- /dev/null +++ b/eth/downloader/whitelist/service_test.go @@ -0,0 +1,107 @@ +package whitelist + +import ( + "errors" + "math/big" + "testing" + + "gotest.tools/assert" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// NewMockService creates a new mock whitelist service +func NewMockService(maxCapacity uint) *Service { + return &Service{ + checkpointWhitelist: make(map[uint64]common.Hash), + checkpointOrder: []uint64{}, + maxCapacity: maxCapacity, + } +} + +// TestWhitelistCheckpoint checks the checkpoint whitelist map queue mechanism +func TestWhitelistCheckpoint(t *testing.T) { + t.Parallel() + + s := NewMockService(10) + for i := 0; i < 10; i++ { + s.enqueueCheckpointWhitelist(uint64(i), common.Hash{}) + } + assert.Equal(t, s.length(), 10, "expected 10 items in whitelist") + + s.enqueueCheckpointWhitelist(11, common.Hash{}) + s.dequeueCheckpointWhitelist() + assert.Equal(t, s.length(), 10, "expected 10 items in whitelist") +} + +// TestIsValidChain checks che IsValidChain function in isolation +// for different cases by providing a mock fetchHeadersByNumber function +func TestIsValidChain(t *testing.T) { + t.Parallel() + + s := NewMockService(10) + + // case1: no checkpoint whitelist, should consider the chain as valid + res, err := s.IsValidChain(nil, nil) + assert.NilError(t, err, "expected no error") + assert.Equal(t, res, true, "expected chain to be valid") + + // add checkpoint entries and mock fetchHeadersByNumber function + s.ProcessCheckpoint(uint64(0), common.Hash{}) + s.ProcessCheckpoint(uint64(1), common.Hash{}) + + assert.Equal(t, s.length(), 2, "expected 2 items in whitelist") + + // create a false function, returning absolutely nothing + falseFetchHeadersByNumber := func(number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error) { + return nil, nil, nil + } + + // case2: false fetchHeadersByNumber function provided, should consider the chain as invalid + // and throw `ErrNoRemoteCheckoint` error + res, err = s.IsValidChain(nil, falseFetchHeadersByNumber) + if err == nil { + t.Fatal("expected error, got nil") + } + + if !errors.Is(err, ErrNoRemoteCheckoint) { + t.Fatalf("expected error ErrNoRemoteCheckoint, got %v", err) + } + + assert.Equal(t, res, false, "expected chain to be invalid") + + // case3: correct fetchHeadersByNumber function provided, should consider the chain as valid + // create a mock function, returning a 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(1) // sending wrong header for misamatch + return []*types.Header{&header}, []common.Hash{hash}, nil + default: + return nil, nil, errors.New("invalid number") + } + } + + res, err = s.IsValidChain(nil, fetchHeadersByNumber) + assert.NilError(t, err, "expected no error") + assert.Equal(t, res, true, "expected chain to be valid") + + // add one more checkpoint whitelist entry + s.ProcessCheckpoint(uint64(2), common.Hash{}) + assert.Equal(t, s.length(), 3, "expected 3 items in whitelist") + + // case4: correct fetchHeadersByNumber function provided with wrong header + // for block number 2. Should consider the chain as invalid and throw an error + res, err = s.IsValidChain(nil, fetchHeadersByNumber) + assert.Equal(t, err, ErrCheckpointMismatch, "expected checkpoint mismatch error") + assert.Equal(t, res, false, "expected chain to be invalid") +} diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 904fb2cbc2..a3c7f49e39 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -91,13 +91,13 @@ var Defaults = Config{ Miner: miner.Config{ GasCeil: 8000000, GasPrice: big.NewInt(params.GWei), - Recommit: 3 * time.Second, + Recommit: 125 * time.Second, }, TxPool: core.DefaultTxPoolConfig, RPCGasCap: 50000000, RPCEVMTimeout: 5 * time.Second, GPO: FullNodeGPO, - RPCTxFeeCap: 1, // 1 ether + RPCTxFeeCap: 5, // 5 matic } func init() { diff --git a/eth/handler.go b/eth/handler.go index 40edfa2d17..ab95f5f769 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -31,11 +31,13 @@ import ( "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/downloader" + "github.com/ethereum/go-ethereum/eth/downloader/whitelist" "github.com/ethereum/go-ethereum/eth/fetcher" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" @@ -77,15 +79,16 @@ type txPool interface { // handlerConfig is the collection of initialization parameters to create a full // node network handler. type handlerConfig struct { - Database ethdb.Database // Database for direct sync insertions - Chain *core.BlockChain // Blockchain to serve data from - TxPool txPool // Transaction pool to propagate from - Merger *consensus.Merger // The manager for eth1/2 transition - Network uint64 // Network identifier to adfvertise - Sync downloader.SyncMode // Whether to snap or full sync - BloomCache uint64 // Megabytes to alloc for snap sync bloom - EventMux *event.TypeMux // Legacy event mux, deprecate for `feed` - Checkpoint *params.TrustedCheckpoint // Hard coded checkpoint for sync challenges + Database ethdb.Database // Database for direct sync insertions + Chain *core.BlockChain // Blockchain to serve data from + TxPool txPool // Transaction pool to propagate from + Merger *consensus.Merger // The manager for eth1/2 transition + Network uint64 // Network identifier to adfvertise + Sync downloader.SyncMode // Whether to snap or full sync + BloomCache uint64 // Megabytes to alloc for snap sync bloom + EventMux *event.TypeMux //nolint:staticcheck // Legacy event mux, deprecate for `feed` + Checkpoint *params.TrustedCheckpoint // Hard coded checkpoint for sync challenges + EthAPI *ethapi.PublicBlockChainAPI // EthAPI to interact PeerRequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges } @@ -111,6 +114,8 @@ type handler struct { peers *peerSet merger *consensus.Merger + ethAPI *ethapi.PublicBlockChainAPI // EthAPI to interact + eventMux *event.TypeMux txsCh chan core.NewTxsEvent txsSub event.Subscription @@ -141,6 +146,7 @@ func newHandler(config *handlerConfig) (*handler, error) { chain: config.Chain, peers: newPeerSet(), merger: config.Merger, + ethAPI: config.EthAPI, peerRequiredBlocks: config.PeerRequiredBlocks, quitSync: make(chan struct{}), } @@ -195,7 +201,8 @@ func newHandler(config *handlerConfig) (*handler, error) { // Construct the downloader (long sync) and its backing state bloom if snap // sync is requested. The downloader is responsible for deallocating the state // bloom when it's done. - h.downloader = downloader.New(h.checkpointNumber, config.Database, h.eventMux, h.chain, nil, h.removePeer, success) + // todo: it'd better to extract maxCapacity into config + h.downloader = downloader.New(h.checkpointNumber, config.Database, h.eventMux, h.chain, nil, h.removePeer, success, whitelist.NewService(10)) // Construct the fetcher (short sync) validator := func(header *types.Header) error { diff --git a/eth/handler_bor.go b/eth/handler_bor.go new file mode 100644 index 0000000000..11896f3c47 --- /dev/null +++ b/eth/handler_bor.go @@ -0,0 +1,75 @@ +package eth + +import ( + "context" + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" +) + +var ( + // errCheckpoint is returned when we are unable to fetch the + // latest checkpoint from the local heimdall. + errCheckpoint = errors.New("failed to fetch latest checkpoint") + + // errMissingCheckpoint is returned when we don't have the + // checkpoint blocks locally, yet. + errMissingCheckpoint = errors.New("missing checkpoint 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") + + // 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") +) + +// fetchWhitelistCheckpoint fetched the latest checkpoint from it's local heimdall +// and verifies the data against bor data. +func (h *ethHandler) fetchWhitelistCheckpoint(bor *bor.Bor) (uint64, common.Hash, error) { + // check for checkpoint whitelisting: bor + checkpoint, err := bor.HeimdallClient.FetchLatestCheckpoint() + if err != nil { + log.Debug("Failed to fetch latest checkpoint for whitelisting") + return 0, common.Hash{}, errCheckpoint + } + + // check if we have the checkpoint blocks + head := h.ethAPI.BlockNumber() + if head < hexutil.Uint64(checkpoint.EndBlock.Uint64()) { + log.Debug("Head block behind checkpoint block", "head", head, "checkpoint end block", checkpoint.EndBlock) + return 0, common.Hash{}, errMissingCheckpoint + } + + // verify the root hash of checkpoint + roothash, err := h.ethAPI.GetRootHash(context.Background(), checkpoint.StartBlock.Uint64(), checkpoint.EndBlock.Uint64()) + if err != nil { + log.Debug("Failed to get root hash of checkpoint while whitelisting") + return 0, common.Hash{}, errRootHash + } + + if roothash != checkpoint.RootHash.String()[2:] { + log.Warn("Checkpoint root hash mismatch while whitelisting", "expected", checkpoint.RootHash.String()[2:], "got", roothash) + return 0, common.Hash{}, errCheckpointRootHashMismatch + } + + // fetch the end checkpoint block hash + block, err := h.ethAPI.GetBlockByNumber(context.Background(), rpc.BlockNumber(checkpoint.EndBlock.Uint64()), false) + if err != nil { + log.Debug("Failed to get end block hash of checkpoint while whitelisting") + return 0, common.Hash{}, errEndBlock + } + + hash := fmt.Sprintf("%v", block["hash"]) + + return checkpoint.EndBlock.Uint64(), common.HexToHash(hash), nil +} diff --git a/go.mod b/go.mod index 852c895e3b..1b452a67a1 100644 --- a/go.mod +++ b/go.mod @@ -76,6 +76,7 @@ require ( gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 gopkg.in/urfave/cli.v1 v1.20.0 + gotest.tools v2.2.0+incompatible pgregory.net/rapid v0.4.7 ) @@ -135,5 +136,4 @@ require ( google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - gotest.tools v2.2.0+incompatible // indirect ) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 15536d5d72..59b6feba52 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -2156,6 +2156,17 @@ func (api *PrivateDebugAPI) SetHead(number hexutil.Uint64) { api.b.SetHead(uint64(number)) } +// GetCheckpointWhitelist retrieves the current checkpoint whitelist +// entries (of the form block number -> block hash) +func (api *PrivateDebugAPI) GetCheckpointWhitelist() map[uint64]common.Hash { + return api.b.GetCheckpointWhitelist() +} + +// PurgeCheckpointWhitelist purges the current checkpoint whitelist entries +func (api *PrivateDebugAPI) PurgeCheckpointWhitelist() { + api.b.PurgeCheckpointWhitelist() +} + // PublicNetAPI offers network related RPC methods type PublicNetAPI struct { net *p2p.Server diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 97ce7c24cf..1287640b83 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -99,6 +99,8 @@ type Backend interface { 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) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription + GetCheckpointWhitelist() map[uint64]common.Hash + PurgeCheckpointWhitelist() ChainConfig() *params.ChainConfig Engine() consensus.Engine diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 9c5950af58..aa2596fe81 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -59,6 +59,7 @@ func (args *TransactionArgs) from() common.Address { if args.From == nil { return common.Address{} } + return *args.From } @@ -67,9 +68,11 @@ func (args *TransactionArgs) data() []byte { if args.Input != nil { return *args.Input } + if args.Data != nil { return *args.Data } + return nil } @@ -78,8 +81,10 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error { if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } + // After london, default to 1559 unless gasPrice is set head := b.CurrentHeader() + // If user specifies both maxPriorityfee and maxFee, then we do not // need to consult the chain for defaults. It's definitely a London tx. if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil { @@ -90,6 +95,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error { if err != nil { return err } + args.MaxPriorityFeePerGas = (*hexutil.Big)(tip) } if args.MaxFeePerGas == nil { @@ -97,8 +103,10 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error { (*big.Int)(args.MaxPriorityFeePerGas), new(big.Int).Mul(head.BaseFee, big.NewInt(2)), ) + args.MaxFeePerGas = (*hexutil.Big)(gasFeeCap) } + if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 { return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas) } @@ -106,17 +114,20 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error { if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil { return errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet") } + if args.GasPrice == nil { price, err := b.SuggestGasTipCap(ctx) if err != nil { return err } + if b.ChainConfig().IsLondon(head.Number) { // The legacy tx gas price suggestion should not add 2x base fee // because all fees are consumed, so it would result in a spiral // upwards. price.Add(price, head.BaseFee) } + args.GasPrice = (*hexutil.Big)(price) } } @@ -126,22 +137,28 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error { return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas) } } + if args.Value == nil { args.Value = new(hexutil.Big) } + if args.Nonce == nil { nonce, err := b.GetPoolNonce(ctx, args.from()) if err != nil { return err } + args.Nonce = (*hexutil.Uint64)(&nonce) } + if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) { return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`) } + if args.To == nil && len(args.data()) == 0 { return errors.New(`contract creation without any data provided`) } + // Estimate the gas usage if necessary. if args.Gas == nil { // These fields are immutable during the estimation, safe to @@ -157,18 +174,23 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error { Data: (*hexutil.Bytes)(&data), AccessList: args.AccessList, } + pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) + estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, b.RPCGasCap()) if err != nil { return err } + args.Gas = &estimated log.Trace("Estimate gas usage automatically", "gas", args.Gas) } + if args.ChainID == nil { id := (*hexutil.Big)(b.ChainConfig().ChainID) args.ChainID = id } + return nil } @@ -180,32 +202,41 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { return types.Message{}, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } + // Set sender address or use zero address if none specified. addr := args.from() + // Gas set for system calls + systemCallGas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + // Set default gas & gas price if none were set gas := globalGasCap if gas == 0 { gas = uint64(math.MaxUint64 / 2) } - if args.Gas != nil { + + if args.Gas != nil && *args.Gas != systemCallGas { gas = uint64(*args.Gas) } + if globalGasCap != 0 && globalGasCap < gas { log.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) gas = globalGasCap } + var ( gasPrice *big.Int gasFeeCap *big.Int gasTipCap *big.Int ) + if baseFee == nil { // If there's no basefee, then it must be a non-1559 execution gasPrice = new(big.Int) if args.GasPrice != nil { gasPrice = args.GasPrice.ToInt() } + gasFeeCap, gasTipCap = gasPrice, gasPrice } else { // A basefee is provided, necessitating 1559-type execution @@ -216,30 +247,40 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t } else { // User specified 1559 gas feilds (or none), use those gasFeeCap = new(big.Int) + if args.MaxFeePerGas != nil { gasFeeCap = args.MaxFeePerGas.ToInt() } + gasTipCap = new(big.Int) + if args.MaxPriorityFeePerGas != nil { gasTipCap = args.MaxPriorityFeePerGas.ToInt() } + // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes gasPrice = new(big.Int) + if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 { gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap) } } } + value := new(big.Int) if args.Value != nil { value = args.Value.ToInt() } + data := args.data() + var accessList types.AccessList if args.AccessList != nil { accessList = *args.AccessList } + msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true) + return msg, nil } @@ -247,6 +288,7 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t // This assumes that setDefaults has been called. func (args *TransactionArgs) toTransaction() *types.Transaction { var data types.TxData + switch { case args.MaxFeePerGas != nil: al := types.AccessList{} @@ -285,6 +327,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction { Data: args.data(), } } + return types.NewTx(data) } diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index dd8b34e025..dcdd5baf23 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -474,6 +474,16 @@ web3._extend({ params: 2, inputFormatter:[web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter], }), + new web3._extend.Method({ + name: 'getCheckpointWhitelist', + call: 'debug_getCheckpointWhitelist', + params: 0, + }), + new web3._extend.Method({ + name: 'purgeCheckpointWhitelist', + call: 'debug_purgeCheckpointWhitelist', + params: 0, + }), ], properties: [] }); diff --git a/les/api_backend.go b/les/api_backend.go index e9e51c4ecc..c716a3967f 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -337,17 +337,24 @@ func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Blo // 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) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) { - return nil, errors.New("Not implemented") + return nil, errors.New("not implemented") } func (b *LesApiBackend) GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { - return nil, common.Hash{}, 0, 0, errors.New("Not implemented") + return nil, common.Hash{}, 0, 0, errors.New("not implemented") } func (b *LesApiBackend) GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { - 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 { + return nil +} + +func (b *LesApiBackend) PurgeCheckpointWhitelist() { } diff --git a/miner/worker.go b/miner/worker.go index 14c5ccd1a3..9fcb2140ca 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -390,27 +390,31 @@ func (w *worker) close() { // recalcRecommit recalculates the resubmitting interval upon feedback. func recalcRecommit(minRecommit, prev time.Duration, target float64, inc bool) time.Duration { - var ( - prevF = float64(prev.Nanoseconds()) - next float64 - ) - - if inc { - next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target+intervalAdjustBias) - - max := float64(maxRecommitInterval.Nanoseconds()) - if next > max { - next = max - } - } else { - next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target-intervalAdjustBias) - min := float64(minRecommit.Nanoseconds()) - if next < min { - next = min - } - } - - return time.Duration(int64(next)) + // var ( + // prevF = float64(prev.Nanoseconds()) + // next float64 + // ) + // + // if inc { + // next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target+intervalAdjustBias) + // max := float64(maxRecommitInterval.Nanoseconds()) + // + // if next > max { + // next = max + // } + // } else { + // next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target-intervalAdjustBias) + // min := float64(minRecommit.Nanoseconds()) + // + // if next < min { + // next = min + // } + // } + // + // log.Info("Recalc Commit", "Prev", prev, "Next", next) + + //returning the Same prev value to keep the recommit interval constant + return prev } // newWorkLoop is a standalone goroutine to submit new sealing work upon received events. diff --git a/miner/worker_test.go b/miner/worker_test.go index 00739844f2..6dae391c88 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -489,10 +489,15 @@ func testRegenerateMiningBlock(t *testing.T, chainConfig *params.ChainConfig, en } func TestAdjustIntervalEthash(t *testing.T) { + // Skipping this test as recommit interval would remain constant + t.Skip() testAdjustInterval(t, ethashChainConfig, ethash.NewFaker()) } func TestAdjustIntervalClique(t *testing.T) { + + // Skipping this test as recommit interval would remain constant + t.Skip() testAdjustInterval(t, cliqueChainConfig, clique.New(cliqueChainConfig.Clique, rawdb.NewMemoryDatabase())) } diff --git a/tests/bor/bor_test.go b/tests/bor/bor_test.go index 434ad805e1..36d515c557 100644 --- a/tests/bor/bor_test.go +++ b/tests/bor/bor_test.go @@ -11,10 +11,13 @@ import ( "time" "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "golang.org/x/crypto/sha3" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/bor" "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/span" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" @@ -25,15 +28,6 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/tests/bor/mocks" - - "github.com/stretchr/testify/assert" - "golang.org/x/crypto/sha3" -) - -const ( - spanPath = "bor/span/1" - clerkPath = "clerk/event-record/list" - clerkQueryParams = "from-time=%d&to-time=%d&page=%d&limit=50" ) func TestInsertingSpanSizeBlocks(t *testing.T) { @@ -42,9 +36,20 @@ func TestInsertingSpanSizeBlocks(t *testing.T) { engine := init.ethereum.Engine() _bor := engine.(*bor.Bor) + defer _bor.Close() + h, heimdallSpan, ctrl := getMockedHeimdallClient(t) defer ctrl.Finish() + _, span := loadSpanFromFile(t) + + h.EXPECT().Close().AnyTimes() + h.EXPECT().FetchLatestCheckpoint().Return(&checkpoint.Checkpoint{ + Proposer: span.SelectedProducers[0].Address, + StartBlock: big.NewInt(0), + EndBlock: big.NewInt(int64(spanSize)), + }, nil).AnyTimes() + _bor.SetHeimdallClient(h) db := init.ethereum.ChainDb() @@ -75,6 +80,8 @@ func TestFetchStateSyncEvents(t *testing.T) { engine := init.ethereum.Engine() _bor := engine.(*bor.Bor) + defer _bor.Close() + // A. Insert blocks for 0th sprint db := init.ethereum.ChainDb() block := init.genesis.ToBlock(db) @@ -92,6 +99,7 @@ func TestFetchStateSyncEvents(t *testing.T) { defer ctrl.Finish() h := mocks.NewMockIHeimdallClient(ctrl) + h.EXPECT().Close().AnyTimes() h.EXPECT().Span(uint64(1)).Return(&res.Result, nil).AnyTimes() // B.2 Mock State Sync events @@ -117,6 +125,8 @@ func TestFetchStateSyncEvents_2(t *testing.T) { engine := init.ethereum.Engine() _bor := engine.(*bor.Bor) + defer _bor.Close() + // Mock /bor/span/1 res, _ := loadSpanFromFile(t) @@ -124,6 +134,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) { defer ctrl.Finish() h := mocks.NewMockIHeimdallClient(ctrl) + h.EXPECT().Close().AnyTimes() h.EXPECT().Span(uint64(1)).Return(&res.Result, nil).AnyTimes() // Mock State Sync events @@ -184,9 +195,12 @@ func TestOutOfTurnSigning(t *testing.T) { engine := init.ethereum.Engine() _bor := engine.(*bor.Bor) + defer _bor.Close() + h, _, ctrl := getMockedHeimdallClient(t) defer ctrl.Finish() + h.EXPECT().Close().AnyTimes() _bor.SetHeimdallClient(h) db := init.ethereum.ChainDb() @@ -217,6 +231,7 @@ func TestOutOfTurnSigning(t *testing.T) { bor.CalcProducerDelay(header.Number.Uint64(), 0, init.genesis.Config.Bor)) sign(t, header, signerKey, init.genesis.Config.Bor) block = types.NewBlockWithHeader(header) + _, err = chain.InsertChain([]*types.Block{block}) assert.Equal(t, *err.(*bor.WrongDifficultyError), @@ -225,6 +240,7 @@ func TestOutOfTurnSigning(t *testing.T) { header.Difficulty = new(big.Int).SetUint64(expectedDifficulty) sign(t, header, signerKey, init.genesis.Config.Bor) block = types.NewBlockWithHeader(header) + _, err = chain.InsertChain([]*types.Block{block}) assert.Nil(t, err) } @@ -235,9 +251,13 @@ func TestSignerNotFound(t *testing.T) { engine := init.ethereum.Engine() _bor := engine.(*bor.Bor) + defer _bor.Close() + h, _, ctrl := getMockedHeimdallClient(t) defer ctrl.Finish() + h.EXPECT().Close().AnyTimes() + _bor.SetHeimdallClient(h) db := init.ethereum.ChainDb() @@ -298,6 +318,10 @@ func getSampleEventRecord(t *testing.T) *clerk.EventRecordWithTime { return eventRecords.Result[0] } +func getEventRecords(t *testing.T) []*clerk.EventRecordWithTime { + return stateSyncEventsPayload(t).Result +} + // TestEIP1559Transition tests the following: // // 1. A transaction whose gasFeeCap is greater than the baseFee is valid. diff --git a/tests/bor/mocks/IHeimdallClient.go b/tests/bor/mocks/IHeimdallClient.go index 4e4d7a3776..f770ed9fa8 100644 --- a/tests/bor/mocks/IHeimdallClient.go +++ b/tests/bor/mocks/IHeimdallClient.go @@ -8,6 +8,7 @@ import ( reflect "reflect" clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk" + checkpoint "github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint" span "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" gomock "github.com/golang/mock/gomock" ) @@ -47,6 +48,21 @@ func (mr *MockIHeimdallClientMockRecorder) Close() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockIHeimdallClient)(nil).Close)) } +// FetchLatestCheckpoint mocks base method. +func (m *MockIHeimdallClient) FetchLatestCheckpoint() (*checkpoint.Checkpoint, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchLatestCheckpoint") + ret0, _ := ret[0].(*checkpoint.Checkpoint) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchLatestCheckpoint indicates an expected call of FetchLatestCheckpoint. +func (mr *MockIHeimdallClientMockRecorder) FetchLatestCheckpoint() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchLatestCheckpoint", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchLatestCheckpoint)) +} + // Span mocks base method. func (m *MockIHeimdallClient) Span(arg0 uint64) (*span.HeimdallSpan, error) { m.ctrl.T.Helper() From 33e646eea1e6c86ed3a2b9fc0fe31b0b8799444f Mon Sep 17 00:00:00 2001 From: Jerry Date: Mon, 13 Jun 2022 20:43:34 -0700 Subject: [PATCH 80/80] Add keystore option to cli --- docs/cli/server.md | 2 ++ internal/cli/server/config.go | 4 ++++ internal/cli/server/flags.go | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/docs/cli/server.md b/docs/cli/server.md index 21ed27ed74..0803208e3a 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -12,6 +12,8 @@ The ```bor server``` command runs the Bor client. - ```datadir```: Path of the data directory to store information +- ```keystore```: Path of the directory to store keystores + - ```config```: File for the config file - ```syncmode```: Blockchain sync mode ("fast", "full", or "snap") diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 137f6aed0f..ab8c8e5155 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -52,6 +52,9 @@ type Config struct { // DataDir is the directory to store the state in DataDir string `hcl:"data-dir,optional"` + // KeyStoreDir is the directory to store keystores + KeyStoreDir string `hcl:"keystore-dir,optional"` + // SyncMode selects the sync protocol SyncMode string `hcl:"sync-mode,optional"` @@ -894,6 +897,7 @@ func (c *Config) buildNode() (*node.Config, error) { cfg := &node.Config{ Name: clientIdentifier, DataDir: c.DataDir, + KeyStoreDir: c.KeyStoreDir, UseLightweightKDF: c.Accounts.UseLightweightKDF, InsecureUnlockAllowed: c.Accounts.AllowInsecureUnlock, Version: params.VersionWithCommit(gitCommit, gitDate), diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index 6269e1c6fa..21e9a38cb9 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -33,6 +33,11 @@ func (c *Command) Flags() *flagset.Flagset { Value: &c.cliConfig.DataDir, Default: c.cliConfig.DataDir, }) + f.StringFlag(&flagset.StringFlag{ + Name: "keystore", + Usage: "Path of the directory to store keystores", + Value: &c.cliConfig.KeyStoreDir, + }) f.SliceStringFlag(&flagset.SliceStringFlag{ Name: "config", Usage: "File for the config file",