[sync] add commit signature in peer registeration and new block push

pull/3612/head
Jacky Wang 4 years ago
parent bec43ca07e
commit b91db85c23
No known key found for this signature in database
GPG Key ID: 1085CE5F4FF5842C
  1. 2
      api/service/legacysync/downloader/client.go
  2. 73
      api/service/legacysync/downloader/proto/downloader.pb.go
  3. 1
      api/service/legacysync/downloader/proto/downloader.proto
  4. 2
      api/service/legacysync/syncing.go
  5. 2
      node/node.go
  6. 30
      node/node_syncing.go

@ -113,7 +113,7 @@ func (client *Client) GetBlocksAndSigs(hashes [][]byte) *pb.DownloaderResponse {
func (client *Client) Register(hash []byte, ip, port string) *pb.DownloaderResponse { func (client *Client) Register(hash []byte, ip, port string) *pb.DownloaderResponse {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
request := &pb.DownloaderRequest{Type: pb.DownloaderRequest_REGISTER} request := &pb.DownloaderRequest{Type: pb.DownloaderRequest_REGISTER, RegisterWithSig: true}
request.PeerHash = make([]byte, len(hash)) request.PeerHash = make([]byte, len(hash))
copy(request.PeerHash, hash) copy(request.PeerHash, hash)
request.Ip = ip request.Ip = ip

@ -160,6 +160,7 @@ type DownloaderRequest struct {
Ip string `protobuf:"bytes,5,opt,name=ip,proto3" json:"ip,omitempty"` Ip string `protobuf:"bytes,5,opt,name=ip,proto3" json:"ip,omitempty"`
Port string `protobuf:"bytes,6,opt,name=port,proto3" json:"port,omitempty"` Port string `protobuf:"bytes,6,opt,name=port,proto3" json:"port,omitempty"`
Size uint32 `protobuf:"varint,7,opt,name=size,proto3" json:"size,omitempty"` Size uint32 `protobuf:"varint,7,opt,name=size,proto3" json:"size,omitempty"`
RegisterWithSig bool `protobuf:"varint,8,opt,name=registerWithSig,proto3" json:"registerWithSig,omitempty"` // Expect to have NEWBLOCK response with signature
} }
func (x *DownloaderRequest) Reset() { func (x *DownloaderRequest) Reset() {
@ -243,6 +244,13 @@ func (x *DownloaderRequest) GetSize() uint32 {
return 0 return 0
} }
func (x *DownloaderRequest) GetRegisterWithSig() bool {
if x != nil {
return x.RegisterWithSig
}
return false
}
// DownloaderResponse is the generic response of DownloaderRequest. // DownloaderResponse is the generic response of DownloaderRequest.
type DownloaderResponse struct { type DownloaderResponse struct {
state protoimpl.MessageState state protoimpl.MessageState
@ -313,8 +321,8 @@ var File_downloader_proto protoreflect.FileDescriptor
var file_downloader_proto_rawDesc = []byte{ var file_downloader_proto_rawDesc = []byte{
0x0a, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x0a, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x0a, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x22, 0xf8, 0x74, 0x6f, 0x12, 0x0a, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x22, 0xa2,
0x02, 0x0a, 0x11, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x03, 0x0a, 0x11, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x29, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e,
0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
@ -327,36 +335,39 @@ var file_downloader_proto_rawDesc = []byte{
0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a,
0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x99, 0x01, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x28, 0x0a,
0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x67,
0x09, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x45, 0x57, 0x42, 0x4c, 0x57, 0x69, 0x74, 0x68, 0x53, 0x69, 0x67, 0x22, 0x99, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75,
0x4f, 0x43, 0x4b, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x48, 0x45, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x42, 0x4c, 0x4f, 0x43, 0x4b,
0x49, 0x47, 0x48, 0x54, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10,
0x45, 0x52, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x45, 0x57, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x02, 0x12,
0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x0f, 0x0a, 0x0b, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x48, 0x45, 0x49, 0x47, 0x48, 0x54, 0x10, 0x03,
0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x06, 0x12, 0x0f, 0x0a, 0x0b, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x48, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x10, 0x04, 0x12, 0x13,
0x45, 0x41, 0x44, 0x45, 0x52, 0x10, 0x07, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x0a, 0x0f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55,
0x57, 0x49, 0x54, 0x48, 0x53, 0x49, 0x47, 0x10, 0x08, 0x22, 0xd4, 0x01, 0x0a, 0x12, 0x44, 0x6f, 0x54, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x06,
0x12, 0x0f, 0x0a, 0x0b, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x10,
0x07, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x57, 0x49, 0x54, 0x48, 0x53, 0x49,
0x47, 0x10, 0x08, 0x22, 0xd4, 0x01, 0x0a, 0x12, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61,
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79,
0x6c, 0x6f, 0x61, 0x64, 0x12, 0x47, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x33, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e,
0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a,
0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22,
0x39, 0x0a, 0x14, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45,
0x53, 0x53, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x01, 0x12, 0x0a,
0x0a, 0x06, 0x49, 0x4e, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x02, 0x32, 0x56, 0x0a, 0x0a, 0x44, 0x6f,
0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72,
0x79, 0x12, 0x1d, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x44,
0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x1e, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x6f,
0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x47, 0x0a, 0x04, 0x74, 0x79,
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c,
0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67,
0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48,
0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x39, 0x0a, 0x14, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a,
0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x41,
0x49, 0x4c, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4e, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x02,
0x32, 0x56, 0x0a, 0x0a, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x48,
0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1d, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
0x61, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
0x64, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

@ -31,6 +31,7 @@ message DownloaderRequest {
string ip = 5; string ip = 5;
string port = 6; string port = 6;
uint32 size = 7; uint32 size = 7;
bool registerWithSig = 8; // Expect to have NEWBLOCK response of block along with current signature
} }
// DownloaderResponse is the generic response of DownloaderRequest. // DownloaderResponse is the generic response of DownloaderRequest.

@ -907,7 +907,7 @@ func (ss *StateSync) generateNewState(bc *core.BlockChain, worker *worker.Worker
if block == nil { if block == nil {
break break
} }
err = ss.UpdateBlockAndStatus(block, bc, worker, false) err = ss.UpdateBlockAndStatus(block, bc, worker, true)
if err != nil { if err != nil {
break break
} }

@ -66,6 +66,8 @@ const (
type syncConfig struct { type syncConfig struct {
timestamp int64 timestamp int64
client *downloader.Client client *downloader.Client
// Determine to send encoded BlockWithSig or Block
withSig bool
} }
// Node represents a protocol-participating node in the network // Node represents a protocol-participating node in the network

@ -357,6 +357,11 @@ func (node *Node) SendNewBlockToUnsync() {
utils.Logger().Warn().Msg("[SYNC] unable to encode block to hashes") utils.Logger().Warn().Msg("[SYNC] unable to encode block to hashes")
continue continue
} }
blockWithSigBytes, err := node.getEncodedBlockWithSigFromBlock(block)
if err != nil {
utils.Logger().Warn().Err(err).Msg("[SYNC] rlp encode BlockWithSig")
continue
}
node.stateMutex.Lock() node.stateMutex.Lock()
for peerID, config := range node.peerRegistrationRecord { for peerID, config := range node.peerRegistrationRecord {
@ -367,7 +372,11 @@ func (node *Node) SendNewBlockToUnsync() {
delete(node.peerRegistrationRecord, peerID) delete(node.peerRegistrationRecord, peerID)
continue continue
} }
response, err := config.client.PushNewBlock(node.GetSyncID(), blockBytes, false) sendBytes := blockBytes
if config.withSig {
sendBytes = blockWithSigBytes
}
response, err := config.client.PushNewBlock(node.GetSyncID(), sendBytes, false)
// close the connection if cannot push new block to unsync node // close the connection if cannot push new block to unsync node
if err != nil { if err != nil {
node.peerRegistrationRecord[peerID].client.Close() node.peerRegistrationRecord[peerID].client.Close()
@ -470,18 +479,21 @@ func (node *Node) CalculateResponse(request *downloader_pb.DownloaderRequest, in
response.Type = downloader_pb.DownloaderResponse_INSYNC response.Type = downloader_pb.DownloaderResponse_INSYNC
return response, nil return response, nil
} }
var blockObj types.Block var bws legacysync.BlockWithSig
err := rlp.DecodeBytes(request.BlockHash, &blockObj) err := rlp.DecodeBytes(request.BlockHash, &bws)
if err != nil { if err != nil {
utils.Logger().Warn().Msg("[SYNC] unable to decode received new block") utils.Logger().Warn().Msg("[SYNC] unable to decode received new block")
return response, err return response, err
} }
node.stateSync.AddNewBlock(request.PeerHash, &blockObj) blockObj := bws.Block
blockObj.SetCurrentCommitSig(bws.CommitSigAndBitmap)
node.stateSync.AddNewBlock(request.PeerHash, blockObj)
case downloader_pb.DownloaderRequest_REGISTER: case downloader_pb.DownloaderRequest_REGISTER:
peerID := string(request.PeerHash[:]) peerID := string(request.PeerHash[:])
ip := request.Ip ip := request.Ip
port := request.Port port := request.Port
withSig := request.RegisterWithSig
node.stateMutex.Lock() node.stateMutex.Lock()
defer node.stateMutex.Unlock() defer node.stateMutex.Unlock()
if _, ok := node.peerRegistrationRecord[peerID]; ok { if _, ok := node.peerRegistrationRecord[peerID]; ok {
@ -509,7 +521,7 @@ func (node *Node) CalculateResponse(request *downloader_pb.DownloaderRequest, in
Msg("[SYNC] unable to setup client for peerID") Msg("[SYNC] unable to setup client for peerID")
return response, nil return response, nil
} }
config := &syncConfig{timestamp: time.Now().UnixNano(), client: client} config := &syncConfig{timestamp: time.Now().UnixNano(), client: client, withSig: withSig}
node.peerRegistrationRecord[peerID] = config node.peerRegistrationRecord[peerID] = config
utils.Logger().Debug(). utils.Logger().Debug().
Str("ip", ip). Str("ip", ip).
@ -603,6 +615,14 @@ func (node *Node) getEncodedBlockWithSigByHash(hash common.Hash) ([]byte, error)
return b, nil return b, nil
} }
func (node *Node) getEncodedBlockWithSigFromBlock(block *types.Block) ([]byte, error) {
bwh := legacysync.BlockWithSig{
Block: block,
CommitSigAndBitmap: block.GetCurrentCommitSig(),
}
return rlp.EncodeToBytes(bwh)
}
func (node *Node) getCommitSigAndBitmap(block *types.Block) ([]byte, error) { func (node *Node) getCommitSigAndBitmap(block *types.Block) ([]byte, error) {
child := node.Blockchain().GetBlockByNumber(block.NumberU64() + 1) child := node.Blockchain().GetBlockByNumber(block.NumberU64() + 1)
if child != nil { if child != nil {

Loading…
Cancel
Save