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

feat: move to agglayer grpc #221

Draft
wants to merge 10 commits into
base: feat/aggchain-prover
Choose a base branch
from
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ lint: ## Runs the linter

.PHONY: generate-code-from-proto
generate-code-from-proto: ## Generates code from proto files
cd proto/src/proto/datastream/v1 && protoc --proto_path=. --proto_path=../../../../include --go_out=../../../../../state/datastream --go-grpc_out=../../../../../state/datastream --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative datastream.proto
# cd proto/src/proto/datastream/v1 && protoc --proto_path=. --proto_path=../../../../include --go_out=../../../../../state/datastream --go-grpc_out=../../../../../state/datastream --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative datastream.proto
protoc --proto_path=agglayer/proto \
--go_out=agglayer/proto --go_opt=paths=source_relative \
--go-grpc_out=agglayer/proto --go-grpc_opt=paths=source_relative \
agglayer/proto/types/*.proto \
agglayer/proto/node/*.proto


## Help display.
Expand Down
37 changes: 18 additions & 19 deletions agglayer/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import (
"time"

"github.com/0xPolygon/cdk-rpc/rpc"
"github.com/0xPolygon/cdk-rpc/types"
rpcTypes "github.com/0xPolygon/cdk-rpc/types"
"github.com/agglayer/aggkit/agglayer/types"
"github.com/ethereum/go-ethereum/common"
)

Expand All @@ -21,20 +22,18 @@ var (
)

type AggLayerClientGetEpochConfiguration interface {
GetEpochConfiguration() (*ClockConfiguration, error)
GetEpochConfiguration(ctx context.Context) (*types.ClockConfiguration, error)
}

type AggLayerClientRecoveryQuerier interface {
GetLatestSettledCertificateHeader(networkID uint32) (*CertificateHeader, error)
GetLatestPendingCertificateHeader(networkID uint32) (*CertificateHeader, error)
GetLatestSettledCertificateHeader(ctx context.Context, networkID uint32) (*types.CertificateHeader, error)
GetLatestPendingCertificateHeader(ctx context.Context, networkID uint32) (*types.CertificateHeader, error)
}

// AgglayerClientInterface is the interface that defines the methods that the AggLayerClient will implement
type AgglayerClientInterface interface {
SendTx(signedTx SignedTx) (common.Hash, error)
WaitTxToBeMined(hash common.Hash, ctx context.Context) error
SendCertificate(certificate *SignedCertificate) (common.Hash, error)
GetCertificateHeader(certificateHash common.Hash) (*CertificateHeader, error)
SendCertificate(ctx context.Context, certificate *types.SignedCertificate) (common.Hash, error)
GetCertificateHeader(ctx context.Context, certificateHash common.Hash) (*types.CertificateHeader, error)
AggLayerClientGetEpochConfiguration
AggLayerClientRecoveryQuerier
}
Expand Down Expand Up @@ -65,7 +64,7 @@ func (c *AggLayerClient) SendTx(signedTx SignedTx) (common.Hash, error) {
return common.Hash{}, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message)
}

var result types.ArgHash
var result rpcTypes.ArgHash
err = json.Unmarshal(response.Result, &result)
if err != nil {
return common.Hash{}, err
Expand Down Expand Up @@ -104,7 +103,7 @@ func (c *AggLayerClient) WaitTxToBeMined(hash common.Hash, ctx context.Context)
}

// SendCertificate sends a certificate to the AggLayer
func (c *AggLayerClient) SendCertificate(certificate *SignedCertificate) (common.Hash, error) {
func (c *AggLayerClient) SendCertificate(certificate *types.SignedCertificate) (common.Hash, error) {
certificateToSend := certificate.CopyWithDefaulting()

response, err := rpc.JSONRPCCall(c.url, "interop_sendCertificate", certificateToSend)
Expand All @@ -116,7 +115,7 @@ func (c *AggLayerClient) SendCertificate(certificate *SignedCertificate) (common
return common.Hash{}, fmt.Errorf("%d %s", response.Error.Code, response.Error.Message)
}

var result types.ArgHash
var result rpcTypes.ArgHash
err = json.Unmarshal(response.Result, &result)
if err != nil {
return common.Hash{}, err
Expand All @@ -126,7 +125,7 @@ func (c *AggLayerClient) SendCertificate(certificate *SignedCertificate) (common
}

// GetCertificateHeader returns the certificate header associated to the hash
func (c *AggLayerClient) GetCertificateHeader(certificateHash common.Hash) (*CertificateHeader, error) {
func (c *AggLayerClient) GetCertificateHeader(certificateHash common.Hash) (*types.CertificateHeader, error) {
response, err := rpc.JSONRPCCall(c.url, "interop_getCertificateHeader", certificateHash)
if err != nil {
return nil, err
Expand All @@ -136,7 +135,7 @@ func (c *AggLayerClient) GetCertificateHeader(certificateHash common.Hash) (*Cer
return nil, fmt.Errorf("%d %s", response.Error.Code, response.Error.Message)
}

var result *CertificateHeader
var result *types.CertificateHeader
err = json.Unmarshal(response.Result, &result)
if err != nil {
return nil, err
Expand All @@ -146,7 +145,7 @@ func (c *AggLayerClient) GetCertificateHeader(certificateHash common.Hash) (*Cer
}

// GetEpochConfiguration returns the clock configuration of AggLayer
func (c *AggLayerClient) GetEpochConfiguration() (*ClockConfiguration, error) {
func (c *AggLayerClient) GetEpochConfiguration() (*types.ClockConfiguration, error) {
response, err := jSONRPCCall(c.url, "interop_getEpochConfiguration")
if err != nil {
return nil, err
Expand All @@ -156,7 +155,7 @@ func (c *AggLayerClient) GetEpochConfiguration() (*ClockConfiguration, error) {
return nil, fmt.Errorf("GetEpochConfiguration code=%d msg=%s", response.Error.Code, response.Error.Message)
}

var result *ClockConfiguration
var result *types.ClockConfiguration
err = json.Unmarshal(response.Result, &result)
if err != nil {
return nil, err
Expand All @@ -165,7 +164,7 @@ func (c *AggLayerClient) GetEpochConfiguration() (*ClockConfiguration, error) {
return result, nil
}

func (c *AggLayerClient) GetLatestSettledCertificateHeader(networkID uint32) (*CertificateHeader, error) {
func (c *AggLayerClient) GetLatestSettledCertificateHeader(networkID uint32) (*types.CertificateHeader, error) {
response, err := jSONRPCCall(c.url, "interop_getLatestSettledCertificateHeader", networkID)
if err != nil {
return nil, fmt.Errorf("interop_getLatestSettledCertificateHeader rpc call failed: %w", err)
Expand All @@ -176,7 +175,7 @@ func (c *AggLayerClient) GetLatestSettledCertificateHeader(networkID uint32) (*C
response.Error.Code, response.Error.Message)
}

var result *CertificateHeader
var result *types.CertificateHeader
err = json.Unmarshal(response.Result, &result)
if err != nil {
return nil, fmt.Errorf("GetLatestSettledCertificateHeader error Unmashal. Err: %w", err)
Expand All @@ -185,7 +184,7 @@ func (c *AggLayerClient) GetLatestSettledCertificateHeader(networkID uint32) (*C
return result, nil
}

func (c *AggLayerClient) GetLatestPendingCertificateHeader(networkID uint32) (*CertificateHeader, error) {
func (c *AggLayerClient) GetLatestPendingCertificateHeader(networkID uint32) (*types.CertificateHeader, error) {
response, err := jSONRPCCall(c.url, "interop_getLatestPendingCertificateHeader", networkID)
if err != nil {
return nil, fmt.Errorf("interop_getLatestPendingCertificateHeader rpc call failed: %w", err)
Expand All @@ -196,7 +195,7 @@ func (c *AggLayerClient) GetLatestPendingCertificateHeader(networkID uint32) (*C
response.Error.Code, response.Error.Message)
}

var result *CertificateHeader
var result *types.CertificateHeader
err = json.Unmarshal(response.Result, &result)
if err != nil {
return nil, fmt.Errorf("GetLatestPendingCertificateHeader error Unmashal. Err: %w", err)
Expand Down
3 changes: 2 additions & 1 deletion agglayer/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/0xPolygon/cdk-rpc/rpc"
"github.com/agglayer/aggkit/agglayer/types"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -100,7 +101,7 @@ func TestGetEpochConfigurationOkResponse(t *testing.T) {
clockConfig, err := sut.GetEpochConfiguration()
require.NotNil(t, clockConfig)
require.NoError(t, err)
require.Equal(t, ClockConfiguration{
require.Equal(t, types.ClockConfiguration{
EpochDuration: 1,
GenesisBlock: 1,
}, *clockConfig)
Expand Down
134 changes: 134 additions & 0 deletions agglayer/grpc/agglayer_grpc_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package grpc

import (
"context"
"errors"

"github.com/agglayer/aggkit/agglayer/proto/node"
protoTypes "github.com/agglayer/aggkit/agglayer/proto/types"
"github.com/agglayer/aggkit/agglayer/types"
aggkitCommon "github.com/agglayer/aggkit/common"
"github.com/ethereum/go-ethereum/common"
)

type AgglayerGRPCClient struct {
networkStateService node.NodeStateServiceClient
cfgService node.ConfigurationServiceClient
submissionService node.CertificateSubmissionServiceClient
}

// NewAggchainProofClient initializes a new AggchainProof instance
func NewAgglayerGRPCClient(serverAddr string) (*AgglayerGRPCClient, error) {
grpcClient, err := aggkitCommon.NewClient(serverAddr)
if err != nil {
return nil, err
}

return &AgglayerGRPCClient{
networkStateService: node.NewNodeStateServiceClient(grpcClient.Conn()),
cfgService: node.NewConfigurationServiceClient(grpcClient.Conn()),
submissionService: node.NewCertificateSubmissionServiceClient(grpcClient.Conn()),
}, nil
}

// GetEpochConfiguration returns the epoch configuration from the AggLayer
func (a *AgglayerGRPCClient) GetEpochConfiguration(ctx context.Context) (*types.ClockConfiguration, error) {
response, err := a.cfgService.GetEpochConfiguration(ctx, &node.GetEpochConfigurationRequest{})
if err != nil {
return nil, err
}

return &types.ClockConfiguration{
EpochDuration: response.EpochConfiguration.EpochDuration,
GenesisBlock: response.EpochConfiguration.GenesisBlock,
}, nil
}

func (a *AgglayerGRPCClient) SendCertificate(ctx context.Context,
certificate *types.SignedCertificate) (common.Hash, error) {
response, err := a.submissionService.SubmitCertificate(ctx, &node.SubmitCertificateRequest{
Certificate: &protoTypes.Certificate{
NetworkId: certificate.NetworkID,
Height: certificate.Height,
},
})

if err != nil {
return common.Hash{}, err
}

return common.BytesToHash(response.CertificateId.Value.Value), nil
}

// GetCertificateHeader returns the certificate header from the AggLayer for the given certificate ID
func (a *AgglayerGRPCClient) GetCertificateHeader(ctx context.Context,
certificateID common.Hash) (*types.CertificateHeader, error) {
response, err := a.networkStateService.GetCertificateHeader(ctx,
&node.GetCertificateHeaderRequest{CertificateId: &protoTypes.CertificateId{
Value: &protoTypes.FixedBytes32{
Value: certificateID.Bytes(),
},
},
})
if err != nil {
return nil, err
}

return convertProtoCertificateHeader(response.CertificateHeader), nil
}

// GetLatestPendingCertificateHeader returns the latest pending certificate header from the AggLayer
func (a *AgglayerGRPCClient) GetLatestSettledCertificateHeader(
ctx context.Context, networkID uint32) (*types.CertificateHeader, error) {
response, err := a.networkStateService.GetLatestSettledCertificateHeader(ctx,
&node.GetLatestSettledCertificateHeaderRequest{NetworkId: networkID})
if err != nil {
return nil, err
}

return convertProtoCertificateHeader(response.CertificateHeader), nil
}

// GetLatestPendingCertificateHeader returns the latest pending certificate header from the AggLayer
func (a *AgglayerGRPCClient) GetLatestPendingCertificateHeader(
ctx context.Context, networkID uint32) (*types.CertificateHeader, error) {
response, err := a.networkStateService.GetLatestPendingCertificateHeader(ctx,
&node.GetLatestPendingCertificateHeaderRequest{NetworkId: networkID})
if err != nil {
return nil, err
}

return convertProtoCertificateHeader(response.CertificateHeader), nil
}

// convertProtoCertificateHeader converts a proto certificate header to a types certificate header
func convertProtoCertificateHeader(response *protoTypes.CertificateHeader) *types.CertificateHeader {
header := &types.CertificateHeader{
NetworkID: response.NetworkId,
Height: response.Height,
EpochNumber: response.EpochNumber,
CertificateIndex: response.CertificateIndex,
CertificateID: common.BytesToHash(response.CertificateId.Value.Value),
PreviousLocalExitRoot: nullableBytesToHash(response.PrevLocalExitRoot.Value),
NewLocalExitRoot: common.BytesToHash(response.NewLocalExitRoot.Value),
Status: types.CertificateStatus(response.Status),
Metadata: common.BytesToHash(response.Metadata.Value),
// AggchainProof - TODO
}

if response.Error != nil && response.Error.Message != nil {
header.Error = errors.New(string(response.Error.Message))
}

return header
}

// nullableBytesToHash converts a nullable byte slice to a hash pointer
func nullableBytesToHash(b []byte) *common.Hash {
if len(b) == 0 {
return nil
}

hash := common.BytesToHash(b)
return &hash
}
Loading
Loading