diff --git a/consensus/bor/api.go b/consensus/bor/api.go
index 672d378215aea51b5d6a3d9f0b2b7bbdb55cadec..5af1ddbc39c2b6acd3c0531b71c3ba05d6e70d75 100644
--- a/consensus/bor/api.go
+++ b/consensus/bor/api.go
@@ -17,6 +17,7 @@
 package bor
 
 import (
+	"encoding/hex"
 	"math"
 	"math/big"
 	"strconv"
@@ -122,21 +123,21 @@ func (api *API) GetCurrentValidators() ([]*Validator, error) {
 }
 
 // GetRootHash returns the merkle root of the start to end block headers
-func (api *API) GetRootHash(start int64, end int64) ([]byte, error) {
+func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
 	if err := api.initializeRootHashCache(); err != nil {
-		return nil, err
+		return "", err
 	}
 	key := getRootHashKey(start, end)
 	if root, known := api.rootHashCache.Get(key); known {
-		return root.([]byte), nil
+		return root.(string), nil
 	}
 	length := uint64(end - start + 1)
 	if length > MaxCheckpointLength {
-		return nil, &MaxCheckpointLengthExceededError{start, end}
+		return "", &MaxCheckpointLengthExceededError{start, end}
 	}
-	currentHeaderNumber := api.chain.CurrentHeader().Number.Int64()
+	currentHeaderNumber := api.chain.CurrentHeader().Number.Uint64()
 	if start > end || end > currentHeaderNumber {
-		return nil, &InvalidStartEndBlockError{start, end, currentHeaderNumber}
+		return "", &InvalidStartEndBlockError{start, end, currentHeaderNumber}
 	}
 	blockHeaders := make([]*types.Header, end-start+1)
 	wg := new(sync.WaitGroup)
@@ -144,7 +145,7 @@ func (api *API) GetRootHash(start int64, end int64) ([]byte, error) {
 	for i := start; i <= end; i++ {
 		wg.Add(1)
 		concurrent <- true
-		go func(number int64) {
+		go func(number uint64) {
 			blockHeaders[number-start] = api.chain.GetHeaderByNumber(uint64(number))
 			<-concurrent
 			wg.Done()
@@ -170,9 +171,9 @@ func (api *API) GetRootHash(start int64, end int64) ([]byte, error) {
 
 	tree := merkle.NewTreeWithOpts(merkle.TreeOptions{EnableHashSorting: false, DisableHashLeaves: true})
 	if err := tree.Generate(convert(headers), sha3.NewLegacyKeccak256()); err != nil {
-		return nil, err
+		return "", err
 	}
-	root := tree.Root().Hash
+	root := hex.EncodeToString(tree.Root().Hash)
 	api.rootHashCache.Add(key, root)
 	return root, nil
 }
@@ -185,6 +186,6 @@ func (api *API) initializeRootHashCache() error {
 	return err
 }
 
-func getRootHashKey(start int64, end int64) string {
-	return strconv.FormatInt(start, 10) + "-" + strconv.FormatInt(end, 10)
+func getRootHashKey(start uint64, end uint64) string {
+	return strconv.FormatUint(start, 10) + "-" + strconv.FormatUint(end, 10)
 }
diff --git a/consensus/bor/errors.go b/consensus/bor/errors.go
index ae7da982a7651cc19e6826186e46c6e78e14ea78..f9f99e2b6490c265a1296f811aa532fb6e6de165 100644
--- a/consensus/bor/errors.go
+++ b/consensus/bor/errors.go
@@ -42,9 +42,9 @@ func (e *TotalVotingPowerExceededError) Error() string {
 }
 
 type InvalidStartEndBlockError struct {
-	Start         int64
-	End           int64
-	CurrentHeader int64
+	Start         uint64
+	End           uint64
+	CurrentHeader uint64
 }
 
 func (e *InvalidStartEndBlockError) Error() string {
@@ -56,8 +56,8 @@ func (e *InvalidStartEndBlockError) Error() string {
 }
 
 type MaxCheckpointLengthExceededError struct {
-	Start int64
-	End   int64
+	Start uint64
+	End   uint64
 }
 
 func (e *MaxCheckpointLengthExceededError) Error() string {
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 7958f86b37c261d9a6d47eb85762d0473bf28d21..0be0376cf556b9b9916aa8da2a7dca9699c01b01 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -249,16 +249,16 @@ func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.Ma
 	}
 }
 
-func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr rpc.BlockNumber, endBlockNr rpc.BlockNumber) ([]byte, error) {
+func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
 	var api *bor.API
 	for _, _api := range b.eth.Engine().APIs(b.eth.BlockChain()) {
 		if _api.Namespace == "bor" {
 			api = _api.Service.(*bor.API)
 		}
 	}
-	root, err := api.GetRootHash(starBlockNr.Int64(), endBlockNr.Int64())
+	root, err := api.GetRootHash(starBlockNr, endBlockNr)
 	if err != nil {
-		return nil, err
+		return "", err
 	}
 	return root, nil
 }
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
index 5d349a289b86f8875b4e59d4b38cdf22778a2f6f..7d44b0da034b1c5373fc2259308c637563c7e806 100644
--- a/ethclient/ethclient.go
+++ b/ethclient/ethclient.go
@@ -522,6 +522,15 @@ func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) er
 	return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", common.ToHex(data))
 }
 
+// GetRootHash returns the merkle root of the block headers
+func (ec *Client) GetRootHash(ctx context.Context, startBlockNumber uint64, endBlockNumber uint64) (string, error) {
+	var rootHash string
+	if err := ec.c.CallContext(ctx, &rootHash, "eth_getRootHash", startBlockNumber, endBlockNumber); err != nil {
+		return "", err
+	}
+	return rootHash, nil
+}
+
 func toCallArg(msg ethereum.CallMsg) interface{} {
 	arg := map[string]interface{}{
 		"from": msg.From,
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 0ad624e7ed3dbf88787e096451291689b7a4ddac..cee5a575fb45cd30e27f4f2d9b4ed15c454e4875 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -716,10 +716,10 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
 	return res[:], state.Error()
 }
 
-func (s *PublicBlockChainAPI) GetRootHash(ctx context.Context, starBlockNr rpc.BlockNumber, endBlockNr rpc.BlockNumber) ([]byte, error) {
+func (s *PublicBlockChainAPI) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
 	root, err := s.b.GetRootHash(ctx, starBlockNr, endBlockNr)
 	if err != nil {
-		return nil, err
+		return "", err
 	}
 	return root, nil
 }
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index 21cef13f441506bdc7c7d38e356d9da287b03620..595a69b0cc2ebd6579b298e4aa01c15a6b76bec5 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -62,7 +62,7 @@ type Backend interface {
 	SubscribeStateEvent(ch chan<- core.NewStateChangeEvent) event.Subscription
 	SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
 	SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription
-	GetRootHash(ctx context.Context, starBlockNr rpc.BlockNumber, endBlockNr rpc.BlockNumber) ([]byte, error)
+	GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error)
 
 	// Transaction pool API
 	SendTx(ctx context.Context, signedTx *types.Transaction) error
diff --git a/les/api_backend.go b/les/api_backend.go
index 4739abcdebf951e96caefd8e46766dd391bbcbe2..3b228e7374625e5a23c82ebb706372969ee8439c 100644
--- a/les/api_backend.go
+++ b/les/api_backend.go
@@ -224,6 +224,6 @@ func (b *LesApiBackend) ServiceFilter(ctx context.Context, session *bloombits.Ma
 	}
 }
 
-func (b *LesApiBackend) GetRootHash(ctx context.Context, starBlockNr rpc.BlockNumber, endBlockNr rpc.BlockNumber) ([]byte, error) {
-	return nil, errors.New("Not implemented")
+func (b *LesApiBackend) GetRootHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64) (string, error) {
+	return "", errors.New("Not implemented")
 }