From d4ae4fb1a6f758ff08e2db538872d9959abf4c51 Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Wed, 24 Mar 2021 13:54:29 -0700 Subject: [PATCH] [sync] added commit sig verification logic to legacy sync --- api/service/legacysync/downloader/client.go | 17 +++++ .../downloader/proto/downloader.pb.go | 46 ++++++------ .../downloader/proto/downloader.proto | 1 + api/service/legacysync/syncing.go | 49 ++++++++++--- internal/chain/engine.go | 3 + node/node_syncing.go | 70 +++++++++++++++++-- 6 files changed, 151 insertions(+), 35 deletions(-) diff --git a/api/service/legacysync/downloader/client.go b/api/service/legacysync/downloader/client.go index 4b331d428..0c7756ba4 100644 --- a/api/service/legacysync/downloader/client.go +++ b/api/service/legacysync/downloader/client.go @@ -91,6 +91,23 @@ func (client *Client) GetBlocks(hashes [][]byte) *pb.DownloaderResponse { return response } +// GetBlocksAndSigs get blockWithSig in serialization byte array by calling a grpc request +func (client *Client) GetBlocksAndSigs(hashes [][]byte) *pb.DownloaderResponse { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + request := &pb.DownloaderRequest{Type: pb.DownloaderRequest_BLOCKWITHSIG} + request.Hashes = make([][]byte, len(hashes)) + for i := range hashes { + request.Hashes[i] = make([]byte, len(hashes[i])) + copy(request.Hashes[i], hashes[i]) + } + response, err := client.dlClient.Query(ctx, request) + if err != nil { + utils.Logger().Error().Err(err).Str("target", client.conn.Target()).Msg("[SYNC] downloader/client.go:GetBlocksAndSigs query failed") + } + return response +} + // Register will register node's ip/port information to peers receive newly created blocks in future // hash is the bytes of "ip:port" string representation func (client *Client) Register(hash []byte, ip, port string) *pb.DownloaderResponse { diff --git a/api/service/legacysync/downloader/proto/downloader.pb.go b/api/service/legacysync/downloader/proto/downloader.pb.go index 1f3e67d7f..fd947f6dd 100644 --- a/api/service/legacysync/downloader/proto/downloader.pb.go +++ b/api/service/legacysync/downloader/proto/downloader.pb.go @@ -40,6 +40,7 @@ const ( DownloaderRequest_REGISTERTIMEOUT DownloaderRequest_RequestType = 5 DownloaderRequest_UNKNOWN DownloaderRequest_RequestType = 6 DownloaderRequest_BLOCKHEADER DownloaderRequest_RequestType = 7 + DownloaderRequest_BLOCKWITHSIG DownloaderRequest_RequestType = 8 ) // Enum value maps for DownloaderRequest_RequestType. @@ -53,6 +54,7 @@ var ( 5: "REGISTERTIMEOUT", 6: "UNKNOWN", 7: "BLOCKHEADER", + 8: "BLOCKWITHSIG", } DownloaderRequest_RequestType_value = map[string]int32{ "BLOCKHASH": 0, @@ -63,6 +65,7 @@ var ( "REGISTERTIMEOUT": 5, "UNKNOWN": 6, "BLOCKHEADER": 7, + "BLOCKWITHSIG": 8, } ) @@ -310,7 +313,7 @@ var File_downloader_proto protoreflect.FileDescriptor var file_downloader_proto_rawDesc = []byte{ 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, 0xe6, + 0x74, 0x6f, 0x12, 0x0a, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x22, 0xf8, 0x02, 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, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, @@ -324,7 +327,7 @@ var file_downloader_proto_rawDesc = []byte{ 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, 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, 0x87, 0x01, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x99, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x45, 0x57, 0x42, 0x4c, @@ -333,26 +336,27 @@ var file_downloader_proto_rawDesc = []byte{ 0x45, 0x52, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 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, 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, + 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, 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, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/service/legacysync/downloader/proto/downloader.proto b/api/service/legacysync/downloader/proto/downloader.proto index 9c2aa46eb..bafed0ff9 100644 --- a/api/service/legacysync/downloader/proto/downloader.proto +++ b/api/service/legacysync/downloader/proto/downloader.proto @@ -18,6 +18,7 @@ message DownloaderRequest { REGISTERTIMEOUT = 5; UNKNOWN = 6; BLOCKHEADER = 7; + BLOCKWITHSIG = 8; } // Request type. diff --git a/api/service/legacysync/syncing.go b/api/service/legacysync/syncing.go index 7c1892c7b..a16ef918a 100644 --- a/api/service/legacysync/syncing.go +++ b/api/service/legacysync/syncing.go @@ -11,6 +11,8 @@ import ( "sync" "time" + "github.com/harmony-one/harmony/internal/chain" + "github.com/Workiva/go-datastructures/queue" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" @@ -280,9 +282,16 @@ func CompareSyncPeerConfigByblockHashes(a *SyncPeerConfig, b *SyncPeerConfig) in return 0 } +// BlockWithSig the serialization structure for request DownloaderRequest_BLOCKWITHSIG +// The block is encoded as block + commit signature +type BlockWithSig struct { + Block *types.Block + CommitSigAndBitmap []byte +} + // GetBlocks gets blocks by calling grpc request to the corresponding peer. func (peerConfig *SyncPeerConfig) GetBlocks(hashes [][]byte) ([][]byte, error) { - response := peerConfig.client.GetBlocks(hashes) + response := peerConfig.client.GetBlocksAndSigs(hashes) if response == nil { return nil, ErrGetBlock } @@ -620,8 +629,8 @@ func (ss *StateSync) handleBlockSyncResult(payload [][]byte, tasks syncBlockTask } for i, blockBytes := range payload { - var blockObj types.Block - if err := rlp.DecodeBytes(blockBytes, &blockObj); err != nil { + var bws BlockWithSig + if err := rlp.DecodeBytes(blockBytes, &bws); err != nil { utils.Logger().Warn(). Err(err). Int("taskIndex", tasks[i].index). @@ -630,6 +639,8 @@ func (ss *StateSync) handleBlockSyncResult(payload [][]byte, tasks syncBlockTask failedTasks = append(failedTasks, tasks[i]) continue } + blockObj := bws.Block + blockObj.SetCurrentCommitSig(bws.CommitSigAndBitmap) gotHash := blockObj.Hash() if !bytes.Equal(gotHash[:], tasks[i].blockHash) { utils.Logger().Warn(). @@ -640,7 +651,7 @@ func (ss *StateSync) handleBlockSyncResult(payload [][]byte, tasks syncBlockTask continue } ss.syncMux.Lock() - ss.commonBlocks[tasks[i].index] = &blockObj + ss.commonBlocks[tasks[i].index] = blockObj ss.syncMux.Unlock() } return failedTasks @@ -771,6 +782,15 @@ func (ss *StateSync) UpdateBlockAndStatus(block *types.Block, bc *core.BlockChai if verifyAllSig { verifySig = true } + if verifySig { + sig, bitmap, err := chain.ParseCommitSigAndBitmap(block.GetCurrentCommitSig()) + if err != nil { + return errors.Wrap(err, "parse commitSigAndBitmap") + } + if err := bc.Engine().VerifyHeaderSignature(bc, block.Header(), sig, bitmap); err != nil { + return errors.Wrapf(err, "verify header signature %v", block.Hash().String()) + } + } err := bc.Engine().VerifyHeader(bc, block.Header(), verifySig) if err == engine.ErrUnknownAncestor { return err @@ -807,6 +827,12 @@ func (ss *StateSync) UpdateBlockAndStatus(block *types.Block, bc *core.BlockChai Str("blockHex", block.Hash().Hex()). Uint32("ShardID", block.ShardID()). Msg("[SYNC] UpdateBlockAndStatus: New Block Added to Blockchain") + + if verifyAllSig { + if err := bc.WriteCommitSig(block.NumberU64(), block.GetCurrentCommitSig()); err != nil { + return err + } + } for i, tx := range block.StakingTransactions() { utils.Logger().Info(). Msgf( @@ -822,16 +848,19 @@ func (ss *StateSync) generateNewState(bc *core.BlockChain, worker *worker.Worker parentHash := bc.CurrentBlock().Hash() var err error - for { - block := ss.getBlockFromOldBlocksByParentHash(parentHash) + for block := ss.getBlockFromOldBlocksByParentHash(parentHash); ; { if block == nil { break } - err = ss.UpdateBlockAndStatus(block, bc, worker, false) + next := ss.getBlockFromOldBlocksByParentHash(block.Hash()) + // Enforce sig check for the last block in a batch + enforceSigCheck := next == nil + + err = ss.UpdateBlockAndStatus(block, bc, worker, enforceSigCheck) if err != nil { break } - parentHash = block.Hash() + block = next } ss.syncMux.Lock() ss.commonBlocks = make(map[int]*types.Block) @@ -844,7 +873,7 @@ func (ss *StateSync) generateNewState(bc *core.BlockChain, worker *worker.Worker if block == nil { break } - err = ss.UpdateBlockAndStatus(block, bc, worker, false) + err = ss.UpdateBlockAndStatus(block, bc, worker, true) if err != nil { break } @@ -865,7 +894,7 @@ func (ss *StateSync) generateNewState(bc *core.BlockChain, worker *worker.Worker if block == nil { break } - err = ss.UpdateBlockAndStatus(block, bc, worker, false) + err = ss.UpdateBlockAndStatus(block, bc, worker, true) if err != nil { break } diff --git a/internal/chain/engine.go b/internal/chain/engine.go index de1b021f1..139de7e8c 100644 --- a/internal/chain/engine.go +++ b/internal/chain/engine.go @@ -395,6 +395,9 @@ func applySlashes( // i.e. this header verification api is more flexible since the caller specifies which commit signature and bitmap to use // for verifying the block header, which is necessary for cross-shard block header verification. Example of such is cross-shard transaction. func (e *engineImpl) VerifyHeaderSignature(chain engine.ChainReader, header *block.Header, commitSig bls_cosi.SerializedSignature, commitBitmap []byte) error { + if chain.CurrentHeader().Number().Uint64() <= uint64(1) { + return nil + } return e.verifyHeaderSignatureCached(chain, header, commitSig, commitBitmap) } diff --git a/node/node_syncing.go b/node/node_syncing.go index 47d916dcf..89afcbe66 100644 --- a/node/node_syncing.go +++ b/node/node_syncing.go @@ -449,6 +449,18 @@ func (node *Node) CalculateResponse(request *downloader_pb.DownloaderRequest, in } } + case downloader_pb.DownloaderRequest_BLOCKWITHSIG: + var hash common.Hash + for _, bytes := range request.Hashes { + hash.SetBytes(bytes) + encoded, err := node.getEncodedBlockWithSigByHash(hash) + if err != nil { + utils.Logger().Info().Err(err).Str("hash", hash.String()).Msg("failed to get block with sig") + continue + } + response.Payload = append(response.Payload, encoded) + } + case downloader_pb.DownloaderRequest_BLOCKHEIGHT: response.BlockHeight = node.Blockchain().CurrentBlock().NumberU64() @@ -513,19 +525,23 @@ func (node *Node) CalculateResponse(request *downloader_pb.DownloaderRequest, in Int("number", count). Msg("[SYNC] extra node registered") } + } + return response, nil } const ( - headerCacheSize = 10000 - blockCacheSize = 10000 + headerCacheSize = 10000 + blockCacheSize = 10000 + blockWithSigCacheSize = 10000 ) var ( // Cached fields for block header and block requests - headerReqCache, _ = lru.New(headerCacheSize) - blockReqCache, _ = lru.New(blockCacheSize) + headerReqCache, _ = lru.New(headerCacheSize) + blockReqCache, _ = lru.New(blockCacheSize) + blockWithSigReqCache, _ = lru.New(blockWithSigCacheSize) errHeaderNotExist = errors.New("header not exist") errBlockNotExist = errors.New("block not exist") @@ -563,6 +579,52 @@ func (node *Node) getEncodedBlockByHash(hash common.Hash) ([]byte, error) { return b, nil } +func (node *Node) getEncodedBlockWithSigByHash(hash common.Hash) ([]byte, error) { + if b, ok := blockWithSigReqCache.Get(hash); ok { + return b.([]byte), nil + } + blk := node.Blockchain().GetBlockByHash(hash) + if blk == nil { + return nil, errBlockNotExist + } + sab, err := node.getCommitSigAndBitmap(blk) + if err != nil { + return nil, err + } + bwh := legacysync.BlockWithSig{ + Block: blk, + CommitSigAndBitmap: sab, + } + b, err := rlp.EncodeToBytes(bwh) + if err != nil { + return nil, err + } + blockWithSigReqCache.Add(hash, b) + return b, nil +} + +func (node *Node) getCommitSigAndBitmap(block *types.Block) ([]byte, error) { + child := node.Blockchain().GetBlockByNumber(block.NumberU64() + 1) + if child == nil { + return node.getCommitSigFromChild(block, child) + } + return node.getCommitSigFromDB(block) +} + +func (node *Node) getCommitSigFromChild(parent, child *types.Block) ([]byte, error) { + if child.ParentHash() != parent.Hash() { + return nil, fmt.Errorf("child's parent hash unexpected: %v / %v", + child.ParentHash().String(), parent.Hash().String()) + } + sig := child.Header().LastCommitSignature() + bitmap := child.Header().LastCommitBitmap() + return append(sig[:], bitmap...), nil +} + +func (node *Node) getCommitSigFromDB(block *types.Block) ([]byte, error) { + return node.Blockchain().ReadCommitSig(block.NumberU64()) +} + // SyncStatus return the syncing status, including whether node is syncing // and the target block number. func (node *Node) SyncStatus(shardID uint32) (bool, uint64) {