diff --git a/.github/workflows/build-docker-proto-image.yaml b/.github/workflows/build-docker-proto-image.yaml new file mode 100644 index 0000000000..3edab75795 --- /dev/null +++ b/.github/workflows/build-docker-proto-image.yaml @@ -0,0 +1,35 @@ +name: Build and Push harmony proto Docker Image + +on: + workflow_dispatch: + +jobs: + build_and_push: + runs-on: ubuntu-latest + + steps: + - name: Checkout harmony core code + uses: actions/checkout@v3 + with: + path: harmony + ref: ${{ github.ref }} + fetch-depth: 0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: ./harmony/api/service/legacysync/downloader + file: ./harmony/api/service/legacysync/downloader/Proto.Dockerfile + push: true + platforms: linux/amd64,linux/arm64 + tags: | + harmonyone/harmony-proto:latest \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 514f8e2fb4..dd92b53df5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ os: linux -dist: bionic +dist: jammy language: go go: - 1.19.5 @@ -22,13 +22,10 @@ install: - git clone https://github.com/harmony-one/harmony-test.git $GOPATH/src/github.com/harmony-one/harmony-test - (cd $GOPATH/src/github.com/harmony-one/mcl; make -j4) - (cd $GOPATH/src/github.com/harmony-one/bls; make BLS_SWAP_G=1 -j4) - - go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 - - go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 # - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.41.1 - make go-get - go install golang.org/x/tools/cmd/goimports@latest - go install github.com/harmony-ek/gencodec@latest - - scripts/install_build_tools.sh script: - ${TEST} after_success: diff --git a/Makefile b/Makefile index 052d6ad420..ee1d40faa0 100644 --- a/Makefile +++ b/Makefile @@ -164,3 +164,6 @@ go-test: docker: docker build --pull -t harmonyone/$(PKGNAME):latest -f scripts/docker/Dockerfile . + +travis_go_checker: + bash ./scripts/travis_go_checker.sh diff --git a/api/proto/message/gen.sh b/api/proto/message/gen.sh index 5dc2fc1bc8..bd667421e3 100755 --- a/api/proto/message/gen.sh +++ b/api/proto/message/gen.sh @@ -1 +1,3 @@ -protoc -I ./ message.proto --go_out=. --go-grpc_out=. +#!/bin/bash + +docker run --platform linux/amd64 -v ${PWD}:/tmp ${PROTOC_IMAGE} /tmp/message.proto diff --git a/api/proto/message/message.go b/api/proto/message/message.go index 8ba69bcf6a..22f91a10e7 100644 --- a/api/proto/message/message.go +++ b/api/proto/message/message.go @@ -1,3 +1,3 @@ package message -//go:generate protoc message.proto --go_out=. --go-grpc_out=. +//go:generate ./gen.sh diff --git a/api/proto/message/message.pb.go b/api/proto/message/message.pb.go index a72c0dd441..b1367f3d7d 100644 --- a/api/proto/message/message.pb.go +++ b/api/proto/message/message.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.15.8 +// protoc-gen-go v1.30.0 +// protoc v3.12.4 // source: message.proto package message @@ -25,9 +25,9 @@ type ServiceType int32 const ( ServiceType_CONSENSUS ServiceType = 0 - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. ServiceType_STAKING ServiceType = 1 - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. ServiceType_DRAND ServiceType = 2 ServiceType_CLIENT_SUPPORT ServiceType = 3 ) @@ -79,7 +79,7 @@ func (ServiceType) EnumDescriptor() ([]byte, []int) { type MessageType int32 const ( - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. MessageType_NEWNODE_BEACON_STAKING MessageType = 0 MessageType_ANNOUNCE MessageType = 1 MessageType_PREPARE MessageType = 2 @@ -88,11 +88,11 @@ const ( MessageType_COMMITTED MessageType = 5 MessageType_VIEWCHANGE MessageType = 6 MessageType_NEWVIEW MessageType = 7 - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. MessageType_DRAND_INIT MessageType = 10 - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. MessageType_DRAND_COMMIT MessageType = 11 - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. MessageType_LOTTERY_REQUEST MessageType = 12 // it should be either ENTER or GETPLAYERS but it will be removed later. ) @@ -156,11 +156,11 @@ func (MessageType) EnumDescriptor() ([]byte, []int) { type LotteryRequest_Type int32 const ( - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. LotteryRequest_ENTER LotteryRequest_Type = 0 - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. LotteryRequest_RESULT LotteryRequest_Type = 1 - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. LotteryRequest_PICK_WINNER LotteryRequest_Type = 2 ) @@ -288,7 +288,7 @@ func (m *Message) GetRequest() isMessage_Request { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *Message) GetStaking() *StakingRequest { if x, ok := x.GetRequest().(*Message_Staking); ok { return x.Staking @@ -303,7 +303,7 @@ func (x *Message) GetConsensus() *ConsensusRequest { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *Message) GetDrand() *DrandRequest { if x, ok := x.GetRequest().(*Message_Drand); ok { return x.Drand @@ -318,7 +318,7 @@ func (x *Message) GetViewchange() *ViewChangeRequest { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *Message) GetLotteryRequest() *LotteryRequest { if x, ok := x.GetRequest().(*Message_LotteryRequest); ok { return x.LotteryRequest @@ -331,7 +331,7 @@ type isMessage_Request interface { } type Message_Staking struct { - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. Staking *StakingRequest `protobuf:"bytes,4,opt,name=staking,proto3,oneof"` } @@ -340,7 +340,7 @@ type Message_Consensus struct { } type Message_Drand struct { - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. Drand *DrandRequest `protobuf:"bytes,6,opt,name=drand,proto3,oneof"` } @@ -351,7 +351,7 @@ type Message_Viewchange struct { type Message_LotteryRequest struct { // Refactor this later after demo. // - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. LotteryRequest *LotteryRequest `protobuf:"bytes,8,opt,name=lottery_request,json=lotteryRequest,proto3,oneof"` } @@ -431,7 +431,7 @@ func (m *Response) GetResponse() isResponse_Response { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *Response) GetLotteryResponse() *LotteryResponse { if x, ok := x.GetResponse().(*Response_LotteryResponse); ok { return x.LotteryResponse @@ -444,7 +444,7 @@ type isResponse_Response interface { } type Response_LotteryResponse struct { - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. LotteryResponse *LotteryResponse `protobuf:"bytes,3,opt,name=lottery_response,json=lotteryResponse,proto3,oneof"` } @@ -455,9 +455,9 @@ type LotteryResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. Players []string `protobuf:"bytes,2,rep,name=players,proto3" json:"players,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. Balances []string `protobuf:"bytes,3,rep,name=balances,proto3" json:"balances,omitempty"` } @@ -493,7 +493,7 @@ func (*LotteryResponse) Descriptor() ([]byte, []int) { return file_message_proto_rawDescGZIP(), []int{2} } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *LotteryResponse) GetPlayers() []string { if x != nil { return x.Players @@ -501,7 +501,7 @@ func (x *LotteryResponse) GetPlayers() []string { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *LotteryResponse) GetBalances() []string { if x != nil { return x.Balances @@ -514,11 +514,11 @@ type LotteryRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. Type LotteryRequest_Type `protobuf:"varint,1,opt,name=type,proto3,enum=message.LotteryRequest_Type" json:"type,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. PrivateKey string `protobuf:"bytes,2,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` } @@ -554,7 +554,7 @@ func (*LotteryRequest) Descriptor() ([]byte, []int) { return file_message_proto_rawDescGZIP(), []int{3} } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *LotteryRequest) GetType() LotteryRequest_Type { if x != nil { return x.Type @@ -562,7 +562,7 @@ func (x *LotteryRequest) GetType() LotteryRequest_Type { return LotteryRequest_ENTER } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *LotteryRequest) GetPrivateKey() string { if x != nil { return x.PrivateKey @@ -570,7 +570,7 @@ func (x *LotteryRequest) GetPrivateKey() string { return "" } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *LotteryRequest) GetAmount() int64 { if x != nil { return x.Amount @@ -584,9 +584,9 @@ type StakingRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. Transaction []byte `protobuf:"bytes,1,opt,name=transaction,proto3" json:"transaction,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. NodeId string `protobuf:"bytes,2,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` } @@ -622,7 +622,7 @@ func (*StakingRequest) Descriptor() ([]byte, []int) { return file_message_proto_rawDescGZIP(), []int{4} } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *StakingRequest) GetTransaction() []byte { if x != nil { return x.Transaction @@ -630,7 +630,7 @@ func (x *StakingRequest) GetTransaction() []byte { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *StakingRequest) GetNodeId() string { if x != nil { return x.NodeId @@ -746,13 +746,13 @@ type DrandRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. ShardId uint32 `protobuf:"varint,1,opt,name=shard_id,json=shardId,proto3" json:"shard_id,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. SenderPubkey []byte `protobuf:"bytes,2,opt,name=sender_pubkey,json=senderPubkey,proto3" json:"sender_pubkey,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in message.proto. Payload []byte `protobuf:"bytes,4,opt,name=payload,proto3" json:"payload,omitempty"` } @@ -788,7 +788,7 @@ func (*DrandRequest) Descriptor() ([]byte, []int) { return file_message_proto_rawDescGZIP(), []int{6} } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *DrandRequest) GetShardId() uint32 { if x != nil { return x.ShardId @@ -796,7 +796,7 @@ func (x *DrandRequest) GetShardId() uint32 { return 0 } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *DrandRequest) GetSenderPubkey() []byte { if x != nil { return x.SenderPubkey @@ -804,7 +804,7 @@ func (x *DrandRequest) GetSenderPubkey() []byte { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *DrandRequest) GetBlockHash() []byte { if x != nil { return x.BlockHash @@ -812,7 +812,7 @@ func (x *DrandRequest) GetBlockHash() []byte { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in message.proto. func (x *DrandRequest) GetPayload() []byte { if x != nil { return x.Payload diff --git a/api/proto/message/message_grpc.pb.go b/api/proto/message/message_grpc.pb.go index e474fe0723..82a08b9b3d 100644 --- a/api/proto/message/message_grpc.pb.go +++ b/api/proto/message/message_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.12.4 +// source: message.proto package message @@ -14,6 +18,10 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 +const ( + ClientService_Process_FullMethodName = "/message.ClientService/Process" +) + // ClientServiceClient is the client API for ClientService service. // // 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. @@ -31,7 +39,7 @@ func NewClientServiceClient(cc grpc.ClientConnInterface) ClientServiceClient { func (c *clientServiceClient) Process(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Response, error) { out := new(Response) - err := c.cc.Invoke(ctx, "/message.ClientService/Process", in, out, opts...) + err := c.cc.Invoke(ctx, ClientService_Process_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -76,7 +84,7 @@ func _ClientService_Process_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/message.ClientService/Process", + FullMethod: ClientService_Process_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ClientServiceServer).Process(ctx, req.(*Message)) diff --git a/api/service/legacysync/downloader/Proto.Dockerfile b/api/service/legacysync/downloader/Proto.Dockerfile new file mode 100644 index 0000000000..5591abb476 --- /dev/null +++ b/api/service/legacysync/downloader/Proto.Dockerfile @@ -0,0 +1,9 @@ +FROM golang:1.19-bullseye + +RUN apt update +RUN apt install -y protobuf-compiler +RUN protoc --version +RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30.0 +RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3 + +ENTRYPOINT ["protoc", "-I=/tmp", "--go_out=/tmp", "--go-grpc_out=/tmp"] \ No newline at end of file diff --git a/api/service/legacysync/downloader/build.sh b/api/service/legacysync/downloader/build.sh new file mode 100755 index 0000000000..b0193985a9 --- /dev/null +++ b/api/service/legacysync/downloader/build.sh @@ -0,0 +1,4 @@ + +# if command fails, try this +# docker buildx create --use +docker buildx build -t frozen621/harmony-proto:latest --platform linux/amd64,linux/arm64 -f Proto.Dockerfile --progress=plain . \ No newline at end of file diff --git a/api/service/legacysync/downloader/gen.sh b/api/service/legacysync/downloader/gen.sh deleted file mode 100755 index 04c9286e71..0000000000 --- a/api/service/legacysync/downloader/gen.sh +++ /dev/null @@ -1,5 +0,0 @@ -# used versions -#go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 -#go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 -SRC_DIR=$(dirname $0) -protoc -I ${SRC_DIR}/proto/ ${SRC_DIR}/proto/downloader.proto --go_out=${SRC_DIR}/proto --go-grpc_out=${SRC_DIR}/proto diff --git a/api/service/legacysync/downloader/proto/downloader.go b/api/service/legacysync/downloader/proto/downloader.go index 023a87eb77..30fe9082d1 100644 --- a/api/service/legacysync/downloader/proto/downloader.go +++ b/api/service/legacysync/downloader/proto/downloader.go @@ -1,4 +1,5 @@ package downloader ///go:generate protoc downloader.proto --go_out=plugins=grpc:. -//go:generate protoc downloader.proto --go_out=. --go-grpc_out=. +///go:generate protoc downloader.proto --go_out=. --go-grpc_out=. +//go:generate ./gen.sh diff --git a/api/service/legacysync/downloader/proto/downloader.pb.go b/api/service/legacysync/downloader/proto/downloader.pb.go index d93550bf09..c0013dc226 100644 --- a/api/service/legacysync/downloader/proto/downloader.pb.go +++ b/api/service/legacysync/downloader/proto/downloader.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.15.8 +// protoc-gen-go v1.30.0 +// protoc v3.12.4 // source: downloader.proto package downloader diff --git a/api/service/legacysync/downloader/proto/downloader_grpc.pb.go b/api/service/legacysync/downloader/proto/downloader_grpc.pb.go index 1360c3eeec..cfe2f27f61 100644 --- a/api/service/legacysync/downloader/proto/downloader_grpc.pb.go +++ b/api/service/legacysync/downloader/proto/downloader_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.12.4 +// source: downloader.proto package downloader @@ -14,6 +18,10 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 +const ( + Downloader_Query_FullMethodName = "/downloader.Downloader/Query" +) + // DownloaderClient is the client API for Downloader service. // // 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. @@ -31,7 +39,7 @@ func NewDownloaderClient(cc grpc.ClientConnInterface) DownloaderClient { func (c *downloaderClient) Query(ctx context.Context, in *DownloaderRequest, opts ...grpc.CallOption) (*DownloaderResponse, error) { out := new(DownloaderResponse) - err := c.cc.Invoke(ctx, "/downloader.Downloader/Query", in, out, opts...) + err := c.cc.Invoke(ctx, Downloader_Query_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -76,7 +84,7 @@ func _Downloader_Query_Handler(srv interface{}, ctx context.Context, dec func(in } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/downloader.Downloader/Query", + FullMethod: Downloader_Query_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DownloaderServer).Query(ctx, req.(*DownloaderRequest)) diff --git a/api/service/legacysync/downloader/proto/gen.sh b/api/service/legacysync/downloader/proto/gen.sh new file mode 100755 index 0000000000..23e55aefb4 --- /dev/null +++ b/api/service/legacysync/downloader/proto/gen.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# used versions +#go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 +#go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 +#SRC_DIR=$(dirname $0) +#protoc -I ${SRC_DIR}/proto/ ${SRC_DIR}/proto/downloader.proto --go_out=${SRC_DIR}/proto --go-grpc_out=${SRC_DIR}/proto + +docker run --platform linux/amd64 -v ${PWD}:/tmp ${PROTOC_IMAGE} /tmp/downloader.proto diff --git a/api/service/legacysync/epoch_syncing.go b/api/service/legacysync/epoch_syncing.go index eefca9a5cb..e4453cb69c 100644 --- a/api/service/legacysync/epoch_syncing.go +++ b/api/service/legacysync/epoch_syncing.go @@ -92,7 +92,7 @@ func (ss *EpochSync) SyncLoop(bc core.BlockChain, consensus *consensus.Consensus } func syncLoop(bc core.BlockChain, syncConfig *SyncConfig) (timeout int) { - isBeacon := bc.ShardID() == 0 + isBeacon := bc.ShardID() == shard.BeaconChainShardID maxHeight, errMaxHeight := getMaxPeerHeight(syncConfig) if errMaxHeight != nil { utils.Logger().Info(). diff --git a/api/service/stagedstreamsync/block_manager.go b/api/service/stagedstreamsync/block_manager.go index df30ab5e36..28c966b4d6 100644 --- a/api/service/stagedstreamsync/block_manager.go +++ b/api/service/stagedstreamsync/block_manager.go @@ -84,7 +84,7 @@ func (gbm *blockDownloadManager) HandleRequestResult(bns []uint64, blockBytes [] for i, bn := range bns { delete(gbm.requesting, bn) - if len(blockBytes[i]) <= 1 { + if indexExists(blockBytes, i) && len(blockBytes[i]) <= 1 { gbm.retries.push(bn) } else { gbm.processing[bn] = struct{}{} @@ -97,6 +97,10 @@ func (gbm *blockDownloadManager) HandleRequestResult(bns []uint64, blockBytes [] return nil } +func indexExists[T any](slice []T, index int) bool { + return index >= 0 && index < len(slice) +} + // SetDownloadDetails sets the download details for a batch of blocks func (gbm *blockDownloadManager) SetDownloadDetails(bns []uint64, loopID int, streamID sttypes.StreamID) error { gbm.lock.Lock() diff --git a/api/service/stagedstreamsync/downloader.go b/api/service/stagedstreamsync/downloader.go index a20b4ac79a..668698f107 100644 --- a/api/service/stagedstreamsync/downloader.go +++ b/api/service/stagedstreamsync/downloader.go @@ -37,7 +37,7 @@ type ( ) // NewDownloader creates a new downloader -func NewDownloader(host p2p.Host, bc core.BlockChain, isBeaconNode bool, config Config) *Downloader { +func NewDownloader(host p2p.Host, bc core.BlockChain, dbDir string, isBeaconNode bool, config Config) *Downloader { config.fixValues() sp := sync.NewProtocol(sync.Config{ @@ -68,7 +68,7 @@ func NewDownloader(host p2p.Host, bc core.BlockChain, isBeaconNode bool, config ctx, cancel := context.WithCancel(context.Background()) //TODO: use mem db should be in config file - stagedSyncInstance, err := CreateStagedSync(ctx, bc, false, isBeaconNode, sp, config, logger, config.LogProgress) + stagedSyncInstance, err := CreateStagedSync(ctx, bc, dbDir, false, isBeaconNode, sp, config, logger, config.LogProgress) if err != nil { cancel() return nil diff --git a/api/service/stagedstreamsync/downloaders.go b/api/service/stagedstreamsync/downloaders.go index 0e79c79631..2df8b74aab 100644 --- a/api/service/stagedstreamsync/downloaders.go +++ b/api/service/stagedstreamsync/downloaders.go @@ -15,7 +15,7 @@ type Downloaders struct { } // NewDownloaders creates Downloaders for sync of multiple blockchains -func NewDownloaders(host p2p.Host, bcs []core.BlockChain, config Config) *Downloaders { +func NewDownloaders(host p2p.Host, bcs []core.BlockChain, dbDir string, config Config) *Downloaders { ds := make(map[uint32]*Downloader) isBeaconNode := len(bcs) == 1 for _, bc := range bcs { @@ -25,7 +25,7 @@ func NewDownloaders(host p2p.Host, bcs []core.BlockChain, config Config) *Downlo if _, ok := ds[bc.ShardID()]; ok { continue } - ds[bc.ShardID()] = NewDownloader(host, bc, isBeaconNode, config) + ds[bc.ShardID()] = NewDownloader(host, bc, dbDir, isBeaconNode, config) } return &Downloaders{ ds: ds, diff --git a/api/service/stagedstreamsync/service.go b/api/service/stagedstreamsync/service.go index 46b182fb53..40fbf7097c 100644 --- a/api/service/stagedstreamsync/service.go +++ b/api/service/stagedstreamsync/service.go @@ -11,9 +11,9 @@ type StagedStreamSyncService struct { } // NewService creates a new downloader service -func NewService(host p2p.Host, bcs []core.BlockChain, config Config) *StagedStreamSyncService { +func NewService(host p2p.Host, bcs []core.BlockChain, config Config, dbDir string) *StagedStreamSyncService { return &StagedStreamSyncService{ - Downloaders: NewDownloaders(host, bcs, config), + Downloaders: NewDownloaders(host, bcs, dbDir, config), } } diff --git a/api/service/stagedstreamsync/short_range_helper.go b/api/service/stagedstreamsync/short_range_helper.go index 90415c87c3..e43b3c6916 100644 --- a/api/service/stagedstreamsync/short_range_helper.go +++ b/api/service/stagedstreamsync/short_range_helper.go @@ -15,13 +15,11 @@ import ( type srHelper struct { syncProtocol syncProtocol - - ctx context.Context - config Config - logger zerolog.Logger + config Config + logger zerolog.Logger } -func (sh *srHelper) getHashChain(bns []uint64) ([]common.Hash, []sttypes.StreamID, error) { +func (sh *srHelper) getHashChain(ctx context.Context, bns []uint64) ([]common.Hash, []sttypes.StreamID, error) { results := newBlockHashResults(bns) var wg sync.WaitGroup @@ -31,7 +29,7 @@ func (sh *srHelper) getHashChain(bns []uint64) ([]common.Hash, []sttypes.StreamI go func(index int) { defer wg.Done() - hashes, stid, err := sh.doGetBlockHashesRequest(bns) + hashes, stid, err := sh.doGetBlockHashesRequest(ctx, bns) if err != nil { sh.logger.Warn().Err(err).Str("StreamID", string(stid)). Msg(WrapStagedSyncMsg("doGetBlockHashes return error")) @@ -43,10 +41,10 @@ func (sh *srHelper) getHashChain(bns []uint64) ([]common.Hash, []sttypes.StreamI wg.Wait() select { - case <-sh.ctx.Done(): - sh.logger.Info().Err(sh.ctx.Err()).Int("num blocks", results.numBlocksWithResults()). + case <-ctx.Done(): + sh.logger.Info().Err(ctx.Err()).Int("num blocks", results.numBlocksWithResults()). Msg(WrapStagedSyncMsg("short range sync get hashes timed out")) - return nil, nil, sh.ctx.Err() + return nil, nil, ctx.Err() default: } @@ -56,13 +54,12 @@ func (sh *srHelper) getHashChain(bns []uint64) ([]common.Hash, []sttypes.StreamI return hashChain, wl, nil } -func (sh *srHelper) getBlocksChain(bns []uint64) ([]*types.Block, sttypes.StreamID, error) { - return sh.doGetBlocksByNumbersRequest(bns) +func (sh *srHelper) getBlocksChain(ctx context.Context, bns []uint64) ([]*types.Block, sttypes.StreamID, error) { + return sh.doGetBlocksByNumbersRequest(ctx, bns) } -func (sh *srHelper) getBlocksByHashes(hashes []common.Hash, whitelist []sttypes.StreamID) ([]*types.Block, []sttypes.StreamID, error) { - ctx, cancel := context.WithCancel(sh.ctx) - defer cancel() +func (sh *srHelper) getBlocksByHashes(ctx context.Context, hashes []common.Hash, whitelist []sttypes.StreamID) ([]*types.Block, []sttypes.StreamID, error) { + m := newGetBlocksByHashManager(hashes, whitelist) var ( @@ -80,7 +77,8 @@ func (sh *srHelper) getBlocksByHashes(hashes []common.Hash, whitelist []sttypes. for i := 0; i != concurrency; i++ { go func(index int) { defer wg.Done() - defer cancel() // it's ok to cancel context more than once + ctx, cancel := context.WithCancel(ctx) + defer cancel() for { if m.isDone() { @@ -121,11 +119,11 @@ func (sh *srHelper) getBlocksByHashes(hashes []common.Hash, whitelist []sttypes. return nil, nil, gErr } select { - case <-sh.ctx.Done(): + case <-ctx.Done(): res, _, _ := m.getResults() - sh.logger.Info().Err(sh.ctx.Err()).Int("num blocks", len(res)). + sh.logger.Info().Err(ctx.Err()).Int("num blocks", len(res)). Msg(WrapStagedSyncMsg("short range sync get blocks timed out")) - return nil, nil, sh.ctx.Err() + return nil, nil, ctx.Err() default: } @@ -149,8 +147,8 @@ func (sh *srHelper) prepareBlockHashNumbers(curNumber uint64) []uint64 { return res } -func (sh *srHelper) doGetBlockHashesRequest(bns []uint64) ([]common.Hash, sttypes.StreamID, error) { - ctx, cancel := context.WithTimeout(sh.ctx, 1*time.Second) +func (sh *srHelper) doGetBlockHashesRequest(ctx context.Context, bns []uint64) ([]common.Hash, sttypes.StreamID, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() hashes, stid, err := sh.syncProtocol.GetBlockHashes(ctx, bns) @@ -171,8 +169,8 @@ func (sh *srHelper) doGetBlockHashesRequest(bns []uint64) ([]common.Hash, sttype return hashes, stid, nil } -func (sh *srHelper) doGetBlocksByNumbersRequest(bns []uint64) ([]*types.Block, sttypes.StreamID, error) { - ctx, cancel := context.WithTimeout(sh.ctx, 10*time.Second) +func (sh *srHelper) doGetBlocksByNumbersRequest(ctx context.Context, bns []uint64) ([]*types.Block, sttypes.StreamID, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() blocks, stid, err := sh.syncProtocol.GetBlocksByNumber(ctx, bns) @@ -186,7 +184,7 @@ func (sh *srHelper) doGetBlocksByNumbersRequest(bns []uint64) ([]*types.Block, s } func (sh *srHelper) doGetBlocksByHashesRequest(ctx context.Context, hashes []common.Hash, wl []sttypes.StreamID) ([]*types.Block, sttypes.StreamID, error) { - ctx, cancel := context.WithTimeout(sh.ctx, 10*time.Second) + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() blocks, stid, err := sh.syncProtocol.GetBlocksByHashes(ctx, hashes, diff --git a/api/service/stagedstreamsync/stage.go b/api/service/stagedstreamsync/stage.go index 255560a0ff..48334a5e52 100644 --- a/api/service/stagedstreamsync/stage.go +++ b/api/service/stagedstreamsync/stage.go @@ -16,21 +16,18 @@ type StageHandler interface { // * invalidBlockRevert - whether the execution is to solve the invalid block // * s - is the current state of the stage and contains stage data. // * reverter - if the stage needs to cause reverting, `reverter` methods can be used. - Exec(firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error + Exec(ctx context.Context, firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error // Revert is the reverting logic of the stage. // * firstCycle - is it the first cycle of syncing. // * u - contains information about the revert itself. // * s - represents the state of this stage at the beginning of revert. - Revert(firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) error + Revert(ctx context.Context, firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) error // CleanUp is the execution function for the stage to prune old data. // * firstCycle - is it the first cycle of syncing. // * p - is the current state of the stage and contains stage data. - CleanUp(firstCycle bool, p *CleanUpState, tx kv.RwTx) error - - // SetStageContext updates the context for stage - SetStageContext(ctx context.Context) + CleanUp(ctx context.Context, firstCycle bool, p *CleanUpState, tx kv.RwTx) error } // Stage is a single sync stage in staged sync. diff --git a/api/service/stagedstreamsync/stage_bodies.go b/api/service/stagedstreamsync/stage_bodies.go index 1fbfcbc2e6..62309b76df 100644 --- a/api/service/stagedstreamsync/stage_bodies.go +++ b/api/service/stagedstreamsync/stage_bodies.go @@ -17,8 +17,8 @@ import ( type StageBodies struct { configs StageBodiesCfg } + type StageBodiesCfg struct { - ctx context.Context bc core.BlockChain db kv.RwDB blockDBs []kv.RwDB @@ -34,9 +34,8 @@ func NewStageBodies(cfg StageBodiesCfg) *StageBodies { } } -func NewStageBodiesCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB, blockDBs []kv.RwDB, concurrency int, protocol syncProtocol, isBeacon bool, logProgress bool) StageBodiesCfg { +func NewStageBodiesCfg(bc core.BlockChain, db kv.RwDB, blockDBs []kv.RwDB, concurrency int, protocol syncProtocol, isBeacon bool, logProgress bool) StageBodiesCfg { return StageBodiesCfg{ - ctx: ctx, bc: bc, db: db, blockDBs: blockDBs, @@ -47,17 +46,13 @@ func NewStageBodiesCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB, bloc } } -func (b *StageBodies) SetStageContext(ctx context.Context) { - b.configs.ctx = ctx -} - // Exec progresses Bodies stage in the forward direction -func (b *StageBodies) Exec(firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) (err error) { +func (b *StageBodies) Exec(ctx context.Context, firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) (err error) { useInternalTx := tx == nil if invalidBlockRevert { - return b.redownloadBadBlock(s) + return b.redownloadBadBlock(ctx, s) } // for short range sync, skip this stage @@ -72,10 +67,8 @@ func (b *StageBodies) Exec(firstCycle bool, invalidBlockRevert bool, s *StageSta } currProgress := uint64(0) targetHeight := s.state.currentCycle.TargetHeight - // isBeacon := s.state.isBeacon - // isLastCycle := targetHeight >= maxHeight - if errV := CreateView(b.configs.ctx, b.configs.db, tx, func(etx kv.Tx) error { + if errV := CreateView(ctx, b.configs.db, tx, func(etx kv.Tx) error { if currProgress, err = s.CurrentStageProgress(etx); err != nil { return err } @@ -85,7 +78,7 @@ func (b *StageBodies) Exec(firstCycle bool, invalidBlockRevert bool, s *StageSta } if currProgress == 0 { - if err := b.cleanAllBlockDBs(); err != nil { + if err := b.cleanAllBlockDBs(ctx); err != nil { return err } currProgress = currentHead @@ -104,7 +97,7 @@ func (b *StageBodies) Exec(firstCycle bool, invalidBlockRevert bool, s *StageSta if useInternalTx { var err error - tx, err = b.configs.db.BeginRw(context.Background()) + tx, err = b.configs.db.BeginRw(ctx) if err != nil { return err } @@ -119,7 +112,7 @@ func (b *StageBodies) Exec(firstCycle bool, invalidBlockRevert bool, s *StageSta for i := 0; i != s.state.config.Concurrency; i++ { wg.Add(1) - go b.runBlockWorkerLoop(s.state.gbm, &wg, i, startTime) + go b.runBlockWorkerLoop(ctx, s.state.gbm, &wg, i, startTime) } wg.Wait() @@ -134,7 +127,7 @@ func (b *StageBodies) Exec(firstCycle bool, invalidBlockRevert bool, s *StageSta } // runBlockWorkerLoop creates a work loop for download blocks -func (b *StageBodies) runBlockWorkerLoop(gbm *blockDownloadManager, wg *sync.WaitGroup, loopID int, startTime time.Time) { +func (b *StageBodies) runBlockWorkerLoop(ctx context.Context, gbm *blockDownloadManager, wg *sync.WaitGroup, loopID int, startTime time.Time) { currentBlock := int(b.configs.bc.CurrentBlock().NumberU64()) @@ -142,21 +135,21 @@ func (b *StageBodies) runBlockWorkerLoop(gbm *blockDownloadManager, wg *sync.Wai for { select { - case <-b.configs.ctx.Done(): + case <-ctx.Done(): return default: } batch := gbm.GetNextBatch() if len(batch) == 0 { select { - case <-b.configs.ctx.Done(): + case <-ctx.Done(): return case <-time.After(100 * time.Millisecond): return } } - blockBytes, sigBytes, stid, err := b.downloadRawBlocks(batch) + blockBytes, sigBytes, stid, err := b.downloadRawBlocks(ctx, batch) if err != nil { if !errors.Is(err, context.Canceled) { b.configs.protocol.StreamFailed(stid, "downloadRawBlocks failed") @@ -168,8 +161,15 @@ func (b *StageBodies) runBlockWorkerLoop(gbm *blockDownloadManager, wg *sync.Wai Msg(WrapStagedSyncMsg("downloadRawBlocks failed")) err = errors.Wrap(err, "request error") gbm.HandleRequestError(batch, err, stid) + } else if blockBytes == nil || len(blockBytes) == 0 { + utils.Logger().Warn(). + Str("stream", string(stid)). + Interface("block numbers", batch). + Msg(WrapStagedSyncMsg("downloadRawBlocks failed, received empty blockBytes")) + err := errors.New("downloadRawBlocks received empty blockBytes") + gbm.HandleRequestError(batch, err, stid) } else { - if err = b.saveBlocks(gbm.tx, batch, blockBytes, sigBytes, loopID, stid); err != nil { + if err = b.saveBlocks(ctx, gbm.tx, batch, blockBytes, sigBytes, loopID, stid); err != nil { panic(ErrSaveBlocksToDbFailed) } gbm.HandleRequestResult(batch, blockBytes, sigBytes, loopID, stid) @@ -190,7 +190,7 @@ func (b *StageBodies) runBlockWorkerLoop(gbm *blockDownloadManager, wg *sync.Wai } // redownloadBadBlock tries to redownload the bad block from other streams -func (b *StageBodies) redownloadBadBlock(s *StageState) error { +func (b *StageBodies) redownloadBadBlock(ctx context.Context, s *StageState) error { batch := make([]uint64, 1) batch = append(batch, s.state.invalidBlock.Number) @@ -199,7 +199,7 @@ func (b *StageBodies) redownloadBadBlock(s *StageState) error { if b.configs.protocol.NumStreams() == 0 { return errors.Errorf("re-download bad block from all streams failed") } - blockBytes, sigBytes, stid, err := b.downloadRawBlocks(batch) + blockBytes, sigBytes, stid, err := b.downloadRawBlocks(ctx, batch) if err != nil { if !errors.Is(err, context.Canceled) { b.configs.protocol.StreamFailed(stid, "tried to re-download bad block from this stream, but downloadRawBlocks failed") @@ -218,8 +218,8 @@ func (b *StageBodies) redownloadBadBlock(s *StageState) error { continue } s.state.gbm.SetDownloadDetails(batch, 0, stid) - if errU := b.configs.blockDBs[0].Update(context.Background(), func(tx kv.RwTx) error { - if err = b.saveBlocks(tx, batch, blockBytes, sigBytes, 0, stid); err != nil { + if errU := b.configs.blockDBs[0].Update(ctx, func(tx kv.RwTx) error { + if err = b.saveBlocks(ctx, tx, batch, blockBytes, sigBytes, 0, stid); err != nil { return errors.Errorf("[STAGED_STREAM_SYNC] saving re-downloaded bad block to db failed.") } return nil @@ -231,8 +231,8 @@ func (b *StageBodies) redownloadBadBlock(s *StageState) error { return nil } -func (b *StageBodies) downloadBlocks(bns []uint64) ([]*types.Block, sttypes.StreamID, error) { - ctx, cancel := context.WithTimeout(b.configs.ctx, 10*time.Second) +func (b *StageBodies) downloadBlocks(ctx context.Context, bns []uint64) ([]*types.Block, sttypes.StreamID, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() blocks, stid, err := b.configs.protocol.GetBlocksByNumber(ctx, bns) @@ -245,8 +245,8 @@ func (b *StageBodies) downloadBlocks(bns []uint64) ([]*types.Block, sttypes.Stre return blocks, stid, nil } -func (b *StageBodies) downloadRawBlocks(bns []uint64) ([][]byte, [][]byte, sttypes.StreamID, error) { - ctx, cancel := context.WithTimeout(b.configs.ctx, 10*time.Second) +func (b *StageBodies) downloadRawBlocks(ctx context.Context, bns []uint64) ([][]byte, [][]byte, sttypes.StreamID, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() return b.configs.protocol.GetRawBlocksByNumber(ctx, bns) @@ -265,9 +265,9 @@ func validateGetBlocksResult(requested []uint64, result []*types.Block) error { } // saveBlocks saves the blocks into db -func (b *StageBodies) saveBlocks(tx kv.RwTx, bns []uint64, blockBytes [][]byte, sigBytes [][]byte, loopID int, stid sttypes.StreamID) error { +func (b *StageBodies) saveBlocks(ctx context.Context, tx kv.RwTx, bns []uint64, blockBytes [][]byte, sigBytes [][]byte, loopID int, stid sttypes.StreamID) error { - tx, err := b.configs.blockDBs[loopID].BeginRw(context.Background()) + tx, err := b.configs.blockDBs[loopID].BeginRw(ctx) if err != nil { return err } @@ -306,11 +306,11 @@ func (b *StageBodies) saveBlocks(tx kv.RwTx, bns []uint64, blockBytes [][]byte, return nil } -func (b *StageBodies) saveProgress(s *StageState, progress uint64, tx kv.RwTx) (err error) { +func (b *StageBodies) saveProgress(ctx context.Context, s *StageState, progress uint64, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { var err error - tx, err = b.configs.db.BeginRw(context.Background()) + tx, err = b.configs.db.BeginRw(ctx) if err != nil { return err } @@ -333,9 +333,8 @@ func (b *StageBodies) saveProgress(s *StageState, progress uint64, tx kv.RwTx) ( return nil } -func (b *StageBodies) cleanBlocksDB(loopID int) (err error) { - - tx, errb := b.configs.blockDBs[loopID].BeginRw(b.configs.ctx) +func (b *StageBodies) cleanBlocksDB(ctx context.Context, loopID int) (err error) { + tx, errb := b.configs.blockDBs[loopID].BeginRw(ctx) if errb != nil { return errb } @@ -363,26 +362,26 @@ func (b *StageBodies) cleanBlocksDB(loopID int) (err error) { return nil } -func (b *StageBodies) cleanAllBlockDBs() (err error) { +func (b *StageBodies) cleanAllBlockDBs(ctx context.Context) (err error) { //clean all blocks DBs for i := 0; i < b.configs.concurrency; i++ { - if err := b.cleanBlocksDB(i); err != nil { + if err := b.cleanBlocksDB(ctx, i); err != nil { return err } } return nil } -func (b *StageBodies) Revert(firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { +func (b *StageBodies) Revert(ctx context.Context, firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { //clean all blocks DBs - if err := b.cleanAllBlockDBs(); err != nil { + if err := b.cleanAllBlockDBs(ctx); err != nil { return err } useInternalTx := tx == nil if useInternalTx { - tx, err = b.configs.db.BeginRw(b.configs.ctx) + tx, err = b.configs.db.BeginRw(ctx) if err != nil { return err } @@ -409,10 +408,9 @@ func (b *StageBodies) Revert(firstCycle bool, u *RevertState, s *StageState, tx return nil } -func (b *StageBodies) CleanUp(firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { - +func (b *StageBodies) CleanUp(ctx context.Context, firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { //clean all blocks DBs - if err := b.cleanAllBlockDBs(); err != nil { + if err := b.cleanAllBlockDBs(ctx); err != nil { return err } diff --git a/api/service/stagedstreamsync/stage_epoch.go b/api/service/stagedstreamsync/stage_epoch.go index 77dc57bfdd..394a1d5d69 100644 --- a/api/service/stagedstreamsync/stage_epoch.go +++ b/api/service/stagedstreamsync/stage_epoch.go @@ -15,9 +15,8 @@ type StageEpoch struct { } type StageEpochCfg struct { - ctx context.Context - bc core.BlockChain - db kv.RwDB + bc core.BlockChain + db kv.RwDB } func NewStageEpoch(cfg StageEpochCfg) *StageEpoch { @@ -26,19 +25,14 @@ func NewStageEpoch(cfg StageEpochCfg) *StageEpoch { } } -func NewStageEpochCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB) StageEpochCfg { +func NewStageEpochCfg(bc core.BlockChain, db kv.RwDB) StageEpochCfg { return StageEpochCfg{ - ctx: ctx, - bc: bc, - db: db, + bc: bc, + db: db, } } -func (sr *StageEpoch) SetStageContext(ctx context.Context) { - sr.configs.ctx = ctx -} - -func (sr *StageEpoch) Exec(firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error { +func (sr *StageEpoch) Exec(ctx context.Context, firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error { // no need to update epoch chain if we are redoing the stages because of bad block if invalidBlockRevert { @@ -54,7 +48,7 @@ func (sr *StageEpoch) Exec(firstCycle bool, invalidBlockRevert bool, s *StageSta } // doShortRangeSyncForEpochSync - n, err := sr.doShortRangeSyncForEpochSync(s) + n, err := sr.doShortRangeSyncForEpochSync(ctx, s) s.state.inserted = n if err != nil { return err @@ -63,7 +57,7 @@ func (sr *StageEpoch) Exec(firstCycle bool, invalidBlockRevert bool, s *StageSta useInternalTx := tx == nil if useInternalTx { var err error - tx, err = sr.configs.db.BeginRw(sr.configs.ctx) + tx, err = sr.configs.db.BeginRw(ctx) if err != nil { return err } @@ -79,17 +73,16 @@ func (sr *StageEpoch) Exec(firstCycle bool, invalidBlockRevert bool, s *StageSta return nil } -func (sr *StageEpoch) doShortRangeSyncForEpochSync(s *StageState) (int, error) { +func (sr *StageEpoch) doShortRangeSyncForEpochSync(ctx context.Context, s *StageState) (int, error) { numShortRangeCounterVec.With(s.state.promLabels()).Inc() - srCtx, cancel := context.WithTimeout(s.state.ctx, ShortRangeTimeout) + ctx, cancel := context.WithTimeout(ctx, ShortRangeTimeout) defer cancel() //TODO: merge srHelper with StageEpochConfig sh := &srHelper{ syncProtocol: s.state.protocol, - ctx: srCtx, config: s.state.config, logger: utils.Logger().With().Str("mode", "epoch chain short range").Logger(), } @@ -116,7 +109,7 @@ func (sr *StageEpoch) doShortRangeSyncForEpochSync(s *StageState) (int, error) { } //////////////////////////////////////////////////////// - hashChain, whitelist, err := sh.getHashChain(bns) + hashChain, whitelist, err := sh.getHashChain(ctx, bns) if err != nil { return 0, errors.Wrap(err, "getHashChain") } @@ -124,7 +117,7 @@ func (sr *StageEpoch) doShortRangeSyncForEpochSync(s *StageState) (int, error) { // short circuit for no sync is needed return 0, nil } - blocks, streamID, err := sh.getBlocksByHashes(hashChain, whitelist) + blocks, streamID, err := sh.getBlocksByHashes(ctx, hashChain, whitelist) if err != nil { utils.Logger().Warn().Err(err).Msg("epoch sync getBlocksByHashes failed") if !errors.Is(err, context.Canceled) { @@ -157,10 +150,10 @@ func (sr *StageEpoch) doShortRangeSyncForEpochSync(s *StageState) (int, error) { return n, nil } -func (sr *StageEpoch) Revert(firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { +func (sr *StageEpoch) Revert(ctx context.Context, firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = sr.configs.db.BeginRw(context.Background()) + tx, err = sr.configs.db.BeginRw(ctx) if err != nil { return err } @@ -179,10 +172,10 @@ func (sr *StageEpoch) Revert(firstCycle bool, u *RevertState, s *StageState, tx return nil } -func (sr *StageEpoch) CleanUp(firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { +func (sr *StageEpoch) CleanUp(ctx context.Context, firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = sr.configs.db.BeginRw(context.Background()) + tx, err = sr.configs.db.BeginRw(ctx) if err != nil { return err } diff --git a/api/service/stagedstreamsync/stage_finish.go b/api/service/stagedstreamsync/stage_finish.go index 9039b5588d..0dfae53ae2 100644 --- a/api/service/stagedstreamsync/stage_finish.go +++ b/api/service/stagedstreamsync/stage_finish.go @@ -11,8 +11,7 @@ type StageFinish struct { } type StageFinishCfg struct { - ctx context.Context - db kv.RwDB + db kv.RwDB } func NewStageFinish(cfg StageFinishCfg) *StageFinish { @@ -21,22 +20,17 @@ func NewStageFinish(cfg StageFinishCfg) *StageFinish { } } -func NewStageFinishCfg(ctx context.Context, db kv.RwDB) StageFinishCfg { +func NewStageFinishCfg(db kv.RwDB) StageFinishCfg { return StageFinishCfg{ - ctx: ctx, - db: db, + db: db, } } -func (finish *StageFinish) SetStageContext(ctx context.Context) { - finish.configs.ctx = ctx -} - -func (finish *StageFinish) Exec(firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error { +func (finish *StageFinish) Exec(ctx context.Context, firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error { useInternalTx := tx == nil if useInternalTx { var err error - tx, err = finish.configs.db.BeginRw(context.Background()) + tx, err = finish.configs.db.BeginRw(ctx) if err != nil { return err } @@ -54,11 +48,11 @@ func (finish *StageFinish) Exec(firstCycle bool, invalidBlockRevert bool, s *Sta return nil } -func (bh *StageFinish) clearBucket(tx kv.RwTx, isBeacon bool) error { +func (finish *StageFinish) clearBucket(ctx context.Context, tx kv.RwTx, isBeacon bool) error { useInternalTx := tx == nil if useInternalTx { var err error - tx, err = bh.configs.db.BeginRw(context.Background()) + tx, err = finish.configs.db.BeginRw(ctx) if err != nil { return err } @@ -73,10 +67,10 @@ func (bh *StageFinish) clearBucket(tx kv.RwTx, isBeacon bool) error { return nil } -func (finish *StageFinish) Revert(firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { +func (finish *StageFinish) Revert(ctx context.Context, firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = finish.configs.db.BeginRw(finish.configs.ctx) + tx, err = finish.configs.db.BeginRw(ctx) if err != nil { return err } @@ -95,10 +89,10 @@ func (finish *StageFinish) Revert(firstCycle bool, u *RevertState, s *StageState return nil } -func (finish *StageFinish) CleanUp(firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { +func (finish *StageFinish) CleanUp(ctx context.Context, firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = finish.configs.db.BeginRw(finish.configs.ctx) + tx, err = finish.configs.db.BeginRw(ctx) if err != nil { return err } diff --git a/api/service/stagedstreamsync/stage_heads.go b/api/service/stagedstreamsync/stage_heads.go index 8e1531a5ee..c917884a36 100644 --- a/api/service/stagedstreamsync/stage_heads.go +++ b/api/service/stagedstreamsync/stage_heads.go @@ -13,9 +13,8 @@ type StageHeads struct { } type StageHeadsCfg struct { - ctx context.Context - bc core.BlockChain - db kv.RwDB + bc core.BlockChain + db kv.RwDB } func NewStageHeads(cfg StageHeadsCfg) *StageHeads { @@ -24,20 +23,14 @@ func NewStageHeads(cfg StageHeadsCfg) *StageHeads { } } -func NewStageHeadersCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB) StageHeadsCfg { +func NewStageHeadersCfg(bc core.BlockChain, db kv.RwDB) StageHeadsCfg { return StageHeadsCfg{ - ctx: ctx, - bc: bc, - db: db, + bc: bc, + db: db, } } -func (heads *StageHeads) SetStageContext(ctx context.Context) { - heads.configs.ctx = ctx -} - -func (heads *StageHeads) Exec(firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error { - +func (heads *StageHeads) Exec(ctx context.Context, firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error { // no need to update target if we are redoing the stages because of bad block if invalidBlockRevert { return nil @@ -51,7 +44,7 @@ func (heads *StageHeads) Exec(firstCycle bool, invalidBlockRevert bool, s *Stage useInternalTx := tx == nil if useInternalTx { var err error - tx, err = heads.configs.db.BeginRw(heads.configs.ctx) + tx, err = heads.configs.db.BeginRw(ctx) if err != nil { return err } @@ -63,7 +56,7 @@ func (heads *StageHeads) Exec(firstCycle bool, invalidBlockRevert bool, s *Stage currentHeight := heads.configs.bc.CurrentBlock().NumberU64() s.state.currentCycle.TargetHeight = maxHeight targetHeight := uint64(0) - if errV := CreateView(heads.configs.ctx, heads.configs.db, tx, func(etx kv.Tx) (err error) { + if errV := CreateView(ctx, heads.configs.db, tx, func(etx kv.Tx) (err error) { if targetHeight, err = s.CurrentStageProgress(etx); err != nil { return err } @@ -114,10 +107,10 @@ func (heads *StageHeads) Exec(firstCycle bool, invalidBlockRevert bool, s *Stage return nil } -func (heads *StageHeads) Revert(firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { +func (heads *StageHeads) Revert(ctx context.Context, firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = heads.configs.db.BeginRw(context.Background()) + tx, err = heads.configs.db.BeginRw(ctx) if err != nil { return err } @@ -136,10 +129,10 @@ func (heads *StageHeads) Revert(firstCycle bool, u *RevertState, s *StageState, return nil } -func (heads *StageHeads) CleanUp(firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { +func (heads *StageHeads) CleanUp(ctx context.Context, firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = heads.configs.db.BeginRw(context.Background()) + tx, err = heads.configs.db.BeginRw(ctx) if err != nil { return err } diff --git a/api/service/stagedstreamsync/stage_short_range.go b/api/service/stagedstreamsync/stage_short_range.go index 75f51ee1e7..8fb2f3059e 100644 --- a/api/service/stagedstreamsync/stage_short_range.go +++ b/api/service/stagedstreamsync/stage_short_range.go @@ -16,9 +16,8 @@ type StageShortRange struct { } type StageShortRangeCfg struct { - ctx context.Context - bc core.BlockChain - db kv.RwDB + bc core.BlockChain + db kv.RwDB } func NewStageShortRange(cfg StageShortRangeCfg) *StageShortRange { @@ -27,20 +26,14 @@ func NewStageShortRange(cfg StageShortRangeCfg) *StageShortRange { } } -func NewStageShortRangeCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB) StageShortRangeCfg { +func NewStageShortRangeCfg(bc core.BlockChain, db kv.RwDB) StageShortRangeCfg { return StageShortRangeCfg{ - ctx: ctx, - bc: bc, - db: db, + bc: bc, + db: db, } } -func (sr *StageShortRange) SetStageContext(ctx context.Context) { - sr.configs.ctx = ctx -} - -func (sr *StageShortRange) Exec(firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error { - +func (sr *StageShortRange) Exec(ctx context.Context, firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) error { // no need to do short range if we are redoing the stages because of bad block if invalidBlockRevert { return nil @@ -56,7 +49,7 @@ func (sr *StageShortRange) Exec(firstCycle bool, invalidBlockRevert bool, s *Sta } // do short range sync - n, err := sr.doShortRangeSync(s) + n, err := sr.doShortRangeSync(ctx, s) s.state.inserted = n if err != nil { return err @@ -65,7 +58,7 @@ func (sr *StageShortRange) Exec(firstCycle bool, invalidBlockRevert bool, s *Sta useInternalTx := tx == nil if useInternalTx { var err error - tx, err = sr.configs.db.BeginRw(sr.configs.ctx) + tx, err = sr.configs.db.BeginRw(ctx) if err != nil { return err } @@ -87,16 +80,13 @@ func (sr *StageShortRange) Exec(firstCycle bool, invalidBlockRevert bool, s *Sta // 1. Obtain the block hashes and compute the longest hash chain.. // 2. Get blocks by hashes from computed hash chain. // 3. Insert the blocks to blockchain. -func (sr *StageShortRange) doShortRangeSync(s *StageState) (int, error) { - +func (sr *StageShortRange) doShortRangeSync(ctx context.Context, s *StageState) (int, error) { numShortRangeCounterVec.With(s.state.promLabels()).Inc() - - srCtx, cancel := context.WithTimeout(s.state.ctx, ShortRangeTimeout) + ctx, cancel := context.WithTimeout(ctx, ShortRangeTimeout) defer cancel() sh := &srHelper{ syncProtocol: s.state.protocol, - ctx: srCtx, config: s.state.config, logger: utils.Logger().With().Str("mode", "short range").Logger(), } @@ -106,7 +96,7 @@ func (sr *StageShortRange) doShortRangeSync(s *StageState) (int, error) { } curBN := sr.configs.bc.CurrentBlock().NumberU64() blkNums := sh.prepareBlockHashNumbers(curBN) - hashChain, whitelist, err := sh.getHashChain(blkNums) + hashChain, whitelist, err := sh.getHashChain(ctx, blkNums) if err != nil { return 0, errors.Wrap(err, "getHashChain") } @@ -130,7 +120,7 @@ func (sr *StageShortRange) doShortRangeSync(s *StageState) (int, error) { s.state.status.finishSyncing() }() - blocks, stids, err := sh.getBlocksByHashes(hashChain, whitelist) + blocks, stids, err := sh.getBlocksByHashes(ctx, hashChain, whitelist) if err != nil { utils.Logger().Warn().Err(err).Msg("getBlocksByHashes failed") if !errors.Is(err, context.Canceled) { @@ -159,10 +149,10 @@ func (sr *StageShortRange) doShortRangeSync(s *StageState) (int, error) { return n, nil } -func (sr *StageShortRange) Revert(firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { +func (sr *StageShortRange) Revert(ctx context.Context, firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = sr.configs.db.BeginRw(context.Background()) + tx, err = sr.configs.db.BeginRw(ctx) if err != nil { return err } @@ -181,10 +171,10 @@ func (sr *StageShortRange) Revert(firstCycle bool, u *RevertState, s *StageState return nil } -func (sr *StageShortRange) CleanUp(firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { +func (sr *StageShortRange) CleanUp(ctx context.Context, firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = sr.configs.db.BeginRw(context.Background()) + tx, err = sr.configs.db.BeginRw(ctx) if err != nil { return err } diff --git a/api/service/stagedstreamsync/stage_state.go b/api/service/stagedstreamsync/stage_state.go index 9eda042477..4b237c2916 100644 --- a/api/service/stagedstreamsync/stage_state.go +++ b/api/service/stagedstreamsync/stage_state.go @@ -11,7 +11,6 @@ import ( "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/internal/utils" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/prometheus/client_golang/prometheus" "github.com/rs/zerolog" ) @@ -19,7 +18,6 @@ type StageStates struct { configs StageStatesCfg } type StageStatesCfg struct { - ctx context.Context bc core.BlockChain db kv.RwDB blockDBs []kv.RwDB @@ -34,7 +32,7 @@ func NewStageStates(cfg StageStatesCfg) *StageStates { } } -func NewStageStatesCfg(ctx context.Context, +func NewStageStatesCfg( bc core.BlockChain, db kv.RwDB, blockDBs []kv.RwDB, @@ -43,7 +41,6 @@ func NewStageStatesCfg(ctx context.Context, logProgress bool) StageStatesCfg { return StageStatesCfg{ - ctx: ctx, bc: bc, db: db, blockDBs: blockDBs, @@ -53,13 +50,8 @@ func NewStageStatesCfg(ctx context.Context, } } -func (stg *StageStates) SetStageContext(ctx context.Context) { - stg.configs.ctx = ctx -} - // Exec progresses States stage in the forward direction -func (stg *StageStates) Exec(firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) (err error) { - +func (stg *StageStates) Exec(ctx context.Context, firstCycle bool, invalidBlockRevert bool, s *StageState, reverter Reverter, tx kv.RwTx) (err error) { // for short range sync, skip this step if !s.state.initSync { return nil @@ -78,7 +70,7 @@ func (stg *StageStates) Exec(firstCycle bool, invalidBlockRevert bool, s *StageS useInternalTx := tx == nil if useInternalTx { var err error - tx, err = stg.configs.db.BeginRw(stg.configs.ctx) + tx, err = stg.configs.db.BeginRw(ctx) if err != nil { return err } @@ -94,7 +86,7 @@ func (stg *StageStates) Exec(firstCycle bool, invalidBlockRevert bool, s *StageS // prepare db transactions txs := make([]kv.RwTx, stg.configs.concurrency) for i := 0; i < stg.configs.concurrency; i++ { - txs[i], err = stg.configs.blockDBs[i].BeginRw(context.Background()) + txs[i], err = stg.configs.blockDBs[i].BeginRw(ctx) if err != nil { return err } @@ -219,19 +211,11 @@ func (stg *StageStates) Exec(firstCycle bool, invalidBlockRevert bool, s *StageS return nil } -func (stg *StageStates) insertChain(gbm *blockDownloadManager, - protocol syncProtocol, - lbls prometheus.Labels, - targetBN uint64) { - -} - -func (stg *StageStates) saveProgress(s *StageState, tx kv.RwTx) (err error) { - +func (stg *StageStates) saveProgress(ctx context.Context, s *StageState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { var err error - tx, err = stg.configs.db.BeginRw(context.Background()) + tx, err = stg.configs.db.BeginRw(ctx) if err != nil { return err } @@ -254,10 +238,10 @@ func (stg *StageStates) saveProgress(s *StageState, tx kv.RwTx) (err error) { return nil } -func (stg *StageStates) Revert(firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { +func (stg *StageStates) Revert(ctx context.Context, firstCycle bool, u *RevertState, s *StageState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = stg.configs.db.BeginRw(stg.configs.ctx) + tx, err = stg.configs.db.BeginRw(ctx) if err != nil { return err } @@ -276,10 +260,10 @@ func (stg *StageStates) Revert(firstCycle bool, u *RevertState, s *StageState, t return nil } -func (stg *StageStates) CleanUp(firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { +func (stg *StageStates) CleanUp(ctx context.Context, firstCycle bool, p *CleanUpState, tx kv.RwTx) (err error) { useInternalTx := tx == nil if useInternalTx { - tx, err = stg.configs.db.BeginRw(stg.configs.ctx) + tx, err = stg.configs.db.BeginRw(ctx) if err != nil { return err } diff --git a/api/service/stagedstreamsync/staged_stream_sync.go b/api/service/stagedstreamsync/staged_stream_sync.go index e73edd622f..6c1eec4c37 100644 --- a/api/service/stagedstreamsync/staged_stream_sync.go +++ b/api/service/stagedstreamsync/staged_stream_sync.go @@ -54,7 +54,6 @@ func (ib *InvalidBlock) addBadStream(bsID sttypes.StreamID) { } type StagedStreamSync struct { - ctx context.Context bc core.BlockChain isBeacon bool isExplorer bool @@ -101,7 +100,6 @@ type SyncCycle struct { } func (s *StagedStreamSync) Len() int { return len(s.stages) } -func (s *StagedStreamSync) Context() context.Context { return s.ctx } func (s *StagedStreamSync) Blockchain() core.BlockChain { return s.bc } func (s *StagedStreamSync) DB() kv.RwDB { return s.db } func (s *StagedStreamSync) IsBeacon() bool { return s.isBeacon } @@ -118,11 +116,11 @@ func (s *StagedStreamSync) NewRevertState(id SyncStageID, revertPoint uint64) *R return &RevertState{id, revertPoint, s} } -func (s *StagedStreamSync) CleanUpStageState(id SyncStageID, forwardProgress uint64, tx kv.Tx, db kv.RwDB) (*CleanUpState, error) { +func (s *StagedStreamSync) CleanUpStageState(ctx context.Context, id SyncStageID, forwardProgress uint64, tx kv.Tx, db kv.RwDB) (*CleanUpState, error) { var pruneProgress uint64 var err error - if errV := CreateView(context.Background(), db, tx, func(tx kv.Tx) error { + if errV := CreateView(ctx, db, tx, func(tx kv.Tx) error { pruneProgress, err = GetStageCleanUpProgress(tx, id, s.isBeacon) if err != nil { return err @@ -215,10 +213,10 @@ func (s *StagedStreamSync) SetCurrentStage(id SyncStageID) error { } // StageState retrieves the latest stage state from db -func (s *StagedStreamSync) StageState(stage SyncStageID, tx kv.Tx, db kv.RwDB) (*StageState, error) { +func (s *StagedStreamSync) StageState(ctx context.Context, stage SyncStageID, tx kv.Tx, db kv.RwDB) (*StageState, error) { var blockNum uint64 var err error - if errV := CreateView(context.Background(), db, tx, func(rtx kv.Tx) error { + if errV := CreateView(ctx, db, tx, func(rtx kv.Tx) error { blockNum, err = GetStageProgress(rtx, stage, s.isBeacon) if err != nil { return err @@ -232,7 +230,7 @@ func (s *StagedStreamSync) StageState(stage SyncStageID, tx kv.Tx, db kv.RwDB) ( } // cleanUp cleans up the stage by calling pruneStage -func (s *StagedStreamSync) cleanUp(fromStage int, db kv.RwDB, tx kv.RwTx, firstCycle bool) error { +func (s *StagedStreamSync) cleanUp(ctx context.Context, fromStage int, db kv.RwDB, tx kv.RwTx, firstCycle bool) error { found := false for i := 0; i < len(s.pruningOrder); i++ { if s.pruningOrder[i].ID == s.stages[fromStage].ID { @@ -241,7 +239,7 @@ func (s *StagedStreamSync) cleanUp(fromStage int, db kv.RwDB, tx kv.RwTx, firstC if !found || s.pruningOrder[i] == nil || s.pruningOrder[i].Disabled { continue } - if err := s.pruneStage(firstCycle, s.pruningOrder[i], db, tx); err != nil { + if err := s.pruneStage(ctx, firstCycle, s.pruningOrder[i], db, tx); err != nil { panic(err) } } @@ -249,7 +247,7 @@ func (s *StagedStreamSync) cleanUp(fromStage int, db kv.RwDB, tx kv.RwTx, firstC } // New creates a new StagedStreamSync instance -func New(ctx context.Context, +func New( bc core.BlockChain, db kv.RwDB, stagesList []*Stage, @@ -288,7 +286,6 @@ func New(ctx context.Context, status := newStatus() return &StagedStreamSync{ - ctx: ctx, bc: bc, isBeacon: isBeacon, db: db, @@ -309,8 +306,8 @@ func New(ctx context.Context, } // doGetCurrentNumberRequest returns estimated current block number and corresponding stream -func (s *StagedStreamSync) doGetCurrentNumberRequest() (uint64, sttypes.StreamID, error) { - ctx, cancel := context.WithTimeout(s.ctx, 10*time.Second) +func (s *StagedStreamSync) doGetCurrentNumberRequest(ctx context.Context) (uint64, sttypes.StreamID, error) { + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() bn, stid, err := s.protocol.GetCurrentBlockNumber(ctx, syncproto.WithHighPriority()) @@ -336,16 +333,8 @@ func (s *StagedStreamSync) checkHaveEnoughStreams() error { return nil } -// SetNewContext sets a new context for all stages -func (s *StagedStreamSync) SetNewContext(ctx context.Context) error { - for _, s := range s.stages { - s.Handler.SetStageContext(ctx) - } - return nil -} - // Run runs a full cycle of stages -func (s *StagedStreamSync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { +func (s *StagedStreamSync) Run(ctx context.Context, db kv.RwDB, tx kv.RwTx, firstCycle bool) error { s.prevRevertPoint = nil s.timings = s.timings[:0] @@ -358,7 +347,7 @@ func (s *StagedStreamSync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { if s.revertOrder[j] == nil || s.revertOrder[j].Disabled { continue } - if err := s.revertStage(firstCycle, s.revertOrder[j], db, tx); err != nil { + if err := s.revertStage(ctx, firstCycle, s.revertOrder[j], db, tx); err != nil { utils.Logger().Error(). Err(err). Interface("stage id", s.revertOrder[j].ID). @@ -383,7 +372,7 @@ func (s *StagedStreamSync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { continue } - if err := s.runStage(stage, db, tx, firstCycle, s.invalidBlock.Active); err != nil { + if err := s.runStage(ctx, stage, db, tx, firstCycle, s.invalidBlock.Active); err != nil { utils.Logger().Error(). Err(err). Interface("stage id", stage.ID). @@ -393,7 +382,7 @@ func (s *StagedStreamSync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { s.NextStage() } - if err := s.cleanUp(0, db, tx, firstCycle); err != nil { + if err := s.cleanUp(ctx, 0, db, tx, firstCycle); err != nil { utils.Logger().Error(). Err(err). Msgf(WrapStagedSyncMsg("stages cleanup failed")) @@ -403,7 +392,7 @@ func (s *StagedStreamSync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { return err } if err := printLogs(tx, s.timings); err != nil { - return err + utils.Logger().Warn().Err(err).Msg("print timing logs failed") } s.currentStage = 0 return nil @@ -414,7 +403,7 @@ func CreateView(ctx context.Context, db kv.RwDB, tx kv.Tx, f func(tx kv.Tx) erro if tx != nil { return f(tx) } - return db.View(context.Background(), func(etx kv.Tx) error { + return db.View(ctx, func(etx kv.Tx) error { return f(etx) }) } @@ -440,8 +429,8 @@ func printLogs(tx kv.RwTx, timings []Timing) error { } } if len(logCtx) > 0 { - utils.Logger().Info(). - Msgf(WrapStagedSyncMsg(fmt.Sprintf("Timings (slower than 50ms) %v", logCtx...))) + timingLog := fmt.Sprintf("Timings (slower than 50ms) %v", logCtx) + utils.Logger().Info().Msgf(WrapStagedSyncMsg(timingLog)) } if tx == nil { @@ -466,14 +455,14 @@ func printLogs(tx kv.RwTx, timings []Timing) error { } // runStage executes stage -func (s *StagedStreamSync) runStage(stage *Stage, db kv.RwDB, tx kv.RwTx, firstCycle bool, invalidBlockRevert bool) (err error) { +func (s *StagedStreamSync) runStage(ctx context.Context, stage *Stage, db kv.RwDB, tx kv.RwTx, firstCycle bool, invalidBlockRevert bool) (err error) { start := time.Now() - stageState, err := s.StageState(stage.ID, tx, db) + stageState, err := s.StageState(ctx, stage.ID, tx, db) if err != nil { return err } - if err = stage.Handler.Exec(firstCycle, invalidBlockRevert, stageState, s, tx); err != nil { + if err = stage.Handler.Exec(ctx, firstCycle, invalidBlockRevert, stageState, s, tx); err != nil { utils.Logger().Error(). Err(err). Interface("stage id", stage.ID). @@ -493,9 +482,9 @@ func (s *StagedStreamSync) runStage(stage *Stage, db kv.RwDB, tx kv.RwTx, firstC } // revertStage reverts stage -func (s *StagedStreamSync) revertStage(firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx) error { +func (s *StagedStreamSync) revertStage(ctx context.Context, firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx) error { start := time.Now() - stageState, err := s.StageState(stage.ID, tx, db) + stageState, err := s.StageState(ctx, stage.ID, tx, db) if err != nil { return err } @@ -510,7 +499,7 @@ func (s *StagedStreamSync) revertStage(firstCycle bool, stage *Stage, db kv.RwDB return err } - err = stage.Handler.Revert(firstCycle, revert, stageState, tx) + err = stage.Handler.Revert(ctx, firstCycle, revert, stageState, tx) if err != nil { return fmt.Errorf("[%s] %w", s.LogPrefix(), err) } @@ -526,15 +515,15 @@ func (s *StagedStreamSync) revertStage(firstCycle bool, stage *Stage, db kv.RwDB } // pruneStage cleans up the stage and logs the timing -func (s *StagedStreamSync) pruneStage(firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx) error { +func (s *StagedStreamSync) pruneStage(ctx context.Context, firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx) error { start := time.Now() - stageState, err := s.StageState(stage.ID, tx, db) + stageState, err := s.StageState(ctx, stage.ID, tx, db) if err != nil { return err } - prune, err := s.CleanUpStageState(stage.ID, stageState.BlockNumber, tx, db) + prune, err := s.CleanUpStageState(ctx, stage.ID, stageState.BlockNumber, tx, db) if err != nil { return err } @@ -542,7 +531,7 @@ func (s *StagedStreamSync) pruneStage(firstCycle bool, stage *Stage, db kv.RwDB, return err } - err = stage.Handler.CleanUp(firstCycle, prune, tx) + err = stage.Handler.CleanUp(ctx, firstCycle, prune, tx) if err != nil { return fmt.Errorf("[%s] %w", s.LogPrefix(), err) } diff --git a/api/service/stagedstreamsync/syncing.go b/api/service/stagedstreamsync/syncing.go index de9b884816..ebef810b19 100644 --- a/api/service/stagedstreamsync/syncing.go +++ b/api/service/stagedstreamsync/syncing.go @@ -3,6 +3,7 @@ package stagedstreamsync import ( "context" "fmt" + "path/filepath" "sync" "time" @@ -37,6 +38,7 @@ var Buckets = []string{ // CreateStagedSync creates an instance of staged sync func CreateStagedSync(ctx context.Context, bc core.BlockChain, + dbDir string, UseMemDB bool, isBeaconNode bool, protocol syncProtocol, @@ -50,14 +52,14 @@ func CreateStagedSync(ctx context.Context, var mainDB kv.RwDB dbs := make([]kv.RwDB, config.Concurrency) if UseMemDB { - mainDB = memdb.New() + mainDB = memdb.New(getMemDbTempPath(dbDir, -1)) for i := 0; i < config.Concurrency; i++ { - dbs[i] = memdb.New() + dbs[i] = memdb.New(getMemDbTempPath(dbDir, i)) } } else { - mainDB = mdbx.NewMDBX(log.New()).Path(GetBlockDbPath(isBeacon, -1)).MustOpen() + mainDB = mdbx.NewMDBX(log.New()).Path(getBlockDbPath(isBeacon, -1, dbDir)).MustOpen() for i := 0; i < config.Concurrency; i++ { - dbPath := GetBlockDbPath(isBeacon, i) + dbPath := getBlockDbPath(isBeacon, i, dbDir) dbs[i] = mdbx.NewMDBX(log.New()).Path(dbPath).MustOpen() } } @@ -66,12 +68,12 @@ func CreateStagedSync(ctx context.Context, return nil, errInitDB } - stageHeadsCfg := NewStageHeadersCfg(ctx, bc, mainDB) - stageShortRangeCfg := NewStageShortRangeCfg(ctx, bc, mainDB) - stageSyncEpochCfg := NewStageEpochCfg(ctx, bc, mainDB) - stageBodiesCfg := NewStageBodiesCfg(ctx, bc, mainDB, dbs, config.Concurrency, protocol, isBeacon, logProgress) - stageStatesCfg := NewStageStatesCfg(ctx, bc, mainDB, dbs, config.Concurrency, logger, logProgress) - stageFinishCfg := NewStageFinishCfg(ctx, mainDB) + stageHeadsCfg := NewStageHeadersCfg(bc, mainDB) + stageShortRangeCfg := NewStageShortRangeCfg(bc, mainDB) + stageSyncEpochCfg := NewStageEpochCfg(bc, mainDB) + stageBodiesCfg := NewStageBodiesCfg(bc, mainDB, dbs, config.Concurrency, protocol, isBeacon, logProgress) + stageStatesCfg := NewStageStatesCfg(bc, mainDB, dbs, config.Concurrency, logger, logProgress) + stageFinishCfg := NewStageFinishCfg(mainDB) stages := DefaultStages(ctx, stageHeadsCfg, @@ -82,7 +84,7 @@ func CreateStagedSync(ctx context.Context, stageFinishCfg, ) - return New(ctx, + return New( bc, mainDB, stages, @@ -136,19 +138,27 @@ func initDB(ctx context.Context, mainDB kv.RwDB, dbs []kv.RwDB, concurrency int) return nil } -// GetBlockDbPath returns the path of the cache database which stores blocks -func GetBlockDbPath(beacon bool, loopID int) string { +// getMemDbTempPath returns the path of the temporary cache database for memdb +func getMemDbTempPath(dbDir string, dbIndex int) string { + if dbIndex >= 0 { + return fmt.Sprintf("%s_%d", filepath.Join(dbDir, "cache/memdb/db"), dbIndex) + } + return filepath.Join(dbDir, "cache/memdb/db_main") +} + +// getBlockDbPath returns the path of the cache database which stores blocks +func getBlockDbPath(beacon bool, loopID int, dbDir string) string { if beacon { if loopID >= 0 { - return fmt.Sprintf("%s_%d", "cache/beacon_blocks_db", loopID) + return fmt.Sprintf("%s_%d", filepath.Join(dbDir, "cache/beacon_blocks_db"), loopID) } else { - return "cache/beacon_blocks_db_main" + return filepath.Join(dbDir, "cache/beacon_blocks_db_main") } } else { if loopID >= 0 { - return fmt.Sprintf("%s_%d", "cache/blocks_db", loopID) + return fmt.Sprintf("%s_%d", filepath.Join(dbDir, "cache/blocks_db"), loopID) } else { - return "cache/blocks_db_main" + return filepath.Join(dbDir, "cache/blocks_db_main") } } } @@ -168,7 +178,7 @@ func (s *StagedStreamSync) doSync(downloaderContext context.Context, initSync bo var estimatedHeight uint64 if initSync { - if h, err := s.estimateCurrentNumber(); err != nil { + if h, err := s.estimateCurrentNumber(downloaderContext); err != nil { return 0, err } else { estimatedHeight = h @@ -187,8 +197,6 @@ func (s *StagedStreamSync) doSync(downloaderContext context.Context, initSync bo for { ctx, cancel := context.WithCancel(downloaderContext) - s.ctx = ctx - s.SetNewContext(ctx) n, err := s.doSyncCycle(ctx, initSync) if err != nil { @@ -224,7 +232,7 @@ func (s *StagedStreamSync) doSyncCycle(ctx context.Context, initSync bool) (int, var tx kv.RwTx if canRunCycleInOneTransaction { var err error - if tx, err = s.DB().BeginRw(context.Background()); err != nil { + if tx, err = s.DB().BeginRw(ctx); err != nil { return totalInserted, err } defer tx.Rollback() @@ -234,7 +242,7 @@ func (s *StagedStreamSync) doSyncCycle(ctx context.Context, initSync bool) (int, // Do one cycle of staged sync initialCycle := s.currentCycle.Number == 0 - if err := s.Run(s.DB(), tx, initialCycle); err != nil { + if err := s.Run(ctx, s.DB(), tx, initialCycle); err != nil { utils.Logger().Error(). Err(err). Bool("isBeacon", s.isBeacon). @@ -284,7 +292,7 @@ func (s *StagedStreamSync) checkPrerequisites() error { // estimateCurrentNumber roughly estimates the current block number. // The block number does not need to be exact, but just a temporary target of the iteration -func (s *StagedStreamSync) estimateCurrentNumber() (uint64, error) { +func (s *StagedStreamSync) estimateCurrentNumber(ctx context.Context) (uint64, error) { var ( cnResults = make(map[sttypes.StreamID]uint64) lock sync.Mutex @@ -294,7 +302,7 @@ func (s *StagedStreamSync) estimateCurrentNumber() (uint64, error) { for i := 0; i != s.config.Concurrency; i++ { go func() { defer wg.Done() - bn, stid, err := s.doGetCurrentNumberRequest() + bn, stid, err := s.doGetCurrentNumberRequest(ctx) if err != nil { s.logger.Err(err).Str("streamID", string(stid)). Msg(WrapStagedSyncMsg("getCurrentNumber request failed")) @@ -312,8 +320,8 @@ func (s *StagedStreamSync) estimateCurrentNumber() (uint64, error) { if len(cnResults) == 0 { select { - case <-s.ctx.Done(): - return 0, s.ctx.Err() + case <-ctx.Done(): + return 0, ctx.Err() default: } return 0, ErrZeroBlockResponse diff --git a/api/service/stagedsync/stage_blockhashes.go b/api/service/stagedsync/stage_blockhashes.go index 1f049d52a9..61e0718dbd 100644 --- a/api/service/stagedsync/stage_blockhashes.go +++ b/api/service/stagedsync/stage_blockhashes.go @@ -4,6 +4,7 @@ import ( "context" "encoding/hex" "fmt" + "path/filepath" "strconv" "time" @@ -37,8 +38,8 @@ func NewStageBlockHashes(cfg StageBlockHashesCfg) *StageBlockHashes { } } -func NewStageBlockHashesCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB, isBeacon bool, turbo bool, logProgress bool) StageBlockHashesCfg { - cachedb, err := initHashesCacheDB(ctx, isBeacon) +func NewStageBlockHashesCfg(ctx context.Context, bc core.BlockChain, dbDir string, db kv.RwDB, isBeacon bool, turbo bool, logProgress bool) StageBlockHashesCfg { + cachedb, err := initHashesCacheDB(ctx, dbDir, isBeacon) if err != nil { panic("can't initialize sync caches") } @@ -53,13 +54,14 @@ func NewStageBlockHashesCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB, } } -func initHashesCacheDB(ctx context.Context, isBeacon bool) (db kv.RwDB, err error) { +func initHashesCacheDB(ctx context.Context, dbDir string, isBeacon bool) (db kv.RwDB, err error) { // create caches db cachedbName := BlockHashesCacheDB if isBeacon { cachedbName = "beacon_" + cachedbName } - cachedb := mdbx.NewMDBX(log.New()).Path(cachedbName).MustOpen() + dbPath := filepath.Join(dbDir, cachedbName) + cachedb := mdbx.NewMDBX(log.New()).Path(dbPath).MustOpen() // create transaction on cachedb tx, errRW := cachedb.BeginRw(ctx) if errRW != nil { diff --git a/api/service/stagedsync/stage_bodies.go b/api/service/stagedsync/stage_bodies.go index 5f0d4a5827..c3f91f0154 100644 --- a/api/service/stagedsync/stage_bodies.go +++ b/api/service/stagedsync/stage_bodies.go @@ -4,6 +4,7 @@ import ( "context" "encoding/hex" "fmt" + "path/filepath" "strconv" "sync" "time" @@ -37,8 +38,8 @@ func NewStageBodies(cfg StageBodiesCfg) *StageBodies { } } -func NewStageBodiesCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB, isBeacon bool, turbo bool, logProgress bool) StageBodiesCfg { - cachedb, err := initBlocksCacheDB(ctx, isBeacon) +func NewStageBodiesCfg(ctx context.Context, bc core.BlockChain, dbDir string, db kv.RwDB, isBeacon bool, turbo bool, logProgress bool) StageBodiesCfg { + cachedb, err := initBlocksCacheDB(ctx, dbDir, isBeacon) if err != nil { panic("can't initialize sync caches") } @@ -53,13 +54,14 @@ func NewStageBodiesCfg(ctx context.Context, bc core.BlockChain, db kv.RwDB, isBe } } -func initBlocksCacheDB(ctx context.Context, isBeacon bool) (db kv.RwDB, err error) { +func initBlocksCacheDB(ctx context.Context, dbDir string, isBeacon bool) (db kv.RwDB, err error) { // create caches db cachedbName := BlockCacheDB if isBeacon { cachedbName = "beacon_" + cachedbName } - cachedb := mdbx.NewMDBX(log.New()).Path(cachedbName).MustOpen() + dbPath := filepath.Join(dbDir, cachedbName) + cachedb := mdbx.NewMDBX(log.New()).Path(dbPath).MustOpen() tx, errRW := cachedb.BeginRw(ctx) if errRW != nil { utils.Logger().Error(). diff --git a/api/service/stagedsync/syncing.go b/api/service/stagedsync/syncing.go index d204971573..11147f6a62 100644 --- a/api/service/stagedsync/syncing.go +++ b/api/service/stagedsync/syncing.go @@ -3,6 +3,7 @@ package stagedsync import ( "context" "fmt" + "path/filepath" "time" "github.com/c2h5oh/datasize" @@ -50,6 +51,7 @@ func CreateStagedSync( port string, peerHash [20]byte, bc core.BlockChain, + dbDir string, role nodeconfig.Role, isExplorer bool, TurboMode bool, @@ -82,9 +84,11 @@ func CreateStagedSync( db = mdbx.NewMDBX(log.New()).MapSize(dbMapSize).InMem("cache_db").MustOpen() } else { if isBeacon { - db = mdbx.NewMDBX(log.New()).Path("cache_beacon_db").MustOpen() + dbPath := filepath.Join(dbDir, "cache_beacon_db") + db = mdbx.NewMDBX(log.New()).Path(dbPath).MustOpen() } else { - db = mdbx.NewMDBX(log.New()).Path("cache_shard_db").MustOpen() + dbPath := filepath.Join(dbDir, "cache_shard_db") + db = mdbx.NewMDBX(log.New()).Path(dbPath).MustOpen() } } @@ -93,8 +97,8 @@ func CreateStagedSync( } headsCfg := NewStageHeadersCfg(ctx, bc, db) - blockHashesCfg := NewStageBlockHashesCfg(ctx, bc, db, isBeacon, TurboMode, logProgress) - bodiesCfg := NewStageBodiesCfg(ctx, bc, db, isBeacon, TurboMode, logProgress) + blockHashesCfg := NewStageBlockHashesCfg(ctx, bc, dbDir, db, isBeacon, TurboMode, logProgress) + bodiesCfg := NewStageBodiesCfg(ctx, bc, dbDir, db, isBeacon, TurboMode, logProgress) statesCfg := NewStageStatesCfg(ctx, bc, db, logProgress) lastMileCfg := NewStageLastMileCfg(ctx, bc, db) finishCfg := NewStageFinishCfg(ctx, db) diff --git a/block/header.go b/block/header.go index 5672446cc7..9b20535a60 100644 --- a/block/header.go +++ b/block/header.go @@ -122,6 +122,11 @@ func (h *Header) Hash() common.Hash { return hash.FromRLP(h) } +// NumberU64 returns the block number of the header as a uint64. +func (h *Header) NumberU64() uint64 { + return h.Number().Uint64() +} + // Logger returns a sub-logger with block contexts added. func (h *Header) Logger(logger *zerolog.Logger) *zerolog.Logger { nlogger := logger.With(). diff --git a/cmd/harmony/config_migrations.go b/cmd/harmony/config_migrations.go index 84607c2d0d..8f222b3d62 100644 --- a/cmd/harmony/config_migrations.go +++ b/cmd/harmony/config_migrations.go @@ -378,6 +378,33 @@ func init() { return confTree } + migrations["2.5.14"] = func(confTree *toml.Tree) *toml.Tree { + if confTree.Get("GPO.Blocks") == nil { + confTree.Set("GPO.Blocks", defaultConfig.GPO.Blocks) + } + if confTree.Get("GPO.Transactions") == nil { + confTree.Set("GPO.Transactions", defaultConfig.GPO.Transactions) + } + if confTree.Get("GPO.Percentile") == nil { + confTree.Set("GPO.Percentile", defaultConfig.GPO.Percentile) + } + if confTree.Get("GPO.DefaultPrice") == nil { + confTree.Set("GPO.DefaultPrice", defaultConfig.GPO.DefaultPrice) + } + if confTree.Get("GPO.MaxPrice") == nil { + confTree.Set("GPO.MaxPrice", defaultConfig.GPO.MaxPrice) + } + if confTree.Get("GPO.LowUsageThreshold") == nil { + confTree.Set("GPO.LowUsageThreshold", defaultConfig.GPO.LowUsageThreshold) + } + if confTree.Get("GPO.BlockGasLimit") == nil { + confTree.Set("GPO.BlockGasLimit", defaultConfig.GPO.BlockGasLimit) + } + // upgrade minor version because of `GPO` section introduction + confTree.Set("Version", "2.6.0") + return confTree + } + // check that the latest version here is the same as in default.go largestKey := getNextVersion(migrations) if largestKey != tomlConfigVersion { diff --git a/cmd/harmony/default.go b/cmd/harmony/default.go index 2c15e123f7..38ae3dacbb 100644 --- a/cmd/harmony/default.go +++ b/cmd/harmony/default.go @@ -2,11 +2,12 @@ package main import ( "github.com/harmony-one/harmony/core" + "github.com/harmony-one/harmony/hmy" harmonyconfig "github.com/harmony-one/harmony/internal/configs/harmony" nodeconfig "github.com/harmony-one/harmony/internal/configs/node" ) -const tomlConfigVersion = "2.5.14" +const tomlConfigVersion = "2.6.0" const ( defNetworkType = nodeconfig.Mainnet @@ -120,6 +121,15 @@ var defaultConfig = harmonyconfig.HarmonyConfig{ CacheTime: 10, CacheSize: 512, }, + GPO: harmonyconfig.GasPriceOracleConfig{ + Blocks: hmy.DefaultGPOConfig.Blocks, + Transactions: hmy.DefaultGPOConfig.Transactions, + Percentile: hmy.DefaultGPOConfig.Percentile, + DefaultPrice: hmy.DefaultGPOConfig.DefaultPrice, + MaxPrice: hmy.DefaultGPOConfig.MaxPrice, + LowUsageThreshold: hmy.DefaultGPOConfig.LowUsageThreshold, + BlockGasLimit: hmy.DefaultGPOConfig.BlockGasLimit, + }, } var defaultSysConfig = harmonyconfig.SysConfig{ diff --git a/cmd/harmony/flags.go b/cmd/harmony/flags.go index 9760652e03..acf53d8b3a 100644 --- a/cmd/harmony/flags.go +++ b/cmd/harmony/flags.go @@ -249,6 +249,16 @@ var ( cacheSizeFlag, } + gpoFlags = []cli.Flag{ + gpoBlocksFlag, + gpoTransactionsFlag, + gpoPercentileFlag, + gpoDefaultPriceFlag, + gpoMaxPriceFlag, + gpoLowUsageThresholdFlag, + gpoBlockGasLimitFlag, + } + metricsFlags = []cli.Flag{ metricsETHFlag, metricsExpensiveETHFlag, @@ -364,6 +374,7 @@ func getRootFlags() []cli.Flag { flags = append(flags, prometheusFlags...) flags = append(flags, syncFlags...) flags = append(flags, shardDataFlags...) + flags = append(flags, gpoFlags...) flags = append(flags, metricsFlags...) return flags @@ -1932,6 +1943,45 @@ var ( } ) +// gas price oracle flags +var ( + gpoBlocksFlag = cli.IntFlag{ + Name: "gpo.blocks", + Usage: "Number of recent blocks to check for gas prices", + DefValue: defaultConfig.GPO.Blocks, + } + gpoTransactionsFlag = cli.IntFlag{ + Name: "gpo.transactions", + Usage: "Number of transactions to sample in a block", + DefValue: defaultConfig.GPO.Transactions, + } + gpoPercentileFlag = cli.IntFlag{ + Name: "gpo.percentile", + Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", + DefValue: defaultConfig.GPO.Percentile, + } + gpoDefaultPriceFlag = cli.Int64Flag{ + Name: "gpo.defaultprice", + Usage: "The gas price to suggest before data is available, and the price to suggest when block utilization is low", + DefValue: defaultConfig.GPO.DefaultPrice, + } + gpoMaxPriceFlag = cli.Int64Flag{ + Name: "gpo.maxprice", + Usage: "Maximum gasprice to be recommended by gpo", + DefValue: defaultConfig.GPO.MaxPrice, + } + gpoLowUsageThresholdFlag = cli.IntFlag{ + Name: "gpo.low-usage-threshold", + Usage: "The block usage threshold below which the default gas price is suggested (0 to disable)", + DefValue: defaultConfig.GPO.LowUsageThreshold, + } + gpoBlockGasLimitFlag = cli.IntFlag{ + Name: "gpo.block-gas-limit", + Usage: "The gas limit, per block. If set to 0, it is pulled from the block header", + DefValue: defaultConfig.GPO.BlockGasLimit, + } +) + // metrics flags required for the go-eth library // https://github.com/ethereum/go-ethereum/blob/master/metrics/metrics.go#L35-L55 var ( @@ -1965,3 +2015,27 @@ func applyShardDataFlags(cmd *cobra.Command, cfg *harmonyconfig.HarmonyConfig) { cfg.ShardData.CacheSize = cli.GetIntFlagValue(cmd, cacheSizeFlag) } } + +func applyGPOFlags(cmd *cobra.Command, cfg *harmonyconfig.HarmonyConfig) { + if cli.IsFlagChanged(cmd, gpoBlocksFlag) { + cfg.GPO.Blocks = cli.GetIntFlagValue(cmd, gpoBlocksFlag) + } + if cli.IsFlagChanged(cmd, gpoTransactionsFlag) { + cfg.GPO.Transactions = cli.GetIntFlagValue(cmd, gpoTransactionsFlag) + } + if cli.IsFlagChanged(cmd, gpoPercentileFlag) { + cfg.GPO.Percentile = cli.GetIntFlagValue(cmd, gpoPercentileFlag) + } + if cli.IsFlagChanged(cmd, gpoDefaultPriceFlag) { + cfg.GPO.DefaultPrice = cli.GetInt64FlagValue(cmd, gpoDefaultPriceFlag) + } + if cli.IsFlagChanged(cmd, gpoMaxPriceFlag) { + cfg.GPO.MaxPrice = cli.GetInt64FlagValue(cmd, gpoMaxPriceFlag) + } + if cli.IsFlagChanged(cmd, gpoLowUsageThresholdFlag) { + cfg.GPO.LowUsageThreshold = cli.GetIntFlagValue(cmd, gpoLowUsageThresholdFlag) + } + if cli.IsFlagChanged(cmd, gpoBlockGasLimitFlag) { + cfg.GPO.BlockGasLimit = cli.GetIntFlagValue(cmd, gpoBlockGasLimitFlag) + } +} diff --git a/cmd/harmony/flags_test.go b/cmd/harmony/flags_test.go index 5338b9f71e..054c804215 100644 --- a/cmd/harmony/flags_test.go +++ b/cmd/harmony/flags_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/harmony-one/harmony/common/denominations" harmonyconfig "github.com/harmony-one/harmony/internal/configs/harmony" "github.com/spf13/cobra" @@ -172,6 +173,15 @@ func TestHarmonyFlags(t *testing.T) { CacheTime: 10, CacheSize: 512, }, + GPO: harmonyconfig.GasPriceOracleConfig{ + Blocks: defaultConfig.GPO.Blocks, + Transactions: defaultConfig.GPO.Transactions, + Percentile: defaultConfig.GPO.Percentile, + DefaultPrice: defaultConfig.GPO.DefaultPrice, + MaxPrice: defaultConfig.GPO.MaxPrice, + LowUsageThreshold: defaultConfig.GPO.LowUsageThreshold, + BlockGasLimit: defaultConfig.GPO.BlockGasLimit, + }, }, }, } @@ -1350,6 +1360,56 @@ func TestSysFlags(t *testing.T) { } } +func TestGPOFlags(t *testing.T) { + tests := []struct { + args []string + expConfig harmonyconfig.GasPriceOracleConfig + expErr error + }{ + { + args: []string{}, + expConfig: harmonyconfig.GasPriceOracleConfig{ + Blocks: defaultConfig.GPO.Blocks, + Transactions: defaultConfig.GPO.Transactions, + Percentile: defaultConfig.GPO.Percentile, + DefaultPrice: defaultConfig.GPO.DefaultPrice, + MaxPrice: defaultConfig.GPO.MaxPrice, + LowUsageThreshold: defaultConfig.GPO.LowUsageThreshold, + BlockGasLimit: defaultConfig.GPO.BlockGasLimit, + }, + }, + { + args: []string{"--gpo.blocks", "5", "--gpo.transactions", "1", "--gpo.percentile", "2", "--gpo.defaultprice", "101000000000", "--gpo.maxprice", "400000000000", "--gpo.low-usage-threshold", "60", "--gpo.block-gas-limit", "10000000"}, + expConfig: harmonyconfig.GasPriceOracleConfig{ + Blocks: 5, + Transactions: 1, + Percentile: 2, + DefaultPrice: 101 * denominations.Nano, + MaxPrice: 400 * denominations.Nano, + LowUsageThreshold: 60, + BlockGasLimit: 10_000_000, + }, + }, + } + + for i, test := range tests { + ts := newFlagTestSuite(t, gpoFlags, applyGPOFlags) + hc, err := ts.run(test.args) + + if assErr := assertError(err, test.expErr); assErr != nil { + t.Fatalf("Test %v: %v", i, assErr) + } + if err != nil || test.expErr != nil { + continue + } + + if !reflect.DeepEqual(hc.GPO, test.expConfig) { + t.Errorf("Test %v:\n\t%+v\n\t%+v", i, hc.GPO, test.expConfig) + } + ts.tearDown() + } +} + func TestDevnetFlags(t *testing.T) { tests := []struct { args []string diff --git a/cmd/harmony/inspectdb.go b/cmd/harmony/inspectdb.go new file mode 100644 index 0000000000..89f8c28271 --- /dev/null +++ b/cmd/harmony/inspectdb.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/harmony-one/harmony/core/rawdb" + "github.com/harmony-one/harmony/internal/cli" +) + +var prefixFlag = cli.StringFlag{ + Name: "prefix", + Shorthand: "p", + Usage: "key prefix", + DefValue: "", +} + +var startKeyFlag = cli.StringFlag{ + Name: "start_key", + Shorthand: "s", + Usage: "start key", + DefValue: "", +} + +var inspectDBCmd = &cobra.Command{ + Use: "inspectdb srcdb prefix startKey", + Short: "inspect a db.", + Long: "inspect a db.", + Example: "harmony inspectdb /srcDir/harmony_db_0", + Args: cobra.RangeArgs(1, 3), + Run: func(cmd *cobra.Command, args []string) { + srcDBDir := args[0] + prefix := cli.GetStringFlagValue(cmd, prefixFlag) + startKey := cli.GetStringFlagValue(cmd, startKeyFlag) + fmt.Println("db path: ", srcDBDir) + inspectDB(srcDBDir, prefix, startKey) + os.Exit(0) + }, +} + +func registerInspectionFlags() error { + return cli.RegisterFlags(inspectDBCmd, []cli.Flag{prefixFlag, startKeyFlag}) + +} + +func inspectDB(srcDBDir, prefix, startKey string) { + fmt.Println("===inspectDB===") + srcDB, err := rawdb.NewLevelDBDatabase(srcDBDir, LEVELDB_CACHE_SIZE, LEVELDB_HANDLES, "", false) + if err != nil { + fmt.Println("open src db error:", err) + os.Exit(-1) + } + + rawdb.InspectDatabase(srcDB, []byte(prefix), []byte(startKey)) + + fmt.Println("database inspection completed!") +} diff --git a/cmd/harmony/main.go b/cmd/harmony/main.go index 88da5f7513..e66d3c9c73 100644 --- a/cmd/harmony/main.go +++ b/cmd/harmony/main.go @@ -111,6 +111,7 @@ func init() { rootCmd.AddCommand(versionCmd) rootCmd.AddCommand(dumpConfigLegacyCmd) rootCmd.AddCommand(dumpDBCmd) + rootCmd.AddCommand(inspectDBCmd) if err := registerRootCmdFlags(); err != nil { os.Exit(2) @@ -121,6 +122,9 @@ func init() { if err := registerDumpDBFlags(); err != nil { os.Exit(2) } + if err := registerInspectionFlags(); err != nil { + os.Exit(2) + } } func main() { @@ -245,6 +249,7 @@ func applyRootFlags(cmd *cobra.Command, config *harmonyconfig.HarmonyConfig) { applyPrometheusFlags(cmd, config) applySyncFlags(cmd, config) applyShardDataFlags(cmd, config) + applyGPOFlags(cmd, config) } func setupNodeLog(config harmonyconfig.HarmonyConfig) { @@ -258,7 +263,7 @@ func setupNodeLog(config harmonyconfig.HarmonyConfig) { utils.SetLogContext(ip, strconv.Itoa(port)) } - if config.Log.Console != true { + if !config.Log.Console { utils.AddLogFile(logPath, config.Log.RotateSize, config.Log.RotateCount, config.Log.RotateMaxAge) } } @@ -717,11 +722,12 @@ func setupConsensusAndNode(hc harmonyconfig.HarmonyConfig, nodeConfig *nodeconfi // We are not beacon chain, make sure beacon already initialized. if nodeConfig.ShardID != shard.BeaconChainShardID { - _, err = collection.ShardChain(shard.BeaconChainShardID, core.Options{EpochChain: true}) + beacon, err := collection.ShardChain(shard.BeaconChainShardID, core.Options{EpochChain: true}) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Error :%v \n", err) os.Exit(1) } + registry.SetBeaconchain(beacon) } blockchain, err = collection.ShardChain(nodeConfig.ShardID) @@ -729,11 +735,20 @@ func setupConsensusAndNode(hc harmonyconfig.HarmonyConfig, nodeConfig *nodeconfi _, _ = fmt.Fprintf(os.Stderr, "Error :%v \n", err) os.Exit(1) } + registry.SetBlockchain(blockchain) + registry.SetWebHooks(nodeConfig.WebHooks.Hooks) + if registry.GetBeaconchain() == nil { + registry.SetBeaconchain(registry.GetBlockchain()) + } + + cxPool := core.NewCxPool(core.CxPoolSize) + registry.SetCxPool(cxPool) // Consensus object. decider := quorum.NewDecider(quorum.SuperMajorityVote, nodeConfig.ShardID) + registry.SetIsBackup(isBackup(hc)) currentConsensus, err := consensus.New( - myHost, nodeConfig.ShardID, nodeConfig.ConsensusPriKey, registry.SetBlockchain(blockchain), decider, minPeers, aggregateSig) + myHost, nodeConfig.ShardID, nodeConfig.ConsensusPriKey, registry, decider, minPeers, aggregateSig) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Error :%v \n", err) @@ -769,7 +784,7 @@ func setupConsensusAndNode(hc harmonyconfig.HarmonyConfig, nodeConfig *nodeconfi ) nodeconfig.GetDefaultConfig().DBDir = nodeConfig.DBDir - currentConsensus.SetIsBackup(processNodeType(hc, currentNode)) + processNodeType(hc, currentNode.NodeConfig) currentNode.NodeConfig.SetShardGroupID(nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(nodeConfig.ShardID))) currentNode.NodeConfig.SetClientGroupID(nodeconfig.NewClientGroupIDByShardID(shard.BeaconChainShardID)) currentNode.NodeConfig.ConsensusPriKey = nodeConfig.ConsensusPriKey @@ -789,9 +804,6 @@ func setupConsensusAndNode(hc harmonyconfig.HarmonyConfig, nodeConfig *nodeconfi Uint64("viewID", viewID). Msg("Init Blockchain") - // Assign closure functions to the consensus object - currentConsensus.SetBlockVerifier( - node.VerifyNewBlock(currentNode.NodeConfig, currentNode.Blockchain(), currentNode.Beaconchain())) currentConsensus.PostConsensusJob = currentNode.PostConsensusProcessing // update consensus information based on the blockchain currentConsensus.SetMode(currentConsensus.UpdateConsensusInformation()) @@ -821,16 +833,23 @@ func setupTiKV(hc harmonyconfig.HarmonyConfig) shardchain.DBFactory { return factory } -func processNodeType(hc harmonyconfig.HarmonyConfig, currentNode *node.Node) (isBackup bool) { +func processNodeType(hc harmonyconfig.HarmonyConfig, nodeConfig *nodeconfig.ConfigType) { switch hc.General.NodeType { case nodeTypeExplorer: nodeconfig.SetDefaultRole(nodeconfig.ExplorerNode) - currentNode.NodeConfig.SetRole(nodeconfig.ExplorerNode) + nodeConfig.SetRole(nodeconfig.ExplorerNode) case nodeTypeValidator: nodeconfig.SetDefaultRole(nodeconfig.Validator) - currentNode.NodeConfig.SetRole(nodeconfig.Validator) + nodeConfig.SetRole(nodeconfig.Validator) + } +} +func isBackup(hc harmonyconfig.HarmonyConfig) (isBackup bool) { + switch hc.General.NodeType { + case nodeTypeExplorer: + + case nodeTypeValidator: return hc.General.IsBackup } return false @@ -934,9 +953,8 @@ func setupStagedSyncService(node *node.Node, host p2p.Host, hc harmonyconfig.Har InsertHook: node.BeaconSyncHook, } } - //Setup stream sync service - s := stagedstreamsync.NewService(host, blockchains, sConfig) + s := stagedstreamsync.NewService(host, blockchains, sConfig, hc.General.DataDir) node.RegisterService(service.StagedStreamSync, s) diff --git a/consensus/consensus.go b/consensus/consensus.go index c5573c972d..ddbea9ec46 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "time" + "github.com/harmony-one/harmony/consensus/engine" "github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/internal/registry" @@ -139,6 +140,12 @@ func (consensus *Consensus) Blockchain() core.BlockChain { return consensus.registry.GetBlockchain() } +// ChainReader returns the chain reader. +// This is mostly the same as Blockchain, but it returns only read methods, so we assume it's safe for concurrent use. +func (consensus *Consensus) ChainReader() engine.ChainReader { + return consensus.Blockchain() +} + func (consensus *Consensus) ReadySignal(p ProposalType) { consensus.readySignal <- p } @@ -147,12 +154,13 @@ func (consensus *Consensus) GetReadySignal() chan ProposalType { return consensus.readySignal } -func (consensus *Consensus) CommitSigChannel() chan []byte { +func (consensus *Consensus) GetCommitSigChannel() chan []byte { return consensus.commitSigChannel } -func (consensus *Consensus) GetCommitSigChannel() chan []byte { - return consensus.commitSigChannel +// Beaconchain returns the beaconchain. +func (consensus *Consensus) Beaconchain() core.BlockChain { + return consensus.registry.GetBeaconchain() } // VerifyBlock is a function used to verify the block and keep trace of verified blocks. @@ -176,6 +184,8 @@ func (consensus *Consensus) BlocksSynchronized() { // BlocksNotSynchronized lets the main loop know that block is not synchronized func (consensus *Consensus) BlocksNotSynchronized() { + consensus.mutex.Lock() + defer consensus.mutex.Unlock() consensus.syncNotReadyChan() } @@ -232,14 +242,6 @@ func (consensus *Consensus) getConsensusLeaderPrivateKey() (*bls.PrivateKeyWrapp return consensus.getLeaderPrivateKey(consensus.LeaderPubKey.Object) } -// SetBlockVerifier sets the block verifier -func (consensus *Consensus) SetBlockVerifier(verifier VerifyBlockFunc) { - consensus.mutex.Lock() - defer consensus.mutex.Unlock() - consensus.BlockVerifier = verifier - consensus.vc.SetVerifyBlock(consensus.verifyBlock) -} - func (consensus *Consensus) IsBackup() bool { return consensus.isBackup } @@ -288,7 +290,6 @@ func New( // the blockchain during initialization as it was // displayed on explorer as Height right now consensus.SetCurBlockViewID(0) - consensus.ShardID = shard consensus.SlashChan = make(chan slash.Record) consensus.readySignal = make(chan ProposalType) consensus.commitSigChannel = make(chan []byte) @@ -297,6 +298,10 @@ func New( consensus.IgnoreViewIDCheck = abool.NewBool(false) // Make Sure Verifier is not null consensus.vc = newViewChange() + // TODO: reference to blockchain/beaconchain should be removed. + verifier := VerifyNewBlock(registry.GetWebHooks(), consensus.Blockchain(), consensus.Beaconchain()) + consensus.BlockVerifier = verifier + consensus.vc.verifyBlock = consensus.verifyBlock // init prometheus metrics initMetrics() @@ -304,3 +309,11 @@ func New( return &consensus, nil } + +func (consensus *Consensus) GetHost() p2p.Host { + return consensus.host +} + +func (consensus *Consensus) Registry() *registry.Registry { + return consensus.registry +} diff --git a/consensus/consensus_service.go b/consensus/consensus_service.go index e8d7e1645c..af40c42bcb 100644 --- a/consensus/consensus_service.go +++ b/consensus/consensus_service.go @@ -5,9 +5,11 @@ import ( "sync/atomic" "time" + "github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/multibls" + "github.com/harmony-one/harmony/webhooks" "github.com/ethereum/go-ethereum/common" protobuf "github.com/golang/protobuf/proto" @@ -590,7 +592,7 @@ func (consensus *Consensus) selfCommit(payload []byte) error { consensus.switchPhase("selfCommit", FBFTCommit) consensus.aggregatedPrepareSig = aggSig consensus.prepareBitmap = mask - commitPayload := signature.ConstructCommitPayload(consensus.Blockchain(), + commitPayload := signature.ConstructCommitPayload(consensus.ChainReader().Config(), block.Epoch(), block.Hash(), block.NumberU64(), block.Header().ViewID().Uint64()) for i, key := range consensus.priKey { if err := consensus.commitBitmap.SetKey(key.Pub.Bytes, true); err != nil { @@ -658,3 +660,35 @@ func (consensus *Consensus) getLogger() *zerolog.Logger { Logger() return &logger } + +// VerifyNewBlock is called by consensus participants to verify the block (account model) they are +// running consensus on. +func VerifyNewBlock(hooks *webhooks.Hooks, blockChain core.BlockChain, beaconChain core.BlockChain) func(*types.Block) error { + return func(newBlock *types.Block) error { + if err := blockChain.ValidateNewBlock(newBlock, beaconChain); err != nil { + if hooks := hooks; hooks != nil { + if p := hooks.ProtocolIssues; p != nil { + url := p.OnCannotCommit + go func() { + webhooks.DoPost(url, map[string]interface{}{ + "bad-header": newBlock.Header(), + "reason": err.Error(), + }) + }() + } + } + utils.Logger().Error(). + Str("blockHash", newBlock.Hash().Hex()). + Int("numTx", len(newBlock.Transactions())). + Int("numStakingTx", len(newBlock.StakingTransactions())). + Err(err). + Msgf("[VerifyNewBlock] Cannot Verify New Block!!!, blockHeight %d, myHeight %d", newBlock.NumberU64(), blockChain.CurrentHeader().NumberU64()) + return errors.Errorf( + "[VerifyNewBlock] Cannot Verify New Block!!! block-hash %s txn-count %d", + newBlock.Hash().Hex(), + len(newBlock.Transactions()), + ) + } + return nil + } +} diff --git a/consensus/consensus_service_test.go b/consensus/consensus_service_test.go index dd2fca7abc..00b8bd3462 100644 --- a/consensus/consensus_service_test.go +++ b/consensus/consensus_service_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/harmony-one/harmony/crypto/bls" + "github.com/harmony-one/harmony/internal/registry" msg_pb "github.com/harmony-one/harmony/api/proto/message" "github.com/harmony-one/harmony/consensus/quorum" @@ -25,7 +26,8 @@ func TestSignAndMarshalConsensusMessage(t *testing.T) { } decider := quorum.NewDecider(quorum.SuperMajorityVote, shard.BeaconChainShardID) blsPriKey := bls.RandPrivateKey() - consensus, err := New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), nil, decider, 3, false) + reg := registry.New() + consensus, err := New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), reg, decider, 3, false) if err != nil { t.Fatalf("Cannot craeate consensus: %v", err) } @@ -57,8 +59,9 @@ func TestSetViewID(t *testing.T) { quorum.SuperMajorityVote, shard.BeaconChainShardID, ) blsPriKey := bls.RandPrivateKey() + reg := registry.New() consensus, err := New( - host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), nil, decider, 3, false, + host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), reg, decider, 3, false, ) if err != nil { t.Fatalf("Cannot craeate consensus: %v", err) diff --git a/consensus/consensus_v2.go b/consensus/consensus_v2.go index 8e72896c3e..262cbe37d6 100644 --- a/consensus/consensus_v2.go +++ b/consensus/consensus_v2.go @@ -608,7 +608,7 @@ func (consensus *Consensus) verifyLastCommitSig(lastCommitSig []byte, blk *types } aggPubKey := consensus.commitBitmap.AggregatePublic - commitPayload := signature.ConstructCommitPayload(consensus.Blockchain(), + commitPayload := signature.ConstructCommitPayload(consensus.Blockchain().Config(), blk.Epoch(), blk.Hash(), blk.NumberU64(), blk.Header().ViewID().Uint64()) if !aggSig.VerifyHash(aggPubKey, commitPayload) { @@ -915,3 +915,24 @@ func (consensus *Consensus) ValidateVdfAndProof(headerObj *block.Header) bool { return true } + +// DeleteBlocksLessThan deletes blocks less than given block number +func (consensus *Consensus) DeleteBlocksLessThan(number uint64) { + consensus.mutex.Lock() + defer consensus.mutex.Unlock() + consensus.FBFTLog.deleteBlocksLessThan(number) +} + +// DeleteMessagesLessThan deletes messages less than given block number. +func (consensus *Consensus) DeleteMessagesLessThan(number uint64) { + consensus.mutex.Lock() + defer consensus.mutex.Unlock() + consensus.FBFTLog.deleteMessagesLessThan(number) +} + +// DeleteBlockByNumber deletes block by given block number. +func (consensus *Consensus) DeleteBlockByNumber(number uint64) { + consensus.mutex.Lock() + defer consensus.mutex.Unlock() + consensus.FBFTLog.deleteBlockByNumber(number) +} diff --git a/consensus/construct_test.go b/consensus/construct_test.go index 1add32219d..7188ebea68 100644 --- a/consensus/construct_test.go +++ b/consensus/construct_test.go @@ -10,6 +10,7 @@ import ( msg_pb "github.com/harmony-one/harmony/api/proto/message" "github.com/harmony-one/harmony/consensus/quorum" "github.com/harmony-one/harmony/crypto/bls" + "github.com/harmony-one/harmony/internal/registry" "github.com/harmony-one/harmony/internal/utils" "github.com/harmony-one/harmony/multibls" "github.com/harmony-one/harmony/p2p" @@ -31,7 +32,8 @@ func TestConstructAnnounceMessage(test *testing.T) { quorum.SuperMajorityVote, shard.BeaconChainShardID, ) blsPriKey := bls.RandPrivateKey() - consensus, err := New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), nil, decider, 3, false) + reg := registry.New() + consensus, err := New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), reg, decider, 3, false) if err != nil { test.Fatalf("Cannot create consensus: %v", err) } @@ -63,7 +65,8 @@ func TestConstructPreparedMessage(test *testing.T) { quorum.SuperMajorityVote, shard.BeaconChainShardID, ) blsPriKey := bls.RandPrivateKey() - consensus, err := New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), nil, decider, 3, false) + reg := registry.New() + consensus, err := New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), reg, decider, 3, false) if err != nil { test.Fatalf("Cannot craeate consensus: %v", err) } @@ -143,7 +146,7 @@ func TestConstructPrepareMessage(test *testing.T) { ) consensus, err := New( - host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey1), nil, decider, 3, false, + host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey1), registry.New(), decider, 3, false, ) if err != nil { test.Fatalf("Cannot create consensus: %v", err) @@ -234,7 +237,7 @@ func TestConstructCommitMessage(test *testing.T) { quorum.SuperMajorityStake, shard.BeaconChainShardID, ) - consensus, err := New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey1), nil, decider, 3, false) + consensus, err := New(host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey1), registry.New(), decider, 3, false) if err != nil { test.Fatalf("Cannot create consensus: %v", err) } @@ -316,7 +319,7 @@ func TestPopulateMessageFields(t *testing.T) { quorum.SuperMajorityVote, shard.BeaconChainShardID, ) consensus, err := New( - host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), nil, decider, 3, false, + host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsPriKey), registry.New(), decider, 3, false, ) if err != nil { t.Fatalf("Cannot craeate consensus: %v", err) diff --git a/consensus/debug.go b/consensus/debug.go index cba13cc011..a323e04ed6 100644 --- a/consensus/debug.go +++ b/consensus/debug.go @@ -14,6 +14,8 @@ func (consensus *Consensus) getConsensusPhase() string { // GetConsensusMode returns the current mode of the consensus func (consensus *Consensus) GetConsensusMode() string { + consensus.mutex.RLock() + defer consensus.mutex.RUnlock() return consensus.current.mode.String() } diff --git a/consensus/downloader.go b/consensus/downloader.go index 8442ed5343..26755bbd25 100644 --- a/consensus/downloader.go +++ b/consensus/downloader.go @@ -114,7 +114,14 @@ func (consensus *Consensus) spinUpStateSync() { v.Stop() } } else { - consensus.spinLegacyStateSync() + select { + case consensus.BlockNumLowChan <- struct{}{}: + consensus.current.SetMode(Syncing) + for _, v := range consensus.consensusTimeout { + v.Stop() + } + default: + } } } diff --git a/consensus/fbft_log.go b/consensus/fbft_log.go index ba37451038..5a4fe21889 100644 --- a/consensus/fbft_log.go +++ b/consensus/fbft_log.go @@ -147,7 +147,7 @@ func (log *FBFTLog) GetBlocksByNumber(number uint64) []*types.Block { } // DeleteBlocksLessThan deletes blocks less than given block number -func (log *FBFTLog) DeleteBlocksLessThan(number uint64) { +func (log *FBFTLog) deleteBlocksLessThan(number uint64) { for h, block := range log.blocks { if block.NumberU64() < number { delete(log.blocks, h) @@ -157,7 +157,7 @@ func (log *FBFTLog) DeleteBlocksLessThan(number uint64) { } // DeleteBlockByNumber deletes block of specific number -func (log *FBFTLog) DeleteBlockByNumber(number uint64) { +func (log *FBFTLog) deleteBlockByNumber(number uint64) { for h, block := range log.blocks { if block.NumberU64() == number { delete(log.blocks, h) @@ -167,7 +167,7 @@ func (log *FBFTLog) DeleteBlockByNumber(number uint64) { } // DeleteMessagesLessThan deletes messages less than given block number -func (log *FBFTLog) DeleteMessagesLessThan(number uint64) { +func (log *FBFTLog) deleteMessagesLessThan(number uint64) { for h, msg := range log.messages { if msg.BlockNum < number { delete(log.messages, h) @@ -357,6 +357,6 @@ func (log *FBFTLog) GetCommittedBlockAndMsgsFromNumber(bn uint64, logger *zerolo // PruneCacheBeforeBlock prune all blocks before bn func (log *FBFTLog) PruneCacheBeforeBlock(bn uint64) { - log.DeleteBlocksLessThan(bn - 1) - log.DeleteMessagesLessThan(bn - 1) + log.deleteBlocksLessThan(bn - 1) + log.deleteMessagesLessThan(bn - 1) } diff --git a/consensus/leader.go b/consensus/leader.go index 2f7766e19b..1b10c96086 100644 --- a/consensus/leader.go +++ b/consensus/leader.go @@ -235,7 +235,7 @@ func (consensus *Consensus) onCommit(recvMsg *FBFTMessage) { Msg("[OnCommit] Failed finding a matching block for committed message") return } - commitPayload := signature.ConstructCommitPayload(consensus.Blockchain(), + commitPayload := signature.ConstructCommitPayload(consensus.Blockchain().Config(), blockObj.Epoch(), blockObj.Hash(), blockObj.NumberU64(), blockObj.Header().ViewID().Uint64()) logger = logger.With(). Uint64("MsgViewID", recvMsg.ViewID). diff --git a/consensus/signature/signature.go b/consensus/signature/signature.go index 3c419b03b0..20226a3811 100644 --- a/consensus/signature/signature.go +++ b/consensus/signature/signature.go @@ -8,18 +8,14 @@ import ( "github.com/harmony-one/harmony/internal/params" ) -type signatureChainReader interface { - Config() *params.ChainConfig -} - // ConstructCommitPayload returns the commit payload for consensus signatures. func ConstructCommitPayload( - chain signatureChainReader, epoch *big.Int, blockHash common.Hash, blockNum, viewID uint64, + config *params.ChainConfig, epoch *big.Int, blockHash common.Hash, blockNum, viewID uint64, ) []byte { blockNumBytes := make([]byte, 8) binary.LittleEndian.PutUint64(blockNumBytes, blockNum) commitPayload := append(blockNumBytes, blockHash.Bytes()...) - if !chain.Config().IsStaking(epoch) { + if !config.IsStaking(epoch) { return commitPayload } viewIDBytes := make([]byte, 8) diff --git a/consensus/threshold.go b/consensus/threshold.go index ecb54980a0..11e65709e6 100644 --- a/consensus/threshold.go +++ b/consensus/threshold.go @@ -46,7 +46,7 @@ func (consensus *Consensus) didReachPrepareQuorum() error { Msg("[didReachPrepareQuorum] Unparseable block data") return err } - commitPayload := signature.ConstructCommitPayload(consensus.Blockchain(), + commitPayload := signature.ConstructCommitPayload(consensus.Blockchain().Config(), blockObj.Epoch(), blockObj.Hash(), blockObj.NumberU64(), blockObj.Header().ViewID().Uint64()) // so by this point, everyone has committed to the blockhash of this block diff --git a/consensus/validator.go b/consensus/validator.go index 92008a91e6..c67765cc8a 100644 --- a/consensus/validator.go +++ b/consensus/validator.go @@ -164,7 +164,7 @@ func (consensus *Consensus) sendCommitMessages(blockObj *types.Block) { priKeys := consensus.getPriKeysInCommittee() // Sign commit signature on the received block and construct the p2p messages - commitPayload := signature.ConstructCommitPayload(consensus.Blockchain(), + commitPayload := signature.ConstructCommitPayload(consensus.Blockchain().Config(), blockObj.Epoch(), blockObj.Hash(), blockObj.NumberU64(), blockObj.Header().ViewID().Uint64()) p2pMsgs := consensus.constructP2pMessages(msg_pb.MessageType_COMMIT, commitPayload, priKeys) diff --git a/consensus/view_change_construct.go b/consensus/view_change_construct.go index 52ea8bbd72..089ec2ef87 100644 --- a/consensus/view_change_construct.go +++ b/consensus/view_change_construct.go @@ -57,11 +57,6 @@ func newViewChange() *viewChange { return &vc } -// SetVerifyBlock .. -func (vc *viewChange) SetVerifyBlock(verifyBlock VerifyBlockFunc) { - vc.verifyBlock = verifyBlock -} - // AddViewIDKeyIfNotExist .. func (vc *viewChange) AddViewIDKeyIfNotExist(viewID uint64, members multibls.PublicKeys) { if _, ok := vc.bhpSigs[viewID]; !ok { diff --git a/core/block_validator.go b/core/block_validator.go index b1126f3972..fe5ff0f44a 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -154,7 +154,7 @@ func (v *BlockValidator) ValidateHeaders(chain []*types.Block) (chan<- struct{}, // to keep the baseline gas above the provided floor, and increase it towards the // ceil if the blocks are full. If the ceil is exceeded, it will always decrease // the gas allowance. -func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 { +func CalcGasLimit(parent *block.Header, gasFloor, gasCeil uint64) uint64 { // contrib = (parentGasUsed * 3 / 2) / 1024 contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor diff --git a/core/blockchain.go b/core/blockchain.go index 8afe622c70..370f0d09e7 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -214,7 +214,7 @@ type BlockChain interface { // ReadCXReceipts retrieves the cross shard transaction receipts of a given shard. ReadCXReceipts(shardID uint32, blockNum uint64, blockHash common.Hash) (types.CXReceipts, error) // CXMerkleProof calculates the cross shard transaction merkle proof of a given destination shard. - CXMerkleProof(toShardID uint32, block *types.Block) (*types.CXMerkleProof, error) + CXMerkleProof(toShardID uint32, block *block.Header) (*types.CXMerkleProof, error) // WriteCXReceiptsProofSpent mark the CXReceiptsProof list with given unspent status WriteCXReceiptsProofSpent(db rawdb.DatabaseWriter, cxps []*types.CXReceiptsProof) error // IsSpent checks whether a CXReceiptsProof is spent. @@ -255,13 +255,6 @@ type BlockChain interface { ReadValidatorStats( addr common.Address, ) (*types2.ValidatorStats, error) - // UpdateValidatorVotingPower writes the voting power for the committees. - UpdateValidatorVotingPower( - batch rawdb.DatabaseWriter, - block *types.Block, - newEpochSuperCommittee, currentEpochSuperCommittee *shard.State, - state *state.DB, - ) (map[common.Address]*types2.ValidatorStats, error) // ComputeAndUpdateAPR ... ComputeAndUpdateAPR( block *types.Block, now *big.Int, diff --git a/core/blockchain_impl.go b/core/blockchain_impl.go index f1d0968422..8294af26b8 100644 --- a/core/blockchain_impl.go +++ b/core/blockchain_impl.go @@ -39,6 +39,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" bls2 "github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/harmony/block" consensus_engine "github.com/harmony-one/harmony/consensus/engine" @@ -46,6 +47,7 @@ import ( "github.com/harmony-one/harmony/consensus/votepower" "github.com/harmony-one/harmony/core/rawdb" "github.com/harmony-one/harmony/core/state" + "github.com/harmony-one/harmony/core/state/snapshot" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/crypto/bls" @@ -124,10 +126,29 @@ const ( // CacheConfig contains the configuration values for the trie caching/pruning // that's resident in a blockchain. type CacheConfig struct { - Disabled bool // Whether to disable trie write caching (archive node) - TrieNodeLimit int // Memory limit (MB) at which to flush the current in-memory trie to disk - TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk - TriesInMemory uint64 // Block number from the head stored in disk before exiting + Disabled bool // Whether to disable trie write caching (archive node) + TrieNodeLimit int // Memory limit (MB) at which to flush the current in-memory trie to disk + TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk + TriesInMemory uint64 // Block number from the head stored in disk before exiting + TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk + TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node) + TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory + TrieCleanJournal string // Disk journal for saving clean cache entries. + Preimages bool // Whether to store preimage of trie key to the disk + SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory + SnapshotNoBuild bool // Whether the background generation is allowed + 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 +// user (also used during testing). +var defaultCacheConfig = &CacheConfig{ + Disabled: false, + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + SnapshotLimit: 256, + SnapshotWait: true, } type BlockChainImpl struct { @@ -137,8 +158,10 @@ type BlockChainImpl struct { shardID uint32 // Shard number db ethdb.Database // Low level persistent database to store final content in + snaps *snapshot.Tree // Snapshot tree for fast trie leaf access triegc *prque.Prque[int64, common.Hash] // Priority queue mapping block numbers to tries to gc gcproc time.Duration // Accumulates canonical block processing for trie dumping + triedb *trie.Database // The database handler for maintaining trie nodes. // The following two variables are used to clean up the cache of redis in tikv mode. // This can improve the cache hit rate of redis @@ -225,6 +248,21 @@ func newBlockChainWithOptions( cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus_engine.Engine, vmConfig vm.Config, options Options) (*BlockChainImpl, error) { + if cacheConfig == nil { + cacheConfig = defaultCacheConfig + } + + // Open trie database with provided config + triedb := trie.NewDatabaseWithConfig(db, &trie.Config{ + Cache: cacheConfig.TrieCleanLimit, + Journal: cacheConfig.TrieCleanJournal, + Preimages: cacheConfig.Preimages, + }) + + if stateCache == nil { + stateCache = state.NewDatabaseWithNodeDB(db, triedb) + } + bodyCache, _ := lru.New(bodyCacheLimit) bodyRLPCache, _ := lru.New(bodyCacheLimit) receiptsCache, _ := lru.New(receiptsCacheLimit) @@ -248,6 +286,7 @@ func newBlockChainWithOptions( cacheConfig: cacheConfig, db: db, triegc: prque.New[int64, common.Hash](nil), + triedb: triedb, stateCache: stateCache, quit: make(chan struct{}), bodyCache: bodyCache, @@ -298,6 +337,28 @@ func newBlockChainWithOptions( bc.SetValidator(NewBlockValidator(chainConfig, bc, engine)) bc.SetProcessor(NewStateProcessor(chainConfig, bc, beaconChain, engine)) + // Load any existing snapshot, regenerating it if loading failed + if bc.cacheConfig.SnapshotLimit > 0 { + // If the chain was rewound past the snapshot persistent layer (causing + // a recovery block number to be persisted to disk), check if we're still + // in recovery mode and in that case, don't invalidate the snapshot on a + // head mismatch. + var recover bool + + head := bc.CurrentBlock() + if layer := rawdb.ReadSnapshotRecoveryNumber(bc.db); layer != nil && *layer >= head.NumberU64() { + utils.Logger().Warn().Uint64("diskbase", *layer).Uint64("chainhead", head.NumberU64()).Msg("Enabling snapshot recovery") + recover = true + } + snapconfig := snapshot.Config{ + CacheSize: bc.cacheConfig.SnapshotLimit, + Recovery: recover, + NoBuild: bc.cacheConfig.SnapshotNoBuild, + AsyncBuild: !bc.cacheConfig.SnapshotWait, + } + bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Hash()) + } + // Take ownership of this particular state go bc.update() return bc, nil @@ -463,7 +524,7 @@ func (bc *BlockChainImpl) ValidateNewBlock(block *types.Block, beaconChain Block } func (bc *BlockChainImpl) validateNewBlock(block *types.Block) error { - state, err := state.New(bc.CurrentBlock().Root(), bc.stateCache, nil) + state, err := state.New(bc.CurrentBlock().Root(), bc.stateCache, bc.snaps) if err != nil { return err } @@ -521,7 +582,7 @@ func (bc *BlockChainImpl) loadLastState() error { return bc.Reset() } // Make sure the state associated with the block is available - if _, err := state.New(currentBlock.Root(), bc.stateCache, nil); err != nil { + if _, err := state.New(currentBlock.Root(), bc.stateCache, bc.snaps); err != nil { // Dangling block without a state associated, init from scratch utils.Logger().Warn(). Str("number", currentBlock.Number().String()). @@ -618,7 +679,7 @@ func (bc *BlockChainImpl) SetHead(head uint64) error { headBlockGauge.Update(int64(newHeadBlock.NumberU64())) } if currentBlock := bc.CurrentBlock(); currentBlock != nil { - if _, err := state.New(currentBlock.Root(), bc.stateCache, nil); err != nil { + if _, err := state.New(currentBlock.Root(), bc.stateCache, bc.snaps); err != nil { // Rewound state missing, rolled back to before pivot, reset to genesis bc.currentBlock.Store(bc.genesisBlock) headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) @@ -695,7 +756,12 @@ func (bc *BlockChainImpl) State() (*state.DB, error) { } func (bc *BlockChainImpl) StateAt(root common.Hash) (*state.DB, error) { - return state.New(root, bc.stateCache, nil) + return state.New(root, bc.stateCache, bc.snaps) +} + +// Snapshots returns the blockchain snapshot tree. +func (bc *BlockChainImpl) Snapshots() *snapshot.Tree { + return bc.snaps } func (bc *BlockChainImpl) Reset() error { @@ -740,7 +806,7 @@ func (bc *BlockChainImpl) repair(head **types.Block) error { valsToRemove := map[common.Address]struct{}{} for { // Abort if we've rewound to a head block that does have associated state - if _, err := state.New((*head).Root(), bc.stateCache, nil); err == nil { + if _, err := state.New((*head).Root(), bc.stateCache, bc.snaps); err == nil { utils.Logger().Info(). Str("number", (*head).Number().String()). Str("hash", (*head).Hash().Hex()). @@ -1052,6 +1118,15 @@ func (bc *BlockChainImpl) Stop() { return } + // Ensure that the entirety of the state snapshot is journalled to disk. + var snapBase common.Hash + if bc.snaps != nil { + var err error + if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Header().Root()); err != nil { + utils.Logger().Error().Err(err).Msg("Failed to journal state snapshot") + } + } + if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) { return } @@ -1091,6 +1166,12 @@ func (bc *BlockChainImpl) Stop() { } } } + if snapBase != (common.Hash{}) { + utils.Logger().Info().Interface("root", snapBase).Msg("Writing snapshot state to disk") + if err := triedb.Commit(snapBase, true); err != nil { + utils.Logger().Error().Err(err).Msg("Failed to commit recent state trie") + } + } for !bc.triegc.Empty() { v := common.Hash(bc.triegc.PopItem()) triedb.Dereference(v) @@ -1099,6 +1180,15 @@ func (bc *BlockChainImpl) Stop() { utils.Logger().Error().Msg("Dangling trie nodes after full cleanup") } } + // Flush the collected preimages to disk + if err := bc.stateCache.TrieDB().CommitPreimages(); err != nil { + utils.Logger().Error().Interface("err", err).Msg("Failed to commit trie preimages") + } + // Ensure all live cached entries be saved into disk, so that we can skip + // cache warmup when node restarts. + if bc.cacheConfig.TrieCleanJournal != "" { + bc.triedb.SaveCache(bc.cacheConfig.TrieCleanJournal) + } utils.Logger().Info().Msg("Blockchain manager stopped") } @@ -1733,7 +1823,7 @@ func (bc *BlockChainImpl) insertChain(chain types.Blocks, verifyHeaders bool) (i } else { parent = chain[i-1] } - state, err := state.New(parent.Root(), bc.stateCache, nil) + state, err := state.New(parent.Root(), bc.stateCache, bc.snaps) if err != nil { return i, events, coalescedLogs, err } @@ -2539,10 +2629,10 @@ func (bc *BlockChainImpl) ReadCXReceipts(shardID uint32, blockNum uint64, blockH return cxs, nil } -func (bc *BlockChainImpl) CXMerkleProof(toShardID uint32, block *types.Block) (*types.CXMerkleProof, error) { - proof := &types.CXMerkleProof{BlockNum: block.Number(), BlockHash: block.Hash(), ShardID: block.ShardID(), CXReceiptHash: block.Header().OutgoingReceiptHash(), CXShardHashes: []common.Hash{}, ShardIDs: []uint32{}} +func (bc *BlockChainImpl) CXMerkleProof(toShardID uint32, block *block.Header) (*types.CXMerkleProof, error) { + proof := &types.CXMerkleProof{BlockNum: block.Number(), BlockHash: block.Hash(), ShardID: block.ShardID(), CXReceiptHash: block.OutgoingReceiptHash(), CXShardHashes: []common.Hash{}, ShardIDs: []uint32{}} - epoch := block.Header().Epoch() + epoch := block.Epoch() shardingConfig := shard.Schedule.InstanceForEpoch(epoch) shardNum := int(shardingConfig.NumShards()) @@ -2654,8 +2744,8 @@ func (bc *BlockChainImpl) ReadValidatorStats( return rawdb.ReadValidatorStats(bc.db, addr) } -func (bc *BlockChainImpl) UpdateValidatorVotingPower( - batch rawdb.DatabaseWriter, +func UpdateValidatorVotingPower( + bc BlockChain, block *types.Block, newEpochSuperCommittee, currentEpochSuperCommittee *shard.State, state *state.DB, @@ -2681,7 +2771,7 @@ func (bc *BlockChainImpl) UpdateValidatorVotingPower( // bc.db, currentValidator, currentEpochSuperCommittee.Epoch, // ) // rawdb.DeleteValidatorStats(bc.db, currentValidator) - stats, err := rawdb.ReadValidatorStats(bc.db, currentValidator) + stats, err := rawdb.ReadValidatorStats(bc.ChainDb(), currentValidator) if err != nil { stats = staking.NewEmptyStats() } @@ -2731,7 +2821,7 @@ func (bc *BlockChainImpl) UpdateValidatorVotingPower( networkWide := votepower.AggregateRosters(rosters) for key, value := range networkWide { - stats, err := rawdb.ReadValidatorStats(bc.db, key) + stats, err := rawdb.ReadValidatorStats(bc.ChainDb(), key) if err != nil { stats = staking.NewEmptyStats() } @@ -3418,14 +3508,14 @@ func (bc *BlockChainImpl) tikvCleanCache() { for i := bc.latestCleanCacheNum + 1; i <= to; i++ { // build previous block statedb fromBlock := bc.GetBlockByNumber(i) - fromTrie, err := state.New(fromBlock.Root(), bc.stateCache, nil) + fromTrie, err := state.New(fromBlock.Root(), bc.stateCache, bc.snaps) if err != nil { continue } // build current block statedb toBlock := bc.GetBlockByNumber(i + 1) - toTrie, err := state.New(toBlock.Root(), bc.stateCache, nil) + toTrie, err := state.New(toBlock.Root(), bc.stateCache, bc.snaps) if err != nil { continue } @@ -3525,7 +3615,7 @@ func (bc *BlockChainImpl) InitTiKV(conf *harmonyconfig.TiKVConfig) { // If redis is empty, the hit rate will be too low and the synchronization block speed will be slow // set LOAD_PRE_FETCH is yes can significantly improve this. if os.Getenv("LOAD_PRE_FETCH") == "yes" { - if trie, err := state.New(bc.CurrentBlock().Root(), bc.stateCache, nil); err == nil { + if trie, err := state.New(bc.CurrentBlock().Root(), bc.stateCache, bc.snaps); err == nil { trie.Prefetch(512) } else { log.Println("LOAD_PRE_FETCH ERR: ", err) diff --git a/core/blockchain_stub.go b/core/blockchain_stub.go index cfe72eed6d..bdab2494e9 100644 --- a/core/blockchain_stub.go +++ b/core/blockchain_stub.go @@ -289,7 +289,7 @@ func (a Stub) ReadCXReceipts(shardID uint32, blockNum uint64, blockHash common.H return nil, errors.Errorf("method ReadCXReceipts not implemented for %s", a.Name) } -func (a Stub) CXMerkleProof(toShardID uint32, block *types.Block) (*types.CXMerkleProof, error) { +func (a Stub) CXMerkleProof(toShardID uint32, block *block.Header) (*types.CXMerkleProof, error) { return nil, errors.Errorf("method CXMerkleProof not implemented for %s", a.Name) } diff --git a/core/evm_test.go b/core/evm_test.go index cab3f712cf..04399ff14c 100644 --- a/core/evm_test.go +++ b/core/evm_test.go @@ -46,7 +46,8 @@ func getTestEnvironment(testBankKey ecdsa.PrivateKey) (*BlockChainImpl, *state.D genesis := gspec.MustCommit(database) // fake blockchain - chain, _ := NewBlockChain(database, state.NewDatabase(database), nil, nil, gspec.Config, engine, vm.Config{}) + cacheConfig := &CacheConfig{SnapshotLimit: 0} + chain, _ := NewBlockChain(database, nil, nil, cacheConfig, gspec.Config, engine, vm.Config{}) db, _ := chain.StateAt(genesis.Root()) // make a fake block header (use epoch 1 so that locked tokens can be tested) diff --git a/core/offchain.go b/core/offchain.go index 3f08b4f81a..6ce7794e4f 100644 --- a/core/offchain.go +++ b/core/offchain.go @@ -205,8 +205,8 @@ func (bc *BlockChainImpl) CommitOffChainData( if shardState, err := shard.DecodeWrapper( header.ShardState(), ); err == nil { - if stats, err := bc.UpdateValidatorVotingPower( - batch, block, shardState, currentSuperCommittee, state, + if stats, err := UpdateValidatorVotingPower( + bc, block, shardState, currentSuperCommittee, state, ); err != nil { utils.Logger(). Err(err). diff --git a/core/rawdb/database.go b/core/rawdb/database.go index c1421b5073..20fac099f4 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -23,7 +23,6 @@ import ( "os" "path" "path/filepath" - "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -297,7 +296,6 @@ func (s *stat) Count() string { // InspectDatabase traverses the entire database and checks the size // of all different categories of data. -// This function is NOT used, just ported over from the Ethereum func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { it := db.NewIterator(keyPrefix, keyStart) defer it.Release() @@ -332,6 +330,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { // Meta- and unaccounted data metadata stat unaccounted stat + zeroval stat // Totals total common.StorageSize @@ -342,6 +341,9 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { key = it.Key() size = common.StorageSize(len(key) + len(it.Value())) ) + if len(it.Value()) == 0 { + zeroval.Add(1) + } total += size switch { case bytes.HasPrefix(key, headerPrefix) && len(key) == (len(headerPrefix)+8+common.HashLength): @@ -433,31 +435,23 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { {"Key-Value store", "Beacon sync headers", beaconHeaders.Size(), beaconHeaders.Count()}, {"Key-Value store", "Clique snapshots", cliqueSnaps.Size(), cliqueSnaps.Count()}, {"Key-Value store", "Singleton metadata", metadata.Size(), metadata.Count()}, + {"Key-Value store", "Zero value keys", zeroval.Size(), zeroval.Count()}, + {"Key-Value store", "Unaccounted", unaccounted.Size(), unaccounted.Count()}, {"Light client", "CHT trie nodes", chtTrieNodes.Size(), chtTrieNodes.Count()}, {"Light client", "Bloom trie nodes", bloomTrieNodes.Size(), bloomTrieNodes.Count()}, } - // Inspect all registered append-only file store then. - ancients, err := inspectFreezers(db) - if err != nil { - return err - } - for _, ancient := range ancients { - for _, table := range ancient.sizes { - stats = append(stats, []string{ - fmt.Sprintf("Ancient store (%s)", strings.Title(ancient.name)), - strings.Title(table.name), - table.size.String(), - fmt.Sprintf("%d", ancient.count()), - }) - } - total += ancient.size() - } table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"Database", "Category", "Size", "Items"}) table.SetFooter([]string{"", "Total", total.String(), " "}) table.AppendBulk(stats) table.Render() + if zeroval.count > 0 { + utils.Logger().Error(). + Interface("count", zeroval). + Msg("Database contains zero value keys") + } + if unaccounted.size > 0 { utils.Logger().Error(). Interface("size", unaccounted.size). diff --git a/core/state/database.go b/core/state/database.go index c1e375ccde..a563678376 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -139,7 +139,10 @@ func NewDatabase(db ethdb.Database) Database { } func NewDatabaseWithCache(db ethdb.Database, cache int) Database { - return NewDatabaseWithConfig(db, nil) + config := trie.Config{ + Cache: cache, + } + return NewDatabaseWithConfig(db, &config) } // NewDatabaseWithConfig creates a backing store for state. The returned database diff --git a/core/state/snapshot/snapshot.go b/core/state/snapshot/snapshot.go index 47dc1a3a17..d294ff1857 100644 --- a/core/state/snapshot/snapshot.go +++ b/core/state/snapshot/snapshot.go @@ -206,7 +206,8 @@ func New(config Config, diskdb ethdb.KeyValueStore, triedb *trie.Database, root utils.Logger().Warn().Err(err).Msg("Snapshot maintenance disabled (syncing)") return snap, nil } - // Create the building waiter iff the background generation is allowed + + // Create the building waiter if the background generation is allowed if !config.NoBuild && !config.AsyncBuild { defer snap.waitBuild() } diff --git a/core/state/statedb.go b/core/state/statedb.go index 9c1eefde82..e84084c02c 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -24,13 +24,13 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/harmony-one/harmony/core/rawdb" + "github.com/harmony-one/harmony/core/state/snapshot" types2 "github.com/harmony-one/harmony/core/types" common2 "github.com/harmony-one/harmony/internal/common" diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index 9b126eac90..4e1c214b1a 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -161,7 +161,8 @@ func createBlockChain() *BlockChainImpl { genesis := gspec.MustCommit(database) _ = genesis engine := chain2.NewEngine() - blockchain, _ := NewBlockChain(database, state.NewDatabase(database), nil, nil, gspec.Config, engine, vm.Config{}) + cacheConfig := &CacheConfig{SnapshotLimit: 0} + blockchain, _ := NewBlockChain(database, nil, nil, cacheConfig, gspec.Config, engine, vm.Config{}) return blockchain } diff --git a/go.mod b/go.mod index 4dd98958b3..32ac5feea0 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/ethereum/go-ethereum v1.11.2 github.com/go-redis/redis/v8 v8.11.5 github.com/golang/mock v1.6.0 - github.com/golang/protobuf v1.5.2 + github.com/golang/protobuf v1.5.3 github.com/golangci/golangci-lint v1.22.2 github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.5.0 @@ -46,20 +46,20 @@ require ( github.com/spf13/cobra v1.5.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.14.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.4 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/tikv/client-go/v2 v2.0.1 github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee go.uber.org/ratelimit v0.1.0 go.uber.org/zap v1.24.0 - golang.org/x/crypto v0.6.0 - golang.org/x/net v0.7.0 // indirect - golang.org/x/sync v0.1.0 - golang.org/x/sys v0.5.0 // indirect - golang.org/x/time v0.2.0 - golang.org/x/tools v0.3.0 // indirect - google.golang.org/grpc v1.51.0 - google.golang.org/protobuf v1.28.1 + golang.org/x/crypto v0.9.0 + golang.org/x/net v0.10.0 // indirect + golang.org/x/sync v0.2.0 + golang.org/x/sys v0.8.0 // indirect + golang.org/x/time v0.3.0 + golang.org/x/tools v0.9.3 // indirect + google.golang.org/grpc v1.55.0 + google.golang.org/protobuf v1.30.0 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 @@ -69,8 +69,8 @@ require ( require ( github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b github.com/holiman/bloomfilter/v2 v2.0.3 - github.com/ledgerwatch/erigon-lib v0.0.0-20221218022306-0f8fdd40c2db - github.com/ledgerwatch/log/v3 v3.6.0 + github.com/ledgerwatch/erigon-lib v0.0.0-20230607152933-42c9c28cac68 + github.com/ledgerwatch/log/v3 v3.8.0 github.com/libp2p/go-libp2p-core v0.20.1 github.com/olekukonko/tablewriter v0.0.5 ) @@ -80,10 +80,10 @@ require ( github.com/BurntSushi/toml v1.2.0 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/OpenPeeDeeP/depguard v1.0.1 // indirect - github.com/VictoriaMetrics/metrics v1.23.0 // indirect + github.com/VictoriaMetrics/metrics v1.23.1 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.2.2 // indirect + github.com/bits-and-blooms/bitset v1.5.0 // indirect github.com/bombsimon/wsl/v2 v2.0.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect @@ -96,7 +96,7 @@ require ( github.com/containerd/cgroups v1.0.4 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/deckarep/golang-set/v2 v2.3.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/dgraph-io/badger v1.6.2 // indirect github.com/dgraph-io/ristretto v0.0.3 // indirect @@ -147,12 +147,12 @@ require ( github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect github.com/google/uuid v1.3.0 // indirect github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect - github.com/holiman/uint256 v1.2.1 // indirect + github.com/holiman/uint256 v1.2.2 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/ipfs/go-cid v0.3.2 // indirect @@ -172,6 +172,7 @@ require ( github.com/koron/go-ssdp v0.0.3 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect + github.com/ledgerwatch/interfaces v0.0.0-20230602104541-cdc6e215fb3e // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect @@ -190,8 +191,9 @@ require ( github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb // indirect + github.com/matryer/moq v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-pointer v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -229,6 +231,7 @@ require ( github.com/prometheus/common v0.41.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/prometheus/tsdb v0.10.0 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect @@ -249,7 +252,7 @@ require ( github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect github.com/tommy-muehle/go-mnd v1.1.1 // indirect - github.com/torquem-ch/mdbx-go v0.27.0 // indirect + github.com/torquem-ch/mdbx-go v0.27.10 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/ultraware/funlen v0.0.2 // indirect github.com/ultraware/whitespace v0.0.4 // indirect @@ -263,11 +266,12 @@ require ( go.uber.org/dig v1.15.0 // indirect go.uber.org/fx v1.18.2 // indirect go.uber.org/multierr v1.8.0 // indirect - golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 8b86a286c2..51be04743c 100644 --- a/go.sum +++ b/go.sum @@ -90,6 +90,8 @@ github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bw github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VictoriaMetrics/metrics v1.23.0 h1:WzfqyzCaxUZip+OBbg1+lV33WChDSu4ssYII3nxtpeA= github.com/VictoriaMetrics/metrics v1.23.0/go.mod h1:rAr/llLpEnAdTehiNlUxKgnjcOuROSzpw0GvjpEbvFc= +github.com/VictoriaMetrics/metrics v1.23.1 h1:/j8DzeJBxSpL2qSIdqnRFLvQQhbJyJbbEi22yMm7oL0= +github.com/VictoriaMetrics/metrics v1.23.1/go.mod h1:rAr/llLpEnAdTehiNlUxKgnjcOuROSzpw0GvjpEbvFc= github.com/Workiva/go-datastructures v1.0.50 h1:slDmfW6KCHcC7U+LP3DDBbm4fqTwZGn1beOFPfGaLvo= github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= @@ -140,6 +142,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bitset v1.2.2 h1:J5gbX05GpMdBjCvQ9MteIg2KKDExr7DrgK+Yc15FvIk= github.com/bits-and-blooms/bitset v1.2.2/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD6ZIpQT8= +github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= @@ -185,6 +189,7 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -259,6 +264,8 @@ github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsP github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/deckarep/golang-set/v2 v2.3.0 h1:qs18EKUfHm2X9fA50Mr/M5hccg2tNnVqsiBImnyDs0g= +github.com/deckarep/golang-set/v2 v2.3.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -498,6 +505,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -615,6 +624,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -666,6 +677,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/holiman/uint256 v1.2.1 h1:XRtyuda/zw2l+Bq/38n5XUoEF72aSOu/77Thd9pPp2o= github.com/holiman/uint256 v1.2.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= +github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= @@ -838,8 +851,14 @@ github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3 github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/ledgerwatch/erigon-lib v0.0.0-20221218022306-0f8fdd40c2db h1:wV9YkkYQArbUdTdlPxXi5BW6H9ovYbyUT8Af7foetvQ= github.com/ledgerwatch/erigon-lib v0.0.0-20221218022306-0f8fdd40c2db/go.mod h1:5GCPOzxAshLF7f0wrMZu2Bdq0qqIiMcIubM9n+25gGo= +github.com/ledgerwatch/erigon-lib v0.0.0-20230607152933-42c9c28cac68 h1:eKTHu42qcMwDR2qi2KfR3cKGU6Qli7ilPwqQDsT5XL0= +github.com/ledgerwatch/erigon-lib v0.0.0-20230607152933-42c9c28cac68/go.mod h1:gV87KL7+CmJ31bLSk0FbCnowHYi6w7kF8Q1vyiwttqg= +github.com/ledgerwatch/interfaces v0.0.0-20230602104541-cdc6e215fb3e h1:2tltVQCyMEk6Az7uSNRAt4S0+2rV4VJ4PCHK1f1rung= +github.com/ledgerwatch/interfaces v0.0.0-20230602104541-cdc6e215fb3e/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= github.com/ledgerwatch/log/v3 v3.6.0 h1:JBUSK1epPyutUrz7KYDTcJtQLEHnehECRpKbM1ugy5M= github.com/ledgerwatch/log/v3 v3.6.0/go.mod h1:L+Sp+ma/h205EdCjviZECjGEvYUYEyXSdiuHNZzg+xQ= +github.com/ledgerwatch/log/v3 v3.8.0 h1:gCpp7uGtIerEz1jKVPeDnbIopFPud9ZnCpBLlLBGqPU= +github.com/ledgerwatch/log/v3 v3.8.0/go.mod h1:J2Jl6zV/58LeA6LTaVVnCGyf1/cYYSEOOLHY4ZN8S2A= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -895,6 +914,8 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE= +github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= +github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI= github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE= @@ -905,6 +926,8 @@ github.com/marten-seemann/webtransport-go v0.4.1 h1:8Ir7OoAvtp79yxQpa3foTKIPuoH+ github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE= github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/matryer/moq v0.3.1 h1:kLDiBJoGcusWS2BixGyTkF224aSCD8nLY24tj/NcTCs= +github.com/matryer/moq v0.3.1/go.mod h1:RJ75ZZZD71hejp39j4crZLsEDszGk6iH4v4YsWFKH4s= github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -925,6 +948,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -1172,6 +1197,8 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= +github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= +github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= @@ -1319,6 +1346,8 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -1355,6 +1384,8 @@ github.com/tommy-muehle/go-mnd v1.1.1 h1:4D0wuPKjOTiK2garzuPGGvm4zZ/wLYDOH8TJSAB github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= github.com/torquem-ch/mdbx-go v0.27.0 h1:FquhRvKL2zweMdk1R6UdOx3h6DiHgJ0+P9yQvSouURI= github.com/torquem-ch/mdbx-go v0.27.0/go.mod h1:T2fsoJDVppxfAPTLd1svUgH1kpPmeXdPESmroSHcL1E= +github.com/torquem-ch/mdbx-go v0.27.10 h1:iwb8Wn9gse4MEYIltAna+pxMPCY7hA1/5LLN/Qrcsx0= +github.com/torquem-ch/mdbx-go v0.27.10/go.mod h1:T2fsoJDVppxfAPTLd1svUgH1kpPmeXdPESmroSHcL1E= github.com/twmb/murmur3 v1.1.3/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= @@ -1398,6 +1429,7 @@ github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= +github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= @@ -1480,6 +1512,7 @@ go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= @@ -1526,6 +1559,8 @@ golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/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= @@ -1544,6 +1579,8 @@ golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9 golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= 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= @@ -1577,6 +1614,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1654,6 +1693,8 @@ golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1687,6 +1728,8 @@ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1779,6 +1822,7 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/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-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1803,6 +1847,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/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/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1810,6 +1856,8 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1823,6 +1871,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1834,6 +1884,8 @@ golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE= golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1923,6 +1975,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= 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= @@ -2024,6 +2078,8 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y= google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -2053,6 +2109,10 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -2069,6 +2129,8 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/hmy/gasprice.go b/hmy/gasprice.go index c4c14a87d4..9dcaca4685 100644 --- a/hmy/gasprice.go +++ b/hmy/gasprice.go @@ -18,13 +18,14 @@ package hmy import ( "context" - "fmt" "math/big" "sort" "sync" "github.com/harmony-one/harmony/block" + "github.com/harmony-one/harmony/common/denominations" "github.com/harmony-one/harmony/eth/rpc" + "github.com/harmony-one/harmony/internal/configs/harmony" "github.com/harmony-one/harmony/internal/utils" "github.com/ethereum/go-ethereum/common" @@ -32,17 +33,6 @@ import ( "github.com/harmony-one/harmony/core/types" ) -const sampleNumber = 3 // Number of transactions sampled in a block - -var DefaultMaxPrice = big.NewInt(1e12) // 1000 gwei is the max suggested limit - -type GasPriceConfig struct { - Blocks int - Percentile int - Default *big.Int `toml:",omitempty"` - MaxPrice *big.Int `toml:",omitempty"` -} - // OracleBackend includes all necessary background APIs for oracle. type OracleBackend interface { HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*block.Header, error) @@ -50,8 +40,7 @@ type OracleBackend interface { ChainConfig() *params.ChainConfig } -// Oracle recommends gas prices based on the content of recent -// blocks. Suitable for both light and full clients. +// Oracle recommends gas prices based on the content of recent blocks. type Oracle struct { backend *Harmony lastHead common.Hash @@ -60,38 +49,74 @@ type Oracle struct { cacheLock sync.RWMutex fetchLock sync.Mutex - checkBlocks int - percentile int + checkBlocks int + percentile int + checkTxs int + lowUsageThreshold float64 + blockGasLimit int + defaultPrice *big.Int +} + +var DefaultGPOConfig = harmony.GasPriceOracleConfig{ + Blocks: 20, + Transactions: 3, + Percentile: 60, + DefaultPrice: 100 * denominations.Nano, // 100 gwei + MaxPrice: 1000 * denominations.Nano, // 1000 gwei + LowUsageThreshold: 50, + BlockGasLimit: 0, // TODO should we set default to 30M? } // NewOracle returns a new gasprice oracle which can recommend suitable // gasprice for newly created transaction. -func NewOracle(backend *Harmony, params GasPriceConfig) *Oracle { +func NewOracle(backend *Harmony, params *harmony.GasPriceOracleConfig) *Oracle { blocks := params.Blocks if blocks < 1 { - blocks = 1 - utils.Logger().Warn().Msg(fmt.Sprint("Sanitizing invalid gasprice oracle sample blocks", "provided", params.Blocks, "updated", blocks)) + blocks = DefaultGPOConfig.Blocks + utils.Logger().Warn(). + Int("provided", params.Blocks). + Int("updated", blocks). + Msg("Sanitizing invalid gasprice oracle sample blocks") } - percent := params.Percentile - if percent < 0 { - percent = 0 - utils.Logger().Warn().Msg(fmt.Sprint("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent)) + txs := params.Transactions + if txs < 1 { + txs = DefaultGPOConfig.Transactions + utils.Logger().Warn(). + Int("provided", params.Transactions). + Int("updated", txs). + Msg("Sanitizing invalid gasprice oracle sample transactions") } - if percent > 100 { - percent = 100 - utils.Logger().Warn().Msg(fmt.Sprint("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent)) + percentile := params.Percentile + if percentile < 0 || percentile > 100 { + percentile = DefaultGPOConfig.Percentile + utils.Logger().Warn(). + Int("provided", params.Percentile). + Int("updated", percentile). + Msg("Sanitizing invalid gasprice oracle percentile") } - maxPrice := params.MaxPrice - if maxPrice == nil || maxPrice.Int64() <= 0 { - maxPrice = DefaultMaxPrice - utils.Logger().Warn().Msg(fmt.Sprint("Sanitizing invalid gasprice oracle price cap", "provided", params.MaxPrice, "updated", maxPrice)) + // no sanity check done, simply convert it + defaultPrice := big.NewInt(params.DefaultPrice) + maxPrice := big.NewInt(params.MaxPrice) + lowUsageThreshold := float64(params.LowUsageThreshold) / 100.0 + if lowUsageThreshold < 0 || lowUsageThreshold > 1 { + lowUsageThreshold = float64(DefaultGPOConfig.LowUsageThreshold) / 100.0 + utils.Logger().Warn(). + Float64("provided", float64(params.LowUsageThreshold)/100.0). + Float64("updated", lowUsageThreshold). + Msg("Sanitizing invalid gasprice oracle lowUsageThreshold") } + blockGasLimit := params.BlockGasLimit return &Oracle{ - backend: backend, - lastPrice: params.Default, - maxPrice: maxPrice, - checkBlocks: blocks, - percentile: percent, + backend: backend, + lastPrice: defaultPrice, + maxPrice: maxPrice, + checkBlocks: blocks, + percentile: percentile, + checkTxs: txs, + lowUsageThreshold: lowUsageThreshold, + blockGasLimit: blockGasLimit, + // do not reference lastPrice + defaultPrice: new(big.Int).Set(defaultPrice), } } @@ -124,9 +149,10 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) { result = make(chan getBlockPricesResult, gpo.checkBlocks) quit = make(chan struct{}) txPrices []*big.Int + usageSum float64 ) for sent < gpo.checkBlocks && number > 0 { - go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(number))), number, sampleNumber, result, quit) + go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(number))), number, gpo.checkTxs, result, quit) sent++ exp++ number-- @@ -149,18 +175,26 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) { // meaningful returned, try to query more blocks. But the maximum // is 2*checkBlocks. if len(res.prices) == 1 && len(txPrices)+1+exp < gpo.checkBlocks*2 && number > 0 { - go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(number))), number, sampleNumber, result, quit) + go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(number))), number, gpo.checkTxs, result, quit) sent++ exp++ number-- } txPrices = append(txPrices, res.prices...) + usageSum += res.usage } price := lastPrice if len(txPrices) > 0 { sort.Sort(bigIntArray(txPrices)) price = txPrices[(len(txPrices)-1)*gpo.percentile/100] } + // `sent` is the number of queries that are sent, while `exp` and `number` count down at query resolved, and sent respectively + // each query is per block, therefore `sent` is the number of blocks for which the usage was (successfully) determined + // approximation that only holds when the gas limits, of all blocks that are sampled, are equal + usage := usageSum / float64(sent) + if usage < gpo.lowUsageThreshold { + price = new(big.Int).Set(gpo.defaultPrice) + } if price.Cmp(gpo.maxPrice) > 0 { price = new(big.Int).Set(gpo.maxPrice) } @@ -173,6 +207,7 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) { type getBlockPricesResult struct { prices []*big.Int + usage float64 err error } @@ -192,7 +227,9 @@ func (gpo *Oracle) getBlockPrices(ctx context.Context, signer types.Signer, bloc block, err := gpo.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum)) if block == nil { select { - case result <- getBlockPricesResult{nil, err}: + // when no block is found, `err` is returned which short-circuits the oracle entirely + // therefore the `usage` becomes irrelevant + case result <- getBlockPricesResult{nil, 2.0, err}: case <-quit: } return @@ -212,8 +249,18 @@ func (gpo *Oracle) getBlockPrices(ctx context.Context, signer types.Signer, bloc } } } + // HACK + var gasLimit float64 + if gpo.blockGasLimit == 0 { + gasLimit = float64(block.GasLimit()) + } else { + gasLimit = float64(gpo.blockGasLimit) + } + // if `gasLimit` is 0, no crash. +Inf is returned and percentile is applied + // this usage includes any transactions from the miner, which are excluded by the `prices` slice + usage := float64(block.GasUsed()) / gasLimit select { - case result <- getBlockPricesResult{prices, nil}: + case result <- getBlockPricesResult{prices, usage, nil}: case <-quit: } } diff --git a/hmy/hmy.go b/hmy/hmy.go index fd01f123c6..24f0caa127 100644 --- a/hmy/hmy.go +++ b/hmy/hmy.go @@ -157,12 +157,8 @@ func New( } // Setup gas price oracle - gpoParams := GasPriceConfig{ - Blocks: 20, // take all eligible txs past 20 blocks and sort them - Percentile: 80, // get the 80th percentile when sorted in an ascending manner - Default: big.NewInt(100e9), // minimum of 100 gwei - } - gpo := NewOracle(backend, gpoParams) + config := nodeAPI.GetConfig().HarmonyConfig.GPO + gpo := NewOracle(backend, &config) backend.gpo = gpo return backend diff --git a/internal/chain/engine.go b/internal/chain/engine.go index 6e018dccfd..71bb0d3052 100644 --- a/internal/chain/engine.go +++ b/internal/chain/engine.go @@ -632,7 +632,7 @@ func payloadArgsFromCrossLink(cl types.CrossLink) payloadArgs { } func (args payloadArgs) constructPayload(chain engine.ChainReader) []byte { - return signature.ConstructCommitPayload(chain, args.epoch, args.blockHash, args.number, args.viewID) + return signature.ConstructCommitPayload(chain.Config(), args.epoch, args.blockHash, args.number, args.viewID) } type sigArgs struct { diff --git a/internal/chain/engine_test.go b/internal/chain/engine_test.go index 5a842088c8..067b265ca0 100644 --- a/internal/chain/engine_test.go +++ b/internal/chain/engine_test.go @@ -275,7 +275,7 @@ func (kp blsKeyPair) Pub() bls.SerializedPublicKey { func (kp blsKeyPair) Sign(block *types.Block) []byte { chain := &fakeBlockChain{config: *params.LocalnetChainConfig} - msg := consensus_sig.ConstructCommitPayload(chain, block.Epoch(), block.Hash(), + msg := consensus_sig.ConstructCommitPayload(chain.Config(), block.Epoch(), block.Hash(), block.Number().Uint64(), block.Header().ViewID().Uint64()) sig := kp.pri.SignHash(msg) diff --git a/internal/chain/reward.go b/internal/chain/reward.go index 664b53bcad..f06556412f 100644 --- a/internal/chain/reward.go +++ b/internal/chain/reward.go @@ -138,7 +138,7 @@ func lookupDelegatorShares( // Handle block rewards during pre-staking era func accumulateRewardsAndCountSigsBeforeStaking( bc engine.ChainReader, state *state.DB, - header *block.Header, beaconChain engine.ChainReader, sigsReady chan bool, + header *block.Header, sigsReady chan bool, ) (reward.Reader, error) { parentHeader := bc.GetHeaderByHash(header.ParentHash()) @@ -252,7 +252,7 @@ func AccumulateRewardsAndCountSigs( // Pre-staking era if !bc.Config().IsStaking(epoch) { - return accumulateRewardsAndCountSigsBeforeStaking(bc, state, header, beaconChain, sigsReady) + return accumulateRewardsAndCountSigsBeforeStaking(bc, state, header, sigsReady) } // Rewards are accumulated only in the beaconchain, so just wait for commit sigs and return. diff --git a/internal/cli/flag.go b/internal/cli/flag.go index f178789bd1..755a6a73b9 100644 --- a/internal/cli/flag.go +++ b/internal/cli/flag.go @@ -3,7 +3,9 @@ package cli -import "github.com/spf13/pflag" +import ( + "github.com/spf13/pflag" +) // Flag is the interface for cli flags. // To get the value after cli parsing, use fs.GetString(flag.Name) @@ -62,6 +64,23 @@ func (f IntFlag) RegisterTo(fs *pflag.FlagSet) error { return markHiddenOrDeprecated(fs, f.Name, f.Deprecated, f.Hidden) } +// Int64Flag is the flag with int64 value, used for gwei configurations +type Int64Flag struct { + Name string + Shorthand string + Usage string + Deprecated string + Hidden bool + + DefValue int64 +} + +// RegisterTo register the int flag to FlagSet +func (f Int64Flag) RegisterTo(fs *pflag.FlagSet) error { + fs.Int64P(f.Name, f.Shorthand, f.DefValue, f.Usage) + return markHiddenOrDeprecated(fs, f.Name, f.Deprecated, f.Hidden) +} + // StringSliceFlag is the flag with string slice value type StringSliceFlag struct { Name string @@ -122,6 +141,8 @@ func getFlagName(flag Flag) string { return f.Name case IntSliceFlag: return f.Name + case Int64Flag: + return f.Name } return "" } diff --git a/internal/cli/parse.go b/internal/cli/parse.go index bc9565a3e3..326c923ad5 100644 --- a/internal/cli/parse.go +++ b/internal/cli/parse.go @@ -70,6 +70,12 @@ func GetIntFlagValue(cmd *cobra.Command, flag IntFlag) int { return getIntFlagValue(cmd.Flags(), flag) } +// GetInt64FlagValue get the int value for the given Int64Flag from the local flags of the +// cobra command. +func GetInt64FlagValue(cmd *cobra.Command, flag Int64Flag) int64 { + return getInt64FlagValue(cmd.Flags(), flag) +} + // GetIntPersistentFlagValue get the int value for the given IntFlag from the persistent // flags of the cobra command. func GetIntPersistentFlagValue(cmd *cobra.Command, flag IntFlag) int { @@ -85,6 +91,15 @@ func getIntFlagValue(fs *pflag.FlagSet, flag IntFlag) int { return val } +func getInt64FlagValue(fs *pflag.FlagSet, flag Int64Flag) int64 { + val, err := fs.GetInt64(flag.Name) + if err != nil { + handleParseError(err) + return 0 + } + return val +} + // GetStringSliceFlagValue get the string slice value for the given StringSliceFlag from // the local flags of the cobra command. func GetStringSliceFlagValue(cmd *cobra.Command, flag StringSliceFlag) []string { diff --git a/internal/configs/harmony/harmony.go b/internal/configs/harmony/harmony.go index 32161d1deb..f4f2ddb96f 100644 --- a/internal/configs/harmony/harmony.go +++ b/internal/configs/harmony/harmony.go @@ -35,6 +35,7 @@ type HarmonyConfig struct { TiKV *TiKVConfig `toml:",omitempty"` DNSSync DnsSync ShardData ShardDataConfig + GPO GasPriceOracleConfig } func (hc HarmonyConfig) ToRPCServerConfig() nodeconfig.RPCServerConfig { @@ -157,6 +158,25 @@ type ShardDataConfig struct { CacheSize int } +type GasPriceOracleConfig struct { + // the number of blocks to sample + Blocks int + // the number of transactions to sample, per block + Transactions int + // the percentile to pick from there + Percentile int + // the default gas price, if the above data is not available + DefaultPrice int64 + // the maximum suggested gas price + MaxPrice int64 + // when block usage (gas) for last `Blocks` blocks is below `LowUsageThreshold`, + // we return the Default price + LowUsageThreshold int + // hack: our block header reports an 80m gas limit, but it is actually 30M. + // if set to non-zero, this is applied UNCHECKED + BlockGasLimit int +} + type ConsensusConfig struct { MinPeers int AggregateSig bool diff --git a/internal/registry/registry.go b/internal/registry/registry.go index 98b69a3ef5..7032609103 100644 --- a/internal/registry/registry.go +++ b/internal/registry/registry.go @@ -4,13 +4,18 @@ import ( "sync" "github.com/harmony-one/harmony/core" + "github.com/harmony-one/harmony/webhooks" ) // Registry consolidates services at one place. type Registry struct { - mu sync.Mutex - blockchain core.BlockChain - txPool *core.TxPool + mu sync.Mutex + blockchain core.BlockChain + beaconchain core.BlockChain + webHooks *webhooks.Hooks + txPool *core.TxPool + cxPool *core.CxPool + isBackup bool } // New creates a new registry. @@ -35,6 +40,40 @@ func (r *Registry) GetBlockchain() core.BlockChain { return r.blockchain } +// SetBeaconchain sets the beaconchain to registry. +func (r *Registry) SetBeaconchain(bc core.BlockChain) *Registry { + r.mu.Lock() + defer r.mu.Unlock() + + r.beaconchain = bc + return r +} + +// GetBeaconchain gets the beaconchain from registry. +func (r *Registry) GetBeaconchain() core.BlockChain { + r.mu.Lock() + defer r.mu.Unlock() + + return r.beaconchain +} + +// SetWebHooks sets the webhooks to registry. +func (r *Registry) SetWebHooks(hooks *webhooks.Hooks) *Registry { + r.mu.Lock() + defer r.mu.Unlock() + + r.webHooks = hooks + return r +} + +// GetWebHooks gets the webhooks from registry. +func (r *Registry) GetWebHooks() *webhooks.Hooks { + r.mu.Lock() + defer r.mu.Unlock() + + return r.webHooks +} + // SetTxPool sets the txpool to registry. func (r *Registry) SetTxPool(txPool *core.TxPool) *Registry { r.mu.Lock() @@ -51,3 +90,35 @@ func (r *Registry) GetTxPool() *core.TxPool { return r.txPool } + +func (r *Registry) SetIsBackup(isBackup bool) *Registry { + r.mu.Lock() + defer r.mu.Unlock() + + r.isBackup = isBackup + return r +} + +func (r *Registry) IsBackup() bool { + r.mu.Lock() + defer r.mu.Unlock() + + return r.isBackup +} + +// SetCxPool sets the cxpool to registry. +func (r *Registry) SetCxPool(cxPool *core.CxPool) *Registry { + r.mu.Lock() + defer r.mu.Unlock() + + r.cxPool = cxPool + return r +} + +// GetCxPool gets the cxpool from registry. +func (r *Registry) GetCxPool() *core.CxPool { + r.mu.Lock() + defer r.mu.Unlock() + + return r.cxPool +} diff --git a/internal/shardchain/shardchains.go b/internal/shardchain/shardchains.go index 1be2c68414..66cfad220a 100644 --- a/internal/shardchain/shardchains.go +++ b/internal/shardchain/shardchains.go @@ -107,7 +107,7 @@ func (sc *CollectionImpl) ShardChain(shardID uint32, options ...core.Options) (c Msg("disable cache, running in archival mode") } else { cacheConfig = &core.CacheConfig{ - TrieNodeLimit: 256 * 1024 * 1024, + TrieNodeLimit: 256, TrieTimeLimit: 2 * time.Minute, TriesInMemory: 128, } @@ -172,9 +172,8 @@ func initStateCache(db ethdb.Database, sc *CollectionImpl, shardID uint32) (stat return nil, err } return state.NewDatabaseWithCache(stateDB, 64), nil - } else { - return state.NewDatabase(db), nil } + return nil, nil } // DisableCache disables caching mode for newly opened chains. diff --git a/node/node.go b/node/node.go index 710751776f..06aecb94d9 100644 --- a/node/node.go +++ b/node/node.go @@ -661,6 +661,7 @@ func validateShardBoundMessage(consensus *consensus.Consensus, nodeConfig *nodec } var ( + errMsgHadNoHMYPayLoadAssumption = errors.New("did not have sufficient size for hmy msg") errConsensusMessageOnUnexpectedTopic = errors.New("received consensus on wrong topic") ) @@ -1106,7 +1107,7 @@ func New( node.TxPool = core.NewTxPool(txPoolConfig, node.Blockchain().Config(), blockchain, node.TransactionErrorSink) node.registry.SetTxPool(node.TxPool) - node.CxPool = core.NewCxPool(core.CxPoolSize) + node.CxPool = node.registry.GetCxPool() node.Worker = worker.New(node.Blockchain().Config(), blockchain, beaconChain, engine) node.deciderCache, _ = lru.New(16) diff --git a/node/node_cross_shard.go b/node/node_cross_shard.go index 014432c4ec..e516394834 100644 --- a/node/node_cross_shard.go +++ b/node/node_cross_shard.go @@ -3,6 +3,8 @@ package node import ( "github.com/ethereum/go-ethereum/rlp" proto_node "github.com/harmony-one/harmony/api/proto/node" + "github.com/harmony-one/harmony/block" + "github.com/harmony-one/harmony/consensus" "github.com/harmony-one/harmony/core" "github.com/harmony-one/harmony/core/types" nodeconfig "github.com/harmony-one/harmony/internal/configs/node" @@ -13,7 +15,7 @@ import ( // BroadcastCXReceipts broadcasts cross shard receipts to correspoding // destination shards -func (node *Node) BroadcastCXReceipts(newBlock *types.Block) { +func BroadcastCXReceipts(newBlock *types.Block, consensus *consensus.Consensus) { commitSigAndBitmap := newBlock.GetCurrentCommitSig() //#### Read payload data from committed msg if len(commitSigAndBitmap) <= 96 { @@ -31,27 +33,27 @@ func (node *Node) BroadcastCXReceipts(newBlock *types.Block) { epoch := newBlock.Header().Epoch() shardingConfig := shard.Schedule.InstanceForEpoch(epoch) shardNum := int(shardingConfig.NumShards()) - myShardID := node.Consensus.ShardID + myShardID := consensus.ShardID utils.Logger().Info().Int("shardNum", shardNum).Uint32("myShardID", myShardID).Uint64("blockNum", newBlock.NumberU64()).Msg("[BroadcastCXReceipts]") for i := 0; i < shardNum; i++ { if i == int(myShardID) { continue } - node.BroadcastCXReceiptsWithShardID(newBlock, commitSig, commitBitmap, uint32(i)) + BroadcastCXReceiptsWithShardID(newBlock.Header(), commitSig, commitBitmap, uint32(i), consensus) } } // BroadcastCXReceiptsWithShardID broadcasts cross shard receipts to given ToShardID -func (node *Node) BroadcastCXReceiptsWithShardID(block *types.Block, commitSig []byte, commitBitmap []byte, toShardID uint32) { - myShardID := node.Consensus.ShardID +func BroadcastCXReceiptsWithShardID(block *block.Header, commitSig []byte, commitBitmap []byte, toShardID uint32, consensus *consensus.Consensus) { + myShardID := consensus.ShardID utils.Logger().Debug(). Uint32("toShardID", toShardID). Uint32("myShardID", myShardID). Uint64("blockNum", block.NumberU64()). Msg("[BroadcastCXReceiptsWithShardID]") - cxReceipts, err := node.Blockchain().ReadCXReceipts(toShardID, block.NumberU64(), block.Hash()) + cxReceipts, err := consensus.Blockchain().ReadCXReceipts(toShardID, block.NumberU64(), block.Hash()) if err != nil || len(cxReceipts) == 0 { utils.Logger().Debug().Uint32("ToShardID", toShardID). Int("numCXReceipts", len(cxReceipts)). @@ -59,7 +61,7 @@ func (node *Node) BroadcastCXReceiptsWithShardID(block *types.Block, commitSig [ return } - merkleProof, err := node.Blockchain().CXMerkleProof(toShardID, block) + merkleProof, err := consensus.Blockchain().CXMerkleProof(toShardID, block) if err != nil { utils.Logger().Warn(). Uint32("ToShardID", toShardID). @@ -70,7 +72,7 @@ func (node *Node) BroadcastCXReceiptsWithShardID(block *types.Block, commitSig [ cxReceiptsProof := &types.CXReceiptsProof{ Receipts: cxReceipts, MerkleProof: merkleProof, - Header: block.Header(), + Header: block, CommitSig: commitSig, CommitBitmap: commitBitmap, } @@ -81,36 +83,40 @@ func (node *Node) BroadcastCXReceiptsWithShardID(block *types.Block, commitSig [ Interface("cxp", cxReceiptsProof). Msg("[BroadcastCXReceiptsWithShardID] ReadCXReceipts and MerkleProof ready. Sending CX receipts...") // TODO ek – limit concurrency - go node.host.SendMessageToGroups([]nodeconfig.GroupID{groupID}, + go consensus.GetHost().SendMessageToGroups([]nodeconfig.GroupID{groupID}, p2p.ConstructMessage(proto_node.ConstructCXReceiptsProof(cxReceiptsProof)), ) } // BroadcastMissingCXReceipts broadcasts missing cross shard receipts per request -func (node *Node) BroadcastMissingCXReceipts() { - sendNextTime := []core.CxEntry{} - it := node.CxPool.Pool().Iterator() +func BroadcastMissingCXReceipts(c *consensus.Consensus) { + var ( + sendNextTime = make([]core.CxEntry, 0) + cxPool = c.Registry().GetCxPool() + blockchain = c.Blockchain() + ) + it := cxPool.Pool().Iterator() for entry := range it.C { cxEntry := entry.(core.CxEntry) toShardID := cxEntry.ToShardID - blk := node.Blockchain().GetBlockByHash(cxEntry.BlockHash) + blk := blockchain.GetBlockByHash(cxEntry.BlockHash) if blk == nil { continue } blockNum := blk.NumberU64() - nextHeader := node.Blockchain().GetHeaderByNumber(blockNum + 1) + nextHeader := blockchain.GetHeaderByNumber(blockNum + 1) if nextHeader == nil { sendNextTime = append(sendNextTime, cxEntry) continue } sig := nextHeader.LastCommitSignature() bitmap := nextHeader.LastCommitBitmap() - node.BroadcastCXReceiptsWithShardID(blk, sig[:], bitmap, toShardID) + BroadcastCXReceiptsWithShardID(blk.Header(), sig[:], bitmap, toShardID, c) } - node.CxPool.Clear() + cxPool.Clear() // this should not happen or maybe happen for impatient user for _, entry := range sendNextTime { - node.CxPool.Add(entry) + cxPool.Add(entry) } } diff --git a/node/node_explorer.go b/node/node_explorer.go index 0d3f31f28b..0dd7319761 100644 --- a/node/node_explorer.go +++ b/node/node_explorer.go @@ -68,7 +68,7 @@ func (node *Node) explorerMessageHandler(ctx context.Context, msg *msg_pb.Messag return errBlockBeforeCommit } - commitPayload := signature.ConstructCommitPayload(node.Blockchain(), + commitPayload := signature.ConstructCommitPayload(node.Blockchain().Config(), block.Epoch(), block.Hash(), block.Number().Uint64(), block.Header().ViewID().Uint64()) if !aggSig.VerifyHash(mask.AggregatePublic, commitPayload) { utils.Logger(). @@ -148,7 +148,7 @@ func (node *Node) TraceLoopForExplorer() { // AddNewBlockForExplorer add new block for explorer. func (node *Node) AddNewBlockForExplorer(block *types.Block) { if node.HarmonyConfig.General.RunElasticMode && node.HarmonyConfig.TiKV.Role == tikv.RoleReader { - node.Consensus.FBFTLog.DeleteBlockByNumber(block.NumberU64()) + node.Consensus.DeleteBlockByNumber(block.NumberU64()) return } @@ -159,7 +159,7 @@ func (node *Node) AddNewBlockForExplorer(block *types.Block) { node.Consensus.UpdateConsensusInformation() } // Clean up the blocks to avoid OOM. - node.Consensus.FBFTLog.DeleteBlockByNumber(block.NumberU64()) + node.Consensus.DeleteBlockByNumber(block.NumberU64()) // if in tikv mode, only master writer node need dump all explorer block if !node.HarmonyConfig.General.RunElasticMode || node.Blockchain().IsTikvWriterMaster() { @@ -216,8 +216,8 @@ func (node *Node) commitBlockForExplorer(block *types.Block) { curNum := block.NumberU64() if curNum-100 > 0 { - node.Consensus.FBFTLog.DeleteBlocksLessThan(curNum - 100) - node.Consensus.FBFTLog.DeleteMessagesLessThan(curNum - 100) + node.Consensus.DeleteBlocksLessThan(curNum - 100) + node.Consensus.DeleteMessagesLessThan(curNum - 100) } } diff --git a/node/node_handler.go b/node/node_handler.go index acc4afc266..92c3396d4b 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -25,7 +25,6 @@ import ( "github.com/harmony-one/harmony/staking/slash" staking "github.com/harmony-one/harmony/staking/types" "github.com/harmony-one/harmony/webhooks" - "github.com/pkg/errors" ) const p2pMsgPrefixSize = 5 @@ -140,8 +139,8 @@ func (node *Node) stakingMessageHandler(msgPayload []byte) { // BroadcastNewBlock is called by consensus leader to sync new blocks with other clients/nodes. // NOTE: For now, just send to the client (basically not broadcasting) // TODO (lc): broadcast the new blocks to new nodes doing state sync -func (node *Node) BroadcastNewBlock(newBlock *types.Block) { - groups := []nodeconfig.GroupID{node.NodeConfig.GetClientGroupID()} +func (node *Node) BroadcastNewBlock(newBlock *types.Block, nodeConfig *nodeconfig.ConfigType) { + groups := []nodeconfig.GroupID{nodeConfig.GetClientGroupID()} utils.Logger().Info(). Msgf( "broadcasting new block %d, group %s", newBlock.NumberU64(), groups[0], @@ -328,38 +327,6 @@ func getCrosslinkHeadersForShards(shardChain core.BlockChain, curBlock *types.Bl return headers, nil } -// VerifyNewBlock is called by consensus participants to verify the block (account model) they are -// running consensus on. -func VerifyNewBlock(nodeConfig *nodeconfig.ConfigType, blockChain core.BlockChain, beaconChain core.BlockChain) func(*types.Block) error { - return func(newBlock *types.Block) error { - if err := blockChain.ValidateNewBlock(newBlock, beaconChain); err != nil { - if hooks := nodeConfig.WebHooks.Hooks; hooks != nil { - if p := hooks.ProtocolIssues; p != nil { - url := p.OnCannotCommit - go func() { - webhooks.DoPost(url, map[string]interface{}{ - "bad-header": newBlock.Header(), - "reason": err.Error(), - }) - }() - } - } - utils.Logger().Error(). - Str("blockHash", newBlock.Hash().Hex()). - Int("numTx", len(newBlock.Transactions())). - Int("numStakingTx", len(newBlock.StakingTransactions())). - Err(err). - Msg("[VerifyNewBlock] Cannot Verify New Block!!!") - return errors.Errorf( - "[VerifyNewBlock] Cannot Verify New Block!!! block-hash %s txn-count %d", - newBlock.Hash().Hex(), - len(newBlock.Transactions()), - ) - } - return nil - } -} - // PostConsensusProcessing is called by consensus participants, after consensus is done, to: // 1. [leader] send new block to the client // 2. [leader] send cross shard tx receipts to destination shard @@ -368,11 +335,12 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) error { if node.IsRunningBeaconChain() { // TODO: consider removing this and letting other nodes broadcast new blocks. // But need to make sure there is at least 1 node that will do the job. - node.BroadcastNewBlock(newBlock) + node.BroadcastNewBlock(newBlock, node.NodeConfig) } - node.BroadcastCXReceipts(newBlock) + BroadcastCXReceipts(newBlock, node.Consensus) } else { if node.Consensus.Mode() != consensus.Listening { + numSignatures := node.Consensus.NumSignaturesIncludedInBlock(newBlock) utils.Logger().Info(). Uint64("blockNum", newBlock.NumberU64()). Uint64("epochNum", newBlock.Epoch().Uint64()). @@ -380,26 +348,25 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) error { Str("blockHash", newBlock.Hash().String()). Int("numTxns", len(newBlock.Transactions())). Int("numStakingTxns", len(newBlock.StakingTransactions())). - Uint32("numSignatures", node.Consensus.NumSignaturesIncludedInBlock(newBlock)). + Uint32("numSignatures", numSignatures). Msg("BINGO !!! Reached Consensus") - numSig := float64(node.Consensus.NumSignaturesIncludedInBlock(newBlock)) - node.Consensus.UpdateValidatorMetrics(numSig, float64(newBlock.NumberU64())) + node.Consensus.UpdateValidatorMetrics(float64(numSignatures), float64(newBlock.NumberU64())) // 1% of the validator also need to do broadcasting rnd := rand.Intn(100) if rnd < 1 { // Beacon validators also broadcast new blocks to make sure beacon sync is strong. if node.IsRunningBeaconChain() { - node.BroadcastNewBlock(newBlock) + node.BroadcastNewBlock(newBlock, node.NodeConfig) } - node.BroadcastCXReceipts(newBlock) + BroadcastCXReceipts(newBlock, node.Consensus) } } } // Broadcast client requested missing cross shard receipts if there is any - node.BroadcastMissingCXReceipts() + BroadcastMissingCXReceipts(node.Consensus) if h := node.NodeConfig.WebHooks.Hooks; h != nil { if h.Availability != nil { diff --git a/node/node_handler_test.go b/node/node_handler_test.go index 25d966f469..3de2918398 100644 --- a/node/node_handler_test.go +++ b/node/node_handler_test.go @@ -103,7 +103,7 @@ func TestVerifyNewBlock(t *testing.T) { t.Fatal("cannot get blockchain") } reg := registry.New().SetBlockchain(blockchain) - consensus, err := consensus.New( + consensusObj, err := consensus.New( host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsKey), reg, decider, 3, false, ) if err != nil { @@ -112,7 +112,7 @@ func TestVerifyNewBlock(t *testing.T) { archiveMode := make(map[uint32]bool) archiveMode[0] = true archiveMode[1] = false - node := New(host, consensus, engine, collection, nil, nil, nil, archiveMode, nil, reg) + node := New(host, consensusObj, engine, collection, nil, nil, nil, archiveMode, nil, reg) txs := make(map[common.Address]types.Transactions) stks := staking.StakingTransactions{} @@ -129,7 +129,7 @@ func TestVerifyNewBlock(t *testing.T) { // work around vrf verification as it's tested in another test. node.Blockchain().Config().VRFEpoch = big.NewInt(2) - if err := VerifyNewBlock(nil, node.Blockchain(), node.Beaconchain())(block); err != nil { + if err := consensus.VerifyNewBlock(nil, node.Blockchain(), node.Beaconchain())(block); err != nil { t.Error("New block is not verified successfully:", err) } } diff --git a/node/node_newblock.go b/node/node_newblock.go index 27c0d843bd..008182fbcc 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -76,7 +76,7 @@ func (node *Node) WaitForConsensusReadyV2(cs *consensus.Consensus, stopChan chan } else { newCommitSigsChan <- sigs } - case commitSigs := <-cs.CommitSigChannel(): + case commitSigs := <-cs.GetCommitSigChannel(): utils.Logger().Info().Msg("[ProposeNewBlock] received commit sigs asynchronously") if len(commitSigs) > bls.BLSSignatureSizeInBytes { newCommitSigsChan <- commitSigs diff --git a/node/node_newblock_test.go b/node/node_newblock_test.go index 492175b1d2..39affacaba 100644 --- a/node/node_newblock_test.go +++ b/node/node_newblock_test.go @@ -46,14 +46,15 @@ func TestFinalizeNewBlockAsync(t *testing.T) { decider := quorum.NewDecider( quorum.SuperMajorityVote, shard.BeaconChainShardID, ) - consensus, err := consensus.New( - host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsKey), nil, decider, 3, false, + reg := registry.New().SetBlockchain(blockchain).SetBeaconchain(blockchain) + consensusObj, err := consensus.New( + host, shard.BeaconChainShardID, multibls.GetPrivateKeys(blsKey), reg, decider, 3, false, ) if err != nil { t.Fatalf("Cannot craeate consensus: %v", err) } - node := New(host, consensus, engine, collection, nil, nil, nil, nil, nil, registry.New().SetBlockchain(blockchain)) + node := New(host, consensusObj, engine, collection, nil, nil, nil, nil, nil, registry.New().SetBlockchain(blockchain)) node.Worker.UpdateCurrent() @@ -71,7 +72,7 @@ func TestFinalizeNewBlockAsync(t *testing.T) { commitSigs, func() uint64 { return 0 }, common.Address{}, nil, nil, ) - if err := VerifyNewBlock(nil, blockchain, nil)(block); err != nil { + if err := consensus.VerifyNewBlock(nil, blockchain, nil)(block); err != nil { t.Error("New block is not verified successfully:", err) } diff --git a/node/node_syncing.go b/node/node_syncing.go index 05ddd4b6b7..84eb1256ff 100644 --- a/node/node_syncing.go +++ b/node/node_syncing.go @@ -109,9 +109,10 @@ func (node *Node) createStagedSync(bc core.BlockChain) *stagedsync.StagedSync { mutatedPort := strconv.Itoa(mySyncPort + legacysync.SyncingPortDifference) role := node.NodeConfig.Role() isExplorer := node.NodeConfig.Role() == nodeconfig.ExplorerNode + dbDir := node.NodeConfig.DBDir if s, err := stagedsync.CreateStagedSync(node.SelfPeer.IP, mutatedPort, - node.GetSyncID(), bc, role, isExplorer, + node.GetSyncID(), bc, dbDir, role, isExplorer, node.NodeConfig.StagedSyncTurboMode, node.NodeConfig.UseMemDB, node.NodeConfig.DoubleCheckBlockHashes, @@ -314,7 +315,8 @@ func (node *Node) doSync(bc core.BlockChain, worker *worker.Worker, willJoinCons if willJoinConsensus { node.Consensus.BlocksNotSynchronized() } - syncInstance.SyncLoop(bc, worker, false, node.Consensus, legacysync.LoopMinTime) + isBeacon := bc.ShardID() == shard.BeaconChainShardID + syncInstance.SyncLoop(bc, worker, isBeacon, node.Consensus, legacysync.LoopMinTime) if willJoinConsensus { node.IsSynchronized.Set() node.Consensus.BlocksSynchronized() diff --git a/node/worker/worker.go b/node/worker/worker.go index 1a711bc193..5a4234229a 100644 --- a/node/worker/worker.go +++ b/node/worker/worker.go @@ -300,7 +300,7 @@ func (w *Worker) CommitReceipts(receiptsList []*types.CXReceiptsProof) error { // UpdateCurrent updates the current environment with the current state and header. func (w *Worker) UpdateCurrent() error { - parent := w.chain.CurrentBlock() + parent := w.chain.CurrentHeader() num := parent.Number() timestamp := time.Now().Unix() @@ -321,7 +321,7 @@ func (w *Worker) GetCurrentHeader() *block.Header { } // makeCurrent creates a new environment for the current cycle. -func (w *Worker) makeCurrent(parent *types.Block, header *block.Header) error { +func (w *Worker) makeCurrent(parent *block.Header, header *block.Header) error { state, err := w.chain.StateAt(parent.Root()) if err != nil { return err @@ -586,7 +586,7 @@ func New( worker.gasFloor = 80000000 worker.gasCeil = 120000000 - parent := worker.chain.CurrentBlock() + parent := worker.chain.CurrentBlock().Header() num := parent.Number() timestamp := time.Now().Unix() diff --git a/node/worker/worker_test.go b/node/worker/worker_test.go index 37d61816cc..4c87c99377 100644 --- a/node/worker/worker_test.go +++ b/node/worker/worker_test.go @@ -5,8 +5,6 @@ import ( "math/rand" "testing" - "github.com/harmony-one/harmony/core/state" - "github.com/harmony-one/harmony/core/rawdb" "github.com/ethereum/go-ethereum/common" @@ -45,7 +43,8 @@ func TestNewWorker(t *testing.T) { genesis := gspec.MustCommit(database) _ = genesis - chain, err := core.NewBlockChain(database, state.NewDatabase(database), &core.BlockChainImpl{}, nil, gspec.Config, engine, vm.Config{}) + cacheConfig := &core.CacheConfig{SnapshotLimit: 0} + chain, err := core.NewBlockChain(database, nil, &core.BlockChainImpl{}, cacheConfig, gspec.Config, engine, vm.Config{}) if err != nil { t.Error(err) @@ -72,7 +71,8 @@ func TestCommitTransactions(t *testing.T) { ) gspec.MustCommit(database) - chain, _ := core.NewBlockChain(database, state.NewDatabase(database), nil, nil, gspec.Config, engine, vm.Config{}) + cacheConfig := &core.CacheConfig{SnapshotLimit: 0} + chain, _ := core.NewBlockChain(database, nil, nil, cacheConfig, gspec.Config, engine, vm.Config{}) // Create a new worker worker := New(params.TestChainConfig, chain, nil, engine) diff --git a/p2p/stream/common/streammanager/streammanager.go b/p2p/stream/common/streammanager/streammanager.go index e57919a76f..26025fb720 100644 --- a/p2p/stream/common/streammanager/streammanager.go +++ b/p2p/stream/common/streammanager/streammanager.go @@ -299,7 +299,7 @@ func (sm *streamManager) removeAllStreamOnClose() { wg.Wait() // Be nice. after close, the field is still accessible to prevent potential panics - sm.streams = newStreamSet() + sm.streams.Erase() } func (sm *streamManager) discoverAndSetupStream(discCtx context.Context) (int, error) { @@ -403,6 +403,14 @@ func newStreamSet() *streamSet { } } +func (ss *streamSet) Erase() { + ss.lock.Lock() + defer ss.lock.Unlock() + + ss.streams = make(map[sttypes.StreamID]sttypes.Stream) + ss.numByProto = make(map[sttypes.ProtoSpec]int) +} + func (ss *streamSet) size() int { ss.lock.RLock() defer ss.lock.RUnlock() diff --git a/p2p/stream/protocols/sync/message/gen.sh b/p2p/stream/protocols/sync/message/gen.sh new file mode 100755 index 0000000000..1e61be7d4f --- /dev/null +++ b/p2p/stream/protocols/sync/message/gen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker run --platform linux/amd64 -v ${PWD}:/tmp ${PROTOC_IMAGE} /tmp/msg.proto \ No newline at end of file diff --git a/p2p/stream/protocols/sync/message/generate.go b/p2p/stream/protocols/sync/message/generate.go index 881c9fc6f5..22f91a10e7 100644 --- a/p2p/stream/protocols/sync/message/generate.go +++ b/p2p/stream/protocols/sync/message/generate.go @@ -1,3 +1,3 @@ package message -//go:generate protoc msg.proto --go_out=. +//go:generate ./gen.sh diff --git a/p2p/stream/protocols/sync/message/msg.pb.go b/p2p/stream/protocols/sync/message/msg.pb.go index edc87badce..5928a7dea4 100644 --- a/p2p/stream/protocols/sync/message/msg.pb.go +++ b/p2p/stream/protocols/sync/message/msg.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.15.8 +// protoc-gen-go v1.30.0 +// protoc v3.12.4 // source: msg.proto package message diff --git a/p2p/stream/protocols/sync/protocol.go b/p2p/stream/protocols/sync/protocol.go index 80ea0927bc..3dcbd6f063 100644 --- a/p2p/stream/protocols/sync/protocol.go +++ b/p2p/stream/protocols/sync/protocol.go @@ -180,7 +180,7 @@ func (p *Protocol) HandleStream(raw libp2p_network.Stream) { Msg("failed to add new stream") return } - fmt.Println("Connected to", raw.Conn().RemotePeer().String(), "(", st.ProtoID(), ")") + fmt.Println("Connected to", raw.Conn().RemotePeer().String(), "(", st.ProtoID(), ")", "my ID: ", raw.Conn().LocalPeer().String()) st.run() } diff --git a/p2p/stream/protocols/sync/stream.go b/p2p/stream/protocols/sync/stream.go index 0af4fff7c4..467588deaf 100644 --- a/p2p/stream/protocols/sync/stream.go +++ b/p2p/stream/protocols/sync/stream.go @@ -298,7 +298,7 @@ func (st *syncStream) computeBlockNumberResp(rid uint64) *syncpb.Message { return syncpb.MakeGetBlockNumberResponseMessage(rid, bn) } -func (st syncStream) computeGetBlockHashesResp(rid uint64, bns []uint64) (*syncpb.Message, error) { +func (st *syncStream) computeGetBlockHashesResp(rid uint64, bns []uint64) (*syncpb.Message, error) { if len(bns) > GetBlockHashesAmountCap { err := fmt.Errorf("GetBlockHashes amount exceed cap: %v>%v", len(bns), GetBlockHashesAmountCap) return nil, err diff --git a/rpc/net.go b/rpc/net.go index 45c122e4bd..70c39fe461 100644 --- a/rpc/net.go +++ b/rpc/net.go @@ -69,3 +69,8 @@ func (s *PublicNetService) Version(ctx context.Context) interface{} { return fmt.Sprintf("%d", s.chainID) } } + +// Listening returns an indication if the node is listening for network connections. +func (s *PublicNetService) Listening() bool { + return true // always listening +} diff --git a/scripts/docker/Dockerfile b/scripts/docker/Dockerfile index 92b566ef47..197117c185 100644 --- a/scripts/docker/Dockerfile +++ b/scripts/docker/Dockerfile @@ -39,7 +39,7 @@ ARG HARMONY_USER_GID=1000 ENV HARMONY_HOME=/harmony ENV HOME=${HARMONY_HOME} -RUN apk add --no-cache bash~=5.1.16-r2 bind-tools~=9.16.37-r0 tini~=0.19.0 curl==7.83.1-r6 sed~=4.8-r0 \ +RUN apk add --no-cache bash bind-tools tini curl sed \ && rm -rf /var/cache/apk/* \ && addgroup -g ${HARMONY_USER_GID} ${HARMONY_USER} \ && adduser -u ${HARMONY_USER_UID} -G ${HARMONY_USER} --shell /sbin/nologin --no-create-home -D ${HARMONY_USER} \ diff --git a/scripts/gogenerate.sh b/scripts/gogenerate.sh index 9adb847d00..91c67661ab 100755 --- a/scripts/gogenerate.sh +++ b/scripts/gogenerate.sh @@ -6,4 +6,4 @@ case "${0}" in *) progdir=.;; esac git grep -l '^//go:generate ' -- '*.go' | \ - "${progdir}/xargs_by_dir.sh" go generate -v -x + PROTOC_IMAGE="frozen621/harmony-proto:latest" "${progdir}/xargs_by_dir.sh" go generate -v -x diff --git a/scripts/install_build_tools.sh b/scripts/install_build_tools.sh deleted file mode 100755 index abebcce3c6..0000000000 --- a/scripts/install_build_tools.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -set -eu - -unset -v progdir -case "${0}" in -/*) progdir="/";; -*/*) progdir="${0%/*}";; -*) progdir="."; -esac - -sed -n 's/^ _ "\([^"]*\)"$/\1/p' "${progdir}/../tools/tools.go" | \ - xargs "${progdir}/goget.sh" - -"${progdir}/install_protoc.sh" -V 3.15.8 diff --git a/scripts/install_protoc.sh b/scripts/install_protoc.sh deleted file mode 100755 index afb4f4866e..0000000000 --- a/scripts/install_protoc.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash -set -eu -unset -v opt OPTIND OPTARG version platform destdir -version= -platform= -destdir=/usr/local -usage() { - case $# in - [1-9]*) echo "$@" >&2;; - esac - cat <<- ENDEND - usage: install_protoc.sh [-P platform] [-d destdir] -V version - options: - -V version protobuf version - -P platform fetch and use given platform (default: autodetect) - -d destdir install into the given dir (default: /usr/local) - -h print this help - ENDEND - exit 64 -} - -while getopts :V:P:d:h opt -do - case "${opt}" in - V) version="${OPTARG}";; - P) platform="${OPTARG}";; - d) destdir="${OPTARG}";; - h) usage;; - "?") usage "unrecognized option -${OPTARG}";; - ":") usage "missing argument for -${OPTARG}";; - *) echo "unhandled option -${OPTARG}" >&2; exit 70;; - esac -done -shift $((${OPTIND} - 1)) -case "${version}" in -"") usage "protobuf version (-V) not specified";; -esac -case "${platform}" in -"") - platform=$(uname -s) - case "${platform}" in - Darwin) platform=osx;; - Linux) platform=linux;; - *) echo "unsupported OS name (${platform})" >&2; exit 69;; - esac - arch=$(uname -m) - case "${arch}" in - aarch64) arch=aarch_64;; - esac - platform="${platform}-${arch}" - ;; -esac -unset -v tmpdir -trap 'case "${tmpdir-}" in ?*) rm -rf "${tmpdir}";; esac' EXIT -tmpdir=$(mktemp -d) -cd "${tmpdir}" -unset -v filename url -filename="protoc-${version}-${platform}.zip" -url="https://github.com/protocolbuffers/protobuf/releases/download/v${version}/${filename}" -echo "Downloading protoc v${version} for ${platform}..." -curl -s -S -L -o "${filename}" "${url}" -echo "Downloaded as ${filename}; unzipping into ${destdir}..." -sudo unzip -o -d "${destdir}" "${filename}" -echo "protoc v${version} has been installed in ${destdir}." -sudo chmod +x "${destdir}/bin/protoc" -exit 0 diff --git a/staking/slash/double-sign.go b/staking/slash/double-sign.go index 6c871f9920..aaaea01300 100644 --- a/staking/slash/double-sign.go +++ b/staking/slash/double-sign.go @@ -248,7 +248,7 @@ func Verify( publicKey.Add(publicKeyObj) } // slash verification only happens in staking era, therefore want commit payload for staking epoch - commitPayload := consensus_sig.ConstructCommitPayload(chain, + commitPayload := consensus_sig.ConstructCommitPayload(chain.Config(), candidate.Evidence.Epoch, ballot.BlockHeaderHash, candidate.Evidence.Height, candidate.Evidence.ViewID) utils.Logger().Debug(). Uint64("epoch", candidate.Evidence.Epoch.Uint64()). diff --git a/staking/slash/double-sign_test.go b/staking/slash/double-sign_test.go index 470a8ae1d8..7bed53b94e 100644 --- a/staking/slash/double-sign_test.go +++ b/staking/slash/double-sign_test.go @@ -1151,8 +1151,7 @@ func (kp blsKeyPair) Pub() bls.SerializedPublicKey { } func (kp blsKeyPair) Sign(block *types.Block) []byte { - chain := &fakeBlockChain{config: *params.LocalnetChainConfig} - msg := consensus_sig.ConstructCommitPayload(chain, block.Epoch(), block.Hash(), + msg := consensus_sig.ConstructCommitPayload(params.LocalnetChainConfig, block.Epoch(), block.Hash(), block.Number().Uint64(), block.Header().ViewID().Uint64()) sig := kp.pri.SignHash(msg) diff --git a/staking/verify/verify.go b/staking/verify/verify.go index 38783d4dbe..efc7e18ce7 100644 --- a/staking/verify/verify.go +++ b/staking/verify/verify.go @@ -1,54 +1 @@ package verify - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/harmony-one/bls/ffi/go/bls" - "github.com/harmony-one/harmony/consensus/quorum" - "github.com/harmony-one/harmony/consensus/signature" - "github.com/harmony-one/harmony/core" - bls_cosi "github.com/harmony-one/harmony/crypto/bls" - "github.com/harmony-one/harmony/shard" - "github.com/pkg/errors" -) - -var ( - errQuorumVerifyAggSign = errors.New("insufficient voting power to verify aggregate sig") - errAggregateSigFail = errors.New("could not verify hash of aggregate signature") -) - -// AggregateSigForCommittee .. -func AggregateSigForCommittee( - chain core.BlockChain, - committee *shard.Committee, - decider quorum.Decider, - aggSignature *bls.Sign, - hash common.Hash, - blockNum, viewID uint64, - epoch *big.Int, - bitmap []byte, -) error { - committerKeys, err := committee.BLSPublicKeys() - if err != nil { - return err - } - mask, err := bls_cosi.NewMask(committerKeys, nil) - if err != nil { - return err - } - if err := mask.SetMask(bitmap); err != nil { - return err - } - - if !decider.IsQuorumAchievedByMask(mask) { - return errQuorumVerifyAggSign - } - - commitPayload := signature.ConstructCommitPayload(chain, epoch, hash, blockNum, viewID) - if !aggSignature.VerifyHash(mask.AggregatePublic, commitPayload) { - return errAggregateSigFail - } - - return nil -} diff --git a/test/chain/chain/chain_makers.go b/test/chain/chain/chain_makers.go index a902fc8441..52c66b2692 100644 --- a/test/chain/chain/chain_makers.go +++ b/test/chain/chain/chain_makers.go @@ -39,7 +39,7 @@ import ( // See GenerateChain for a detailed explanation. type BlockGen struct { i int - parent *types.Block + parent *block.Header chain []*types.Block factory blockfactory.Factory header *block.Header @@ -140,19 +140,6 @@ func (b *BlockGen) AddUncle(h *block.Header) { b.uncles = append(b.uncles, h) } -// PrevBlock returns a previously generated block by number. It panics if -// num is greater or equal to the number of the block being generated. -// For index -1, PrevBlock returns the parent block given to GenerateChain. -func (b *BlockGen) PrevBlock(index int) *types.Block { - if index >= b.i { - panic(fmt.Errorf("block index %d out of range (%d,%d)", index, -1, b.i)) - } - if index == -1 { - return b.parent - } - return b.chain[index] -} - // GenerateChain creates a chain of n blocks. The first block's // parent will be the provided parent. db is used to store // intermediate states and should contain the parent's state trie. @@ -166,7 +153,7 @@ func (b *BlockGen) PrevBlock(index int) *types.Block { // values. Inserting them into BlockChain requires use of FakePow or // a similar non-validating proof of work implementation. func GenerateChain( - config *params.ChainConfig, parent *types.Block, + config *params.ChainConfig, parent *block.Header, engine consensus_engine.Engine, db ethdb.Database, n int, gen func(int, *BlockGen), @@ -177,7 +164,7 @@ func GenerateChain( factory := blockfactory.NewFactory(config) blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n) chainreader := &fakeChainReader{config: config} - genblock := func(i int, parent *types.Block, statedb *state.DB) (*types.Block, types.Receipts) { + genblock := func(i int, parent *block.Header, statedb *state.DB) (*types.Block, types.Receipts) { b := &BlockGen{ i: i, chain: blocks, @@ -187,7 +174,7 @@ func GenerateChain( factory: factory, engine: engine, } - b.header = makeHeader(chainreader, parent, statedb, b.engine, factory) + b.header = makeHeader(chainreader, parent, statedb, factory) // Execute any user modifications to the block if gen != nil { @@ -223,12 +210,12 @@ func GenerateChain( block, receipt := genblock(i, parent, statedb) blocks[i] = block receipts[i] = receipt - parent = block + parent = block.Header() } return blocks, receipts } -func makeHeader(chain consensus_engine.ChainReader, parent *types.Block, state *state.DB, engine consensus_engine.Engine, factory blockfactory.Factory) *block.Header { +func makeHeader(chain consensus_engine.ChainReader, parent *block.Header, state *state.DB, factory blockfactory.Factory) *block.Header { var time *big.Int if parent.Time() == nil { time = big.NewInt(10) diff --git a/test/chain/main.go b/test/chain/main.go index fd1a74e737..ec28ead0cd 100644 --- a/test/chain/main.go +++ b/test/chain/main.go @@ -15,7 +15,6 @@ import ( blockfactory "github.com/harmony-one/harmony/block/factory" "github.com/harmony-one/harmony/core" core_state "github.com/harmony-one/harmony/core/state" - harmonyState "github.com/harmony-one/harmony/core/state" "github.com/harmony-one/harmony/core/types" "github.com/harmony-one/harmony/core/vm" "github.com/harmony-one/harmony/crypto/hash" @@ -206,7 +205,7 @@ func playFaucetContract(chain core.BlockChain) { func main() { genesis := gspec.MustCommit(database) - chain, _ := core.NewBlockChain(database, harmonyState.NewDatabase(database), nil, nil, gspec.Config, chain.Engine(), vm.Config{}) + chain, _ := core.NewBlockChain(database, nil, nil, nil, gspec.Config, chain.Engine(), vm.Config{}) txpool := core.NewTxPool(core.DefaultTxPoolConfig, chainConfig, chain, types.NewTransactionErrorSink()) backend := &testWorkerBackend{ @@ -223,7 +222,7 @@ func main() { //// Generate a small n-block chain and an uncle block for it n := 3 if n > 0 { - blocks, _ := chain2.GenerateChain(chainConfig, genesis, chain.Engine(), database, n, func(i int, gen *chain2.BlockGen) { + blocks, _ := chain2.GenerateChain(chainConfig, genesis.Header(), chain.Engine(), database, n, func(i int, gen *chain2.BlockGen) { gen.SetCoinbase(FaucetAddress) gen.SetShardID(0) gen.AddTx(pendingTxs[i].(*types.Transaction)) diff --git a/test/chain/reward/main.go b/test/chain/reward/main.go index 5cfe9425a1..17be3b2715 100644 --- a/test/chain/reward/main.go +++ b/test/chain/reward/main.go @@ -109,7 +109,7 @@ func main() { genesis := gspec.MustCommit(database) _ = genesis engine := chain.NewEngine() - bc, _ := core.NewBlockChain(database, state.NewDatabase(database), nil, nil, gspec.Config, engine, vm.Config{}) + bc, _ := core.NewBlockChain(database, nil, nil, nil, gspec.Config, engine, vm.Config{}) statedb, _ := state.New(common2.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) msg := createValidator() statedb.AddBalance(msg.ValidatorAddress, new(big.Int).Mul(big.NewInt(5e18), big.NewInt(2000)))