Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement gRPC bidirectional communication between heimdall and bor #1203

Merged
merged 27 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions bor/client/grpc/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package grpc

import (
"strings"
"time"

"github.com/ethereum/go-ethereum/log"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"

proto "github.com/maticnetwork/polyproto/bor"

"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
)

type BorGRPCClient struct {
conn *grpc.ClientConn
client proto.BorApiClient
}

func NewBorGRPCClient(address string) *BorGRPCClient {
address = removePrefix(address)

opts := []grpc_retry.CallOption{
grpc_retry.WithMax(5),
grpc_retry.WithBackoff(grpc_retry.BackoffLinear(1 * time.Second)),
grpc_retry.WithCodes(codes.Internal, codes.Unavailable, codes.Aborted, codes.NotFound),
}

conn, err := grpc.NewClient(address,
grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor(opts...)),
grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor(opts...)),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Crit("Failed to connect to Bor gRPC", "error", err)
}

log.Info("Connected to Bor gRPC server", "address", address)

return &BorGRPCClient{
conn: conn,
client: proto.NewBorApiClient(conn),
}
}

func (h *BorGRPCClient) Close() {
log.Debug("Shutdown detected, Closing Bor gRPC client")
h.conn.Close()
}

// removePrefix removes the http:// or https:// prefix from the address, if present.
func removePrefix(address string) string {
if strings.HasPrefix(address, "http://") || strings.HasPrefix(address, "https://") {
return address[strings.Index(address, "//")+2:]
}
return address
}
155 changes: 155 additions & 0 deletions bor/client/grpc/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package grpc

import (
"context"
"math/big"

"github.com/ethereum/go-ethereum/common"
ethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"

proto "github.com/maticnetwork/polyproto/bor"
protoutil "github.com/maticnetwork/polyproto/utils"
)

func (h *BorGRPCClient) GetRootHash(ctx context.Context, startBlock uint64, endBlock uint64) (string, error) {

req := &proto.GetRootHashRequest{
StartBlockNumber: startBlock,
EndBlockNumber: endBlock,
}

log.Info("Fetching bor root hash")

res, err := h.client.GetRootHash(ctx, req)
if err != nil {
return "", err
}

log.Info("Fetched bor root hash")

return res.RootHash, nil
}

func (h *BorGRPCClient) GetVoteOnHash(ctx context.Context, startBlock uint64, endBlock uint64, rootHash string, milestoneId string) (bool, error) {

req := &proto.GetVoteOnHashRequest{
StartBlockNumber: startBlock,
EndBlockNumber: endBlock,
Hash: rootHash,
MilestoneId: milestoneId,
}

log.Info("Fetching vote on hash")

res, err := h.client.GetVoteOnHash(ctx, req)
if err != nil {
return false, err
}

log.Info("Fetched vote on hash")

return res.Response, nil
}

func (h *BorGRPCClient) HeaderByNumber(ctx context.Context, blockID uint64) (*ethTypes.Header, error) {

req := &proto.GetHeaderByNumberRequest{
Number: blockID,
}

log.Info("Fetching header by number")

res, err := h.client.HeaderByNumber(ctx, req)
if err != nil {
return &ethTypes.Header{}, err
}

log.Info("Fetched header by number")

resp := &ethTypes.Header{
Number: big.NewInt(int64(res.Header.Number)),
ParentHash: protoutil.ConvertH256ToHash(res.Header.ParentHash),
Time: res.Header.Time,
}

return resp, nil
}

func (h *BorGRPCClient) BlockByNumber(ctx context.Context, blockID uint64) (*ethTypes.Block, error) {

req := &proto.GetBlockByNumberRequest{
Number: blockID,
}

log.Info("Fetching block by number")

res, err := h.client.BlockByNumber(ctx, req)
if err != nil {
return &ethTypes.Block{}, err
}

log.Info("Fetched block by number")

header := ethTypes.Header{
Number: big.NewInt(int64(res.Block.Header.Number)),
ParentHash: protoutil.ConvertH256ToHash(res.Block.Header.ParentHash),
Time: res.Block.Header.Time,
}
return ethTypes.NewBlock(&header, nil, nil, nil, nil), nil
}

func (h *BorGRPCClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (*ethTypes.Receipt, error) {

req := &proto.ReceiptRequest{
Hash: protoutil.ConvertHashToH256(txHash),
}

log.Info("Fetching transaction receipt")

res, err := h.client.TransactionReceipt(ctx, req)
if err != nil {
return &ethTypes.Receipt{}, err
}

log.Info("Fetched transaction receipt")

return receiptResponseToTypesReceipt(res.Receipt), nil
}

func (h *BorGRPCClient) BorBlockReceipt(ctx context.Context, txHash common.Hash) (*ethTypes.Receipt, error) {

req := &proto.ReceiptRequest{
Hash: protoutil.ConvertHashToH256(txHash),
}

log.Info("Fetching bor block receipt")

res, err := h.client.BorBlockReceipt(ctx, req)
if err != nil {
return &ethTypes.Receipt{}, err
}

log.Info("Fetched bor block receipt")

return receiptResponseToTypesReceipt(res.Receipt), nil
}

func receiptResponseToTypesReceipt(receipt *proto.Receipt) *ethTypes.Receipt {
// Bloom and Logs have been intentionally left out as they are not used in the current implementation
return &ethTypes.Receipt{
Type: uint8(receipt.Type),
PostState: receipt.PostState,
Status: receipt.Status,
CumulativeGasUsed: receipt.CumulativeGasUsed,
TxHash: protoutil.ConvertH256ToHash(receipt.TxHash),
ContractAddress: protoutil.ConvertH160toAddress(receipt.ContractAddress),
GasUsed: receipt.GasUsed,
EffectiveGasPrice: big.NewInt(receipt.EffectiveGasPrice),
BlobGasUsed: receipt.BlobGasUsed,
BlobGasPrice: big.NewInt(receipt.BlobGasPrice),
BlockHash: protoutil.ConvertH256ToHash(receipt.BlockHash),
BlockNumber: big.NewInt(receipt.BlockNumber),
TransactionIndex: uint(receipt.TransactionIndex),
}
}
2 changes: 1 addition & 1 deletion bridge/setu/broadcaster/broadcaster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ var (
}
)

// Parallel test - to check BroadcastToHeimdall synchronisation
//nolint:tparallel
func TestBroadcastToHeimdall(t *testing.T) {
t.Parallel()

Expand Down
6 changes: 3 additions & 3 deletions bridge/setu/processor/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (mp *MilestoneProcessor) checkAndPropose(milestoneLength uint64) (err error
}

if result == nil {
return fmt.Errorf("Got nil result while fetching milestone count")
return errors.New("got nil result while fetching milestone count")
}

var start = helper.GetMilestoneBorBlockHeight()
Expand All @@ -118,7 +118,7 @@ func (mp *MilestoneProcessor) checkAndPropose(milestoneLength uint64) (err error
}

if latestMilestone == nil {
return errors.New("Got nil result while fetching latest milestone")
return errors.New("got nil result while fetching latest milestone")
}

//start block number should be continuous to the end block of lasted stored milestone
Expand Down Expand Up @@ -160,7 +160,7 @@ func (mp *MilestoneProcessor) createAndSendMilestoneToHeimdall(milestoneContext
//fetch the endBlock+1 number instead of endBlock so that we can directly get the hash of endBlock using parent hash
block, err = mp.contractConnector.GetMaticChainBlock(big.NewInt(int64(endNum + 1)))
if err != nil {
return fmt.Errorf("Error while fetching %d block %w", endNum+1, err)
return fmt.Errorf("error while fetching block %d: %w", endNum+1, err)
}

endHash := block.ParentHash
Expand Down
6 changes: 2 additions & 4 deletions cmd/heimdalld/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
ethCommon "github.com/ethereum/go-ethereum/common"
jsoniter "github.com/json-iterator/go"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -49,9 +50,6 @@ import (
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"

ethCommon "github.com/ethereum/go-ethereum/common"

"github.com/maticnetwork/heimdall/app"
authTypes "github.com/maticnetwork/heimdall/auth/types"
Expand Down Expand Up @@ -365,7 +363,7 @@ func startOpenTracing(cmd *cobra.Command) (*sdktrace.TracerProvider, *context.Co
ctx,
otlptracegrpc.WithInsecure(),
otlptracegrpc.WithEndpoint(openCollectorEndpoint),
otlptracegrpc.WithDialOption(grpc.WithBlock()),
otlptracegrpc.WithDialOption(),
)
traceExporterReady <- traceExporter
}()
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ require (
github.com/golang/mock v1.6.0
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/hashicorp/golang-lru v1.0.2
github.com/json-iterator/go v1.1.12
github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53
github.com/maticnetwork/polyproto v0.0.3
github.com/pborman/uuid v1.2.1
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.19.0
Expand Down
4 changes: 3 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1995,6 +1995,7 @@ github.com/gorilla/websocket v1.5.2 h1:qoW6V1GT3aZxybsbC6oLnailWnB+qTMVwMreOso9X
github.com/gorilla/websocket v1.5.2/go.mod h1:0n9H61RBAcf5/38py2MCYbxzPIY9rOkpvvMT24Rqs30=
github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
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.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
Expand Down Expand Up @@ -2223,8 +2224,9 @@ github.com/maticnetwork/cosmos-sdk v0.38.4/go.mod h1:NbuVdUoqlRF6RrFJp27hpbqSoRB
github.com/maticnetwork/crand v1.0.2 h1:Af0tAivC8zrxXDpGWNWVT/0s1fOz8w0eRbahZgURS8I=
github.com/maticnetwork/crand v1.0.2/go.mod h1:/NRNL3bj2eYdqpWmoIP5puxndTpi0XRxpj5ZKxfHjyg=
github.com/maticnetwork/heimdall v1.0.7/go.mod h1:+ANI5+VV28ahwfdl7oMzrcNwaTEs1Fn6z39BqBGcvaA=
github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53 h1:PjYV+lghs106JKkrYgOnrsfDLoTc11BxZd4rUa4Rus4=
github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
github.com/maticnetwork/polyproto v0.0.3 h1:a69rIp97fcl3ABY4LlVX9B2t1qhLa0Jhny3HNOzReBU=
github.com/maticnetwork/polyproto v0.0.3/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
github.com/maticnetwork/tendermint v0.33.2 h1:R9M7jgAmON8K/LbzMvtWPDhtPkNcqzkUUHp1ict/h3s=
github.com/maticnetwork/tendermint v0.33.2/go.mod h1:D2fcnxGk6bje+LoPwImuKSSYLiK7/G06IynGNDSEcJk=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
Expand Down
Loading
Loading