Skip to content

Commit

Permalink
feat: incorporate getCertificateHeader call
Browse files Browse the repository at this point in the history
  • Loading branch information
goran-ethernal committed Oct 3, 2024
1 parent 772987b commit 7612888
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 31 deletions.
37 changes: 32 additions & 5 deletions agglayer/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import (
type AgglayerClientInterface interface {
SendTx(signedTx SignedTx) (common.Hash, error)
WaitTxToBeMined(hash common.Hash, ctx context.Context) error
SendCertificate(certificate *SignedCertificate) error
SendCertificate(certificate *SignedCertificate) (common.Hash, error)
GetCertificateHeader(certificateHash common.Hash) (*CertificateHeader, error)
}

// AggLayerClient is the client that will be used to interact with the AggLayer
Expand Down Expand Up @@ -82,15 +83,41 @@ func (c *AggLayerClient) WaitTxToBeMined(hash common.Hash, ctx context.Context)
}

// SendCertificate sends a certificate to the AggLayer
func (c *AggLayerClient) SendCertificate(certificate *SignedCertificate) error {
func (c *AggLayerClient) SendCertificate(certificate *SignedCertificate) (common.Hash, error) {
response, err := rpc.JSONRPCCall(c.url, "interop_sendCertificate", certificate)
if err != nil {
return err
return common.Hash{}, err
}

if response.Error != nil {
return fmt.Errorf("%v %v", response.Error.Code, response.Error.Message)
return common.Hash{}, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message)
}

var result types.ArgHash
err = json.Unmarshal(response.Result, &result)
if err != nil {
return common.Hash{}, err
}

return result.Hash(), nil
}

// GetCertificateHeader returns the certificate header associated to the hash
func (c *AggLayerClient) GetCertificateHeader(certificateHash common.Hash) (*CertificateHeader, error) {
response, err := rpc.JSONRPCCall(c.url, "interop_getCertificateHeader", certificateHash)
if err != nil {
return nil, err
}

if response.Error != nil {
return nil, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message)
}

var result *CertificateHeader
err = json.Unmarshal(response.Result, &result)
if err != nil {
return nil, err
}

return nil
return result, nil
}
24 changes: 24 additions & 0 deletions agglayer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)

type CertificateStatus int

const (
Pending CertificateStatus = iota
InError
Settled
)

// String representation of the enum
func (c CertificateStatus) String() string {
return [...]string{"Pending", "InError", "Settled"}[c]
}

type LeafType uint8

func (l LeafType) Uint8() uint8 {
Expand Down Expand Up @@ -151,3 +164,14 @@ func (c *ImportedBridgeExit) Hash() common.Hash {
c.GlobalIndex.RollupIndex, c.GlobalIndex.LeafIndex)
return crypto.Keccak256Hash(globalIndexBig.Bytes())
}

// CertificateHeader is the structure returned by the interop_getCertificateHeader RPC call
type CertificateHeader struct {
NetworkID uint32 `json:"network_id"`
Height uint64 `json:"height"`
EpochNumber *uint64 `json:"epoch_number"`
CertificateIndex *uint64 `json:"certificate_index"`
CertificateID common.Hash `json:"certificate_id"`
NewLocalExitRoot common.Hash `json:"new_local_exit_root"`
Status CertificateStatus `json:"status"`
}
57 changes: 33 additions & 24 deletions aggsender/aggsender.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,26 +103,41 @@ func (a *AggSender) sendCertificates(ctx context.Context) {
func (a *AggSender) sendCertificate(ctx context.Context) error {
a.log.Info("trying to send a new certificate...")

lastSentCertificateBlock, lastSentCertificate, err := a.getLastSentCertificate(ctx)
lastSentCertificateHash, _, err := a.getLastSentCertificate(ctx)
if err != nil {
return fmt.Errorf("error getting last sent certificate: %w", err)
}

a.log.Info("last sent certificate block: %d", lastSentCertificateBlock)
a.log.Info("last sent certificate: %s", lastSentCertificateHash)

finality := a.l2Syncer.BlockFinality()
blockFinality, err := finality.ToBlockNum()
if err != nil {
return fmt.Errorf("error getting block finality: %w", err)
}

lastFinalizedBlock, err := a.l2Client.HeaderByNumber(ctx, blockFinality)
lastL2Block, err := a.l2Client.HeaderByNumber(ctx, blockFinality)
if err != nil {
return fmt.Errorf("error getting block number: %w", err)
return fmt.Errorf("error getting block from l2: %w", err)
}

fromBlock := lastSentCertificateBlock + 1
toBlock := lastFinalizedBlock.Nonce.Uint64()
lastSentCertificateHeader, err := a.aggLayerClient.GetCertificateHeader(lastSentCertificateHash)
if err != nil {
return fmt.Errorf("error getting certificate %s header: %w", lastSentCertificateHash, err)
}

block, err := a.l2Syncer.GetBlockByLER(ctx, lastSentCertificateHeader.NewLocalExitRoot)
if err != nil {
return fmt.Errorf("error getting block by LER %s: %w", lastSentCertificateHash, err)
}

if lastL2Block.Number.Uint64() <= block {
a.log.Info("no new blocks to send a certificate")
return nil
}

fromBlock := block + 1
toBlock := lastL2Block.Number.Uint64()

bridges, err := a.l2Syncer.GetBridges(ctx, fromBlock, toBlock)
if err != nil {
Expand All @@ -139,14 +154,7 @@ func (a *AggSender) sendCertificate(ctx context.Context) error {
return fmt.Errorf("error getting claims: %w", err)
}

previousExitRoot := common.Hash{}
lastHeight := uint64(0)
if lastSentCertificate != nil {
previousExitRoot = lastSentCertificate.NewLocalExitRoot
lastHeight = lastSentCertificate.Height
}

certificate, err := a.buildCertificate(ctx, bridges, claims, previousExitRoot, lastHeight)
certificate, err := a.buildCertificate(ctx, bridges, claims, lastSentCertificateHeader.NewLocalExitRoot, lastSentCertificateHeader.Height)
if err != nil {
return fmt.Errorf("error building certificate: %w", err)
}
Expand All @@ -156,15 +164,16 @@ func (a *AggSender) sendCertificate(ctx context.Context) error {
return fmt.Errorf("error signing certificate: %w", err)
}

if err := a.aggLayerClient.SendCertificate(signedCertificate); err != nil {
certificateHash, err := a.aggLayerClient.SendCertificate(signedCertificate)
if err != nil {
return fmt.Errorf("error sending certificate: %w", err)
}

if err := a.saveLastSentCertificate(ctx, lastFinalizedBlock.Nonce.Uint64(), certificate); err != nil {
if err := a.saveLastSentCertificate(ctx, certificateHash, certificate); err != nil {
return fmt.Errorf("error saving last sent certificate in db: %w", err)
}

a.log.Info("certificate sent successfully for block: %d", lastFinalizedBlock.Nonce.Uint64())
a.log.Info("certificate: %s sent successfully for block: %d", certificateHash, lastL2Block.Nonce.Uint64())

return nil
}
Expand Down Expand Up @@ -343,23 +352,23 @@ func (a *AggSender) getImportedBridgeExits(ctx context.Context,
}

// saveLastSentCertificate saves the last sent certificate
func (a *AggSender) saveLastSentCertificate(ctx context.Context, blockNum uint64,
func (a *AggSender) saveLastSentCertificate(ctx context.Context, certificateHash common.Hash,
certificate *agglayer.Certificate) error {
return a.db.Update(ctx, func(tx kv.RwTx) error {
raw, err := json.Marshal(certificate)
if err != nil {
return err
}

return tx.Put(sentCertificatesL2Table, cdkcommon.Uint64ToBytes(blockNum), raw)
return tx.Put(sentCertificatesL2Table, certificateHash.Bytes(), raw)
})
}

// getLastSentCertificate returns the last sent certificate
func (a *AggSender) getLastSentCertificate(ctx context.Context) (uint64, *agglayer.Certificate, error) {
func (a *AggSender) getLastSentCertificate(ctx context.Context) (common.Hash, *agglayer.Certificate, error) {
var (
lastSentCertificateBlock uint64
lastCertificate *agglayer.Certificate
lastSentCertificateHash common.Hash
lastCertificate *agglayer.Certificate
)

err := a.db.View(ctx, func(tx kv.Tx) error {
Expand All @@ -374,7 +383,7 @@ func (a *AggSender) getLastSentCertificate(ctx context.Context) (uint64, *agglay
}

if k != nil {
lastSentCertificateBlock = cdkcommon.BytesToUint64(k)
lastSentCertificateHash = common.BytesToHash(k)
if err := json.Unmarshal(v, &lastCertificate); err != nil {
return err
}
Expand All @@ -383,7 +392,7 @@ func (a *AggSender) getLastSentCertificate(ctx context.Context) (uint64, *agglay
return nil
})

return lastSentCertificateBlock, lastCertificate, err
return lastSentCertificateHash, lastCertificate, err
}

// signCertificate signs a certificate with the sequencer key
Expand Down
4 changes: 2 additions & 2 deletions bridgesync/bridgesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ func (s *BridgeSync) GetProof(ctx context.Context, depositCount uint32, localExi
return s.processor.exitTree.GetProof(ctx, depositCount, localExitRoot)
}

func (p *processor) GetBlockByLER(ctx context.Context, ler common.Hash) (uint64, error) {
root, err := p.exitTree.GetRootByHash(ctx, ler)
func (p *BridgeSync) GetBlockByLER(ctx context.Context, ler common.Hash) (uint64, error) {
root, err := p.processor.exitTree.GetRootByHash(ctx, ler)
if err != nil {
return 0, err
}
Expand Down

0 comments on commit 7612888

Please sign in to comment.