Merge pull request #1373 from maticnetwork/bor-grpc

Implement gRPC bidirectional communication between bor and heimdall
This commit is contained in:
Marcello Ardizzone 2024-11-13 07:56:28 +01:00 committed by GitHub
commit 59b085a54c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 193 additions and 15 deletions

View file

@ -39,7 +39,7 @@ func (b *EthAPIBackend) GetRootHash(ctx context.Context, starBlockNr uint64, end
return root, nil return root, nil
} }
// GetRootHash returns root hash for given start and end block // GetVoteOnHash returns the vote on hash
func (b *EthAPIBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) { func (b *EthAPIBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBlockNr uint64, hash string, milestoneId string) (bool, error) {
var api *bor.API var api *bor.API

View file

@ -132,7 +132,7 @@ func (mr *MockBackendMockRecorder) GetBorBlockLogs(arg0, arg1 interface{}) *gomo
// GetBorBlockReceipt mocks base method. // GetBorBlockReceipt mocks base method.
func (m *MockBackend) GetBorBlockReceipt(arg0 context.Context, arg1 common.Hash) (*types.Receipt, error) { func (m *MockBackend) GetBorBlockReceipt(arg0 context.Context, arg1 common.Hash) (*types.Receipt, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetBorBlockReceipt", arg0, arg1) ret := m.ctrl.Call(m, "BorBlockReceipt", arg0, arg1)
ret0, _ := ret[0].(*types.Receipt) ret0, _ := ret[0].(*types.Receipt)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
@ -141,7 +141,7 @@ func (m *MockBackend) GetBorBlockReceipt(arg0 context.Context, arg1 common.Hash)
// GetBorBlockReceipt indicates an expected call of GetBorBlockReceipt. // GetBorBlockReceipt indicates an expected call of GetBorBlockReceipt.
func (mr *MockBackendMockRecorder) GetBorBlockReceipt(arg0, arg1 interface{}) *gomock.Call { func (mr *MockBackendMockRecorder) GetBorBlockReceipt(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockReceipt", reflect.TypeOf((*MockBackend)(nil).GetBorBlockReceipt), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BorBlockReceipt", reflect.TypeOf((*MockBackend)(nil).GetBorBlockReceipt), arg0, arg1)
} }
// GetLogs mocks base method. // GetLogs mocks base method.

2
go.mod
View file

@ -65,7 +65,7 @@ require (
github.com/kylelemons/godebug v1.1.0 github.com/kylelemons/godebug v1.1.0
github.com/maticnetwork/crand v1.0.2 github.com/maticnetwork/crand v1.0.2
github.com/maticnetwork/heimdall v1.0.7 github.com/maticnetwork/heimdall v1.0.7
github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53 github.com/maticnetwork/polyproto v0.0.3
github.com/mattn/go-colorable v0.1.13 github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-isatty v0.0.20
github.com/mitchellh/cli v1.1.5 github.com/mitchellh/cli v1.1.5

3
go.sum
View file

@ -1706,8 +1706,9 @@ github.com/maticnetwork/crand v1.0.2/go.mod h1:/NRNL3bj2eYdqpWmoIP5puxndTpi0XRxp
github.com/maticnetwork/heimdall v1.0.4/go.mod h1:Xh7KFvtbs/SVNjOI8IgYmk6JdzYx89eU/XUwH0AgHLs= github.com/maticnetwork/heimdall v1.0.4/go.mod h1:Xh7KFvtbs/SVNjOI8IgYmk6JdzYx89eU/XUwH0AgHLs=
github.com/maticnetwork/heimdall v1.0.7 h1:QStn+hbZKxfE+PqecaorA/uATDPuQoi+U9Z7IIonb60= github.com/maticnetwork/heimdall v1.0.7 h1:QStn+hbZKxfE+PqecaorA/uATDPuQoi+U9Z7IIonb60=
github.com/maticnetwork/heimdall v1.0.7/go.mod h1:+ANI5+VV28ahwfdl7oMzrcNwaTEs1Fn6z39BqBGcvaA= 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-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.0 h1:f+vORM02BoUOlCvnu3Zjw5rv6l6JSNVchWjH03rUuR8= github.com/maticnetwork/tendermint v0.33.0 h1:f+vORM02BoUOlCvnu3Zjw5rv6l6JSNVchWjH03rUuR8=
github.com/maticnetwork/tendermint v0.33.0/go.mod h1:D2fcnxGk6bje+LoPwImuKSSYLiK7/G06IynGNDSEcJk= github.com/maticnetwork/tendermint v0.33.0/go.mod h1:D2fcnxGk6bje+LoPwImuKSSYLiK7/G06IynGNDSEcJk=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=

View file

@ -0,0 +1,93 @@
package server
import (
"context"
"errors"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
protobor "github.com/maticnetwork/polyproto/bor"
protoutil "github.com/maticnetwork/polyproto/utils"
)
func (s *Server) GetRootHash(ctx context.Context, req *protobor.GetRootHashRequest) (*protobor.GetRootHashResponse, error) {
rootHash, err := s.backend.APIBackend.GetRootHash(ctx, req.StartBlockNumber, req.EndBlockNumber)
if err != nil {
return nil, err
}
return &protobor.GetRootHashResponse{RootHash: rootHash}, nil
}
func (s *Server) GetVoteOnHash(ctx context.Context, req *protobor.GetVoteOnHashRequest) (*protobor.GetVoteOnHashResponse, error) {
vote, err := s.backend.APIBackend.GetVoteOnHash(ctx, req.StartBlockNumber, req.EndBlockNumber, req.Hash, req.MilestoneId)
if err != nil {
return nil, err
}
return &protobor.GetVoteOnHashResponse{Response: vote}, nil
}
func headerToProtoborHeader(h *types.Header) *protobor.Header {
return &protobor.Header{
Number: h.Number.Uint64(),
ParentHash: protoutil.ConvertHashToH256(h.ParentHash),
Time: h.Time,
}
}
func (s *Server) HeaderByNumber(ctx context.Context, req *protobor.GetHeaderByNumberRequest) (*protobor.GetHeaderByNumberResponse, error) {
header, err := s.backend.APIBackend.HeaderByNumber(ctx, rpc.BlockNumber(req.Number))
if err != nil {
return nil, err
}
return &protobor.GetHeaderByNumberResponse{Header: headerToProtoborHeader(header)}, nil
}
func (s *Server) BlockByNumber(ctx context.Context, req *protobor.GetBlockByNumberRequest) (*protobor.GetBlockByNumberResponse, error) {
block, err := s.backend.APIBackend.BlockByNumber(ctx, rpc.BlockNumber(req.Number))
if err != nil {
return nil, err
}
return &protobor.GetBlockByNumberResponse{Block: blockToProtoBlock(block)}, nil
}
func blockToProtoBlock(h *types.Block) *protobor.Block {
return &protobor.Block{
Header: headerToProtoborHeader(h.Header()),
}
}
func (s *Server) TransactionReceipt(ctx context.Context, req *protobor.ReceiptRequest) (*protobor.ReceiptResponse, error) {
_, _, blockHash, _, txnIndex, err := s.backend.APIBackend.GetTransaction(ctx, protoutil.ConvertH256ToHash(req.Hash))
if err != nil {
return nil, err
}
receipts, err := s.backend.APIBackend.GetReceipts(ctx, blockHash)
if err != nil {
return nil, err
}
if receipts == nil {
return nil, errors.New("no receipts found")
}
if len(receipts) <= int(txnIndex) {
return nil, errors.New("transaction index out of bounds")
}
return &protobor.ReceiptResponse{Receipt: ConvertReceiptToProtoReceipt(receipts[txnIndex])}, nil
}
func (s *Server) BorBlockReceipt(ctx context.Context, req *protobor.ReceiptRequest) (*protobor.ReceiptResponse, error) {
receipt, err := s.backend.APIBackend.GetBorBlockReceipt(ctx, protoutil.ConvertH256ToHash(req.Hash))
if err != nil {
return nil, err
}
return &protobor.ReceiptResponse{Receipt: ConvertReceiptToProtoReceipt(receipt)}, nil
}

View file

@ -11,16 +11,6 @@ import (
"runtime" "runtime"
"time" "time"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
"google.golang.org/grpc"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
@ -40,14 +30,28 @@ import (
"github.com/ethereum/go-ethereum/metrics/prometheus" "github.com/ethereum/go-ethereum/metrics/prometheus"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
// Force-load the tracer engines to trigger registration // Force-load the tracer engines to trigger registration
_ "github.com/ethereum/go-ethereum/eth/tracers/js" _ "github.com/ethereum/go-ethereum/eth/tracers/js"
_ "github.com/ethereum/go-ethereum/eth/tracers/native" _ "github.com/ethereum/go-ethereum/eth/tracers/native"
protobor "github.com/maticnetwork/polyproto/bor"
) )
type Server struct { type Server struct {
proto.UnimplementedBorServer proto.UnimplementedBorServer
protobor.UnimplementedBorApiServer
node *node.Node node *node.Node
backend *eth.Ethereum backend *eth.Ethereum
grpcServer *grpc.Server grpcServer *grpc.Server
@ -439,6 +443,8 @@ func (s *Server) gRPCServerByAddress(addr string) error {
func (s *Server) gRPCServerByListener(listener net.Listener) error { func (s *Server) gRPCServerByListener(listener net.Listener) error {
s.grpcServer = grpc.NewServer(s.withLoggingUnaryInterceptor()) s.grpcServer = grpc.NewServer(s.withLoggingUnaryInterceptor())
proto.RegisterBorServer(s.grpcServer, s) proto.RegisterBorServer(s.grpcServer, s)
protobor.RegisterBorApiServer(s.grpcServer, s)
reflection.Register(s.grpcServer)
go func() { go func() {
if err := s.grpcServer.Serve(listener); err != nil { if err := s.grpcServer.Serve(listener); err != nil {

View file

@ -0,0 +1,78 @@
package server
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
"github.com/ethereum/go-ethereum/p2p"
protobor "github.com/maticnetwork/polyproto/bor"
protocommon "github.com/maticnetwork/polyproto/common"
protoutil "github.com/maticnetwork/polyproto/utils"
)
func PeerInfoToPeer(info *p2p.PeerInfo) *proto.Peer {
return &proto.Peer{
Id: info.ID,
Enode: info.Enode,
Enr: info.ENR,
Caps: info.Caps,
Name: info.Name,
Trusted: info.Network.Trusted,
Static: info.Network.Static,
}
}
func ConvertBloomToProtoBloom(bloom types.Bloom) *protobor.Bloom {
return &protobor.Bloom{
Bloom: bloom.Bytes(),
}
}
func ConvertLogsToProtoLogs(logs []*types.Log) []*protobor.Log {
var protoLogs []*protobor.Log
for _, log := range logs {
protoLog := &protobor.Log{
Address: protoutil.ConvertAddressToH160(log.Address),
Topics: ConvertTopicsToProtoTopics(log.Topics),
Data: log.Data,
BlockNumber: log.BlockNumber,
TxHash: protoutil.ConvertHashToH256(log.TxHash),
TxIndex: uint64(log.TxIndex),
BlockHash: protoutil.ConvertHashToH256(log.BlockHash),
Index: uint64(log.Index),
Removed: log.Removed,
}
protoLogs = append(protoLogs, protoLog)
}
return protoLogs
}
func ConvertTopicsToProtoTopics(topics []common.Hash) []*protocommon.H256 {
var protoTopics []*protocommon.H256
for _, topic := range topics {
protoTopics = append(protoTopics, protoutil.ConvertHashToH256(topic))
}
return protoTopics
}
func ConvertReceiptToProtoReceipt(receipt *types.Receipt) *protobor.Receipt {
return &protobor.Receipt{
Type: uint64(receipt.Type),
PostState: receipt.PostState,
Status: receipt.Status,
CumulativeGasUsed: receipt.CumulativeGasUsed,
Bloom: ConvertBloomToProtoBloom(receipt.Bloom),
Logs: ConvertLogsToProtoLogs(receipt.Logs),
TxHash: protoutil.ConvertHashToH256(receipt.TxHash),
ContractAddress: protoutil.ConvertAddressToH160(receipt.ContractAddress),
GasUsed: receipt.GasUsed,
EffectiveGasPrice: receipt.EffectiveGasPrice.Int64(),
BlobGasUsed: receipt.BlobGasUsed,
BlockHash: protoutil.ConvertHashToH256(receipt.BlockHash),
BlockNumber: receipt.BlockNumber.Int64(),
TransactionIndex: uint64(receipt.TransactionIndex),
}
}