Skip to content

Commit

Permalink
feat: cherry picks from release for aggsender (#246)
Browse files Browse the repository at this point in the history
* refactor: encode metadata to be backwards compatible (#216)

* refactor: encode metadata to be backwards compatible

* tests: fix UT

* apply feedback

* test: fix

* fix merge issues

* refactor: metadata cert versioning

* test: fix ut

* fix: typo

* use the CertificateBuildParams

* test: fix ut

* Apply feedback

* fix: lint

* fix: Aggsender high cpu usage (#235)

- fix aggsender is using about 200% of CPU
- add a warning if decrease blockNumber (from L1 provider)

* fix: calculate correct root for `LER` merkle proof and fix `BridgeExit` hash (#237)

* fix: calculate correct root for LER merkle proof, and fix BridgeExit hash

* fix: UTs

* fix: comments

* fix: sqlite3 config improvements

Set some recommended params for sqlite connection.

* fix: lint

---------

Co-authored-by: Victor Castell <[email protected]>
Co-authored-by: Joan Esteban <[email protected]>
Co-authored-by: Victor Castell <[email protected]>
  • Loading branch information
4 people authored Dec 18, 2024
1 parent aab06f8 commit e53a878
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 95 deletions.
2 changes: 1 addition & 1 deletion agglayer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ func (b *BridgeExit) Hash() common.Hash {
b.TokenInfo.OriginTokenAddress.Bytes(),
cdkcommon.Uint32ToBytes(b.DestinationNetwork),
b.DestinationAddress.Bytes(),
b.Amount.Bytes(),
common.BigToHash(b.Amount).Bytes(),
metaDataHash,
)
}
Expand Down
15 changes: 0 additions & 15 deletions agglayer/types_helpers_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package agglayer

import (
"fmt"
"testing"

"github.com/0xPolygon/cdk/tree/types"
"github.com/ethereum/go-ethereum/common"
)

Expand Down Expand Up @@ -56,16 +54,3 @@ func createDummyClaim(t *testing.T) *ClaimFromMainnnet {
},
}
}

// Helper function to create a dummy proof
func createDummyProof(t *testing.T) types.Proof {
t.Helper()

proof := types.Proof{}

for i := 0; i < int(types.DefaultHeight); i++ {
proof[i] = common.HexToHash(fmt.Sprintf("0x%x", i))
}

return proof
}
46 changes: 38 additions & 8 deletions agglayer/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,21 @@ func TestBridgeExit_Hash(t *testing.T) {
IsMetadataHashed: true,
Metadata: MetadaHash[:],
}
require.Equal(t, "0x7d344cd1a895c66f0819be6a392d2a5d649c0cd5c8345706e11c757324da2943",
require.Equal(t, "0xaa57e4bf430fe25ca5068f9e1a25e8aef15744905cdf7635e0d5a468bd26bb18",
bridge.Hash().String(), "use the hashed metadata, instead of calculating hash")

bridge.IsMetadataHashed = false
require.Equal(t, "0xa3ef92d7ca132432b864e424039077556b8757d2da4e01d6040c6ccbb39bef60",
require.Equal(t, "0x79d5362ad609e06e022277ede4fd10899dc189c0ed56e1a2c6982d0563fe1be7",
bridge.Hash().String(), "metadata is not hashed, calculate hash")

bridge.IsMetadataHashed = false
bridge.Metadata = []byte{}
require.Equal(t, "0xad4224e96b39d42026b4795e5be83f43e0df757cdb13e781cd49e1a5363b193c",
require.Equal(t, "0xe3e297278c7df4ae4f235be10155ac62c53b08e2a14ed09b7dd6b688952ee883",
bridge.Hash().String(), "metadata is not hashed and it's empty, calculate hash")

bridge.IsMetadataHashed = true
bridge.Metadata = []byte{}
require.Equal(t, "0x184125b2e3d1ded2ad3f82a383d9b09bd5bac4ccea4d41092f49523399598aca",
require.Equal(t, "0x51980562e41978f15369c21f26920284ac6836d53b02cd89edf4fedc97e68215",
bridge.Hash().String(), "metadata is a hashed and it's empty,use it")
}

Expand Down Expand Up @@ -248,10 +248,10 @@ func TestMarshalJSON(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expectedJSON, string(data))

require.Equal(t, "0x46da3ca29098968ffc46ed2b894757671fa73cf7ebd4b82c89e90cc36a2737ae", cert.Hash().String())
require.Equal(t, "0xc82b12e7383d2a8c1ec290d575bf6b2ac48363ca824cd51fe9f8cd312d55cd7a", cert.BridgeExits[0].Hash().String())
require.Equal(t, "0x23fbdb2d272c9a4ae45135986363363d2e87dd6c2f2494a62b86851396f3fed4", cert.ImportedBridgeExits[0].Hash().String())
require.Equal(t, "0x7eb947fcd0ed89ba0f41ec3f85e600d7114ec9349eb99a9478e3dd4e456297b1", cert.ImportedBridgeExits[1].Hash().String())
require.Equal(t, "0xda355a601420351a0c950ebb34b6278580978d7b6a215338531d543a8f03574a", cert.Hash().String())
require.Equal(t, "0x2f01782930cbf2bc2ab4ec16759a2288ad7df865dea387aadf55f96136269cf4", cert.BridgeExits[0].Hash().String())
require.Equal(t, "0xac83b106ad2ca491828d49613c8356a15e3de298c794e1abd9632dc4d03b7c79", cert.ImportedBridgeExits[0].Hash().String())
require.Equal(t, "0x6d9dc59396058ef7845fd872a87e77f1a58d010a760957f8814bd3d2ca5914a1", cert.ImportedBridgeExits[1].Hash().String())
})
}

Expand Down Expand Up @@ -510,6 +510,8 @@ func TestConvertNumeric(t *testing.T) {
}

for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -731,6 +733,8 @@ func TestBridgeExit_String(t *testing.T) {
}

for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
t.Parallel()
actualOutput := tt.bridgeExit.String()
Expand Down Expand Up @@ -793,6 +797,8 @@ func TestCertificateStatus_UnmarshalJSON(t *testing.T) {
}

for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -852,6 +858,8 @@ func TestMerkleProof_String(t *testing.T) {
}

for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -899,6 +907,8 @@ func TestGlobalIndexString(t *testing.T) {
}

for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -936,6 +946,8 @@ func TestL1InfoTreeLeafString(t *testing.T) {
}

for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -966,6 +978,8 @@ func TestClaimType(t *testing.T) {
}

for _, c := range cases {
c := c

t.Run(c.name, func(t *testing.T) {
t.Parallel()

Expand All @@ -975,6 +989,22 @@ func TestClaimType(t *testing.T) {
}
}

func Test_ProblematicBridgeExitHash(t *testing.T) {
bridgeExit := &BridgeExit{
LeafType: LeafTypeAsset,
TokenInfo: &TokenInfo{
OriginNetwork: 0,
OriginTokenAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"),
},
DestinationNetwork: 1,
DestinationAddress: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"),
Amount: new(big.Int).SetUint64(10000000000000000000),
IsMetadataHashed: false,
}

require.Equal(t, "0x22ed288677b4c2afd83a6d7d55f7df7f4eaaf60f7310210c030fd27adacbc5e0", bridgeExit.Hash().Hex())
}

func generateTestProof(t *testing.T) types.Proof {
t.Helper()

Expand Down
41 changes: 25 additions & 16 deletions aggsender/aggsender.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
cdkcommon "github.com/0xPolygon/cdk/common"
"github.com/0xPolygon/cdk/l1infotreesync"
"github.com/0xPolygon/cdk/log"
"github.com/0xPolygon/cdk/tree"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
Expand Down Expand Up @@ -195,6 +196,7 @@ func (a *AggSender) sendCertificate(ctx context.Context) (*agglayer.SignedCertif
ToBlock: toBlock,
Bridges: bridges,
Claims: claims,
CreatedAt: uint32(time.Now().UTC().Unix()),
}

certificateParams, err = a.limitCertSize(certificateParams)
Expand All @@ -204,8 +206,7 @@ func (a *AggSender) sendCertificate(ctx context.Context) (*agglayer.SignedCertif
a.log.Infof("building certificate for %s estimatedSize=%d",
certificateParams.String(), certificateParams.EstimatedSize())

createdTime := time.Now().UTC().UnixMilli()
certificate, err := a.buildCertificate(ctx, certificateParams, lastSentCertificateInfo, createdTime)
certificate, err := a.buildCertificate(ctx, certificateParams, lastSentCertificateInfo)
if err != nil {
return nil, fmt.Errorf("error building certificate: %w", err)
}
Expand Down Expand Up @@ -238,8 +239,8 @@ func (a *AggSender) sendCertificate(ctx context.Context) (*agglayer.SignedCertif
PreviousLocalExitRoot: &prevLER,
FromBlock: fromBlock,
ToBlock: toBlock,
CreatedAt: createdTime,
UpdatedAt: createdTime,
CreatedAt: certificateParams.CreatedAt,
UpdatedAt: certificateParams.CreatedAt,
SignedCertificate: string(raw),
}
// TODO: Improve this case, if a cert is not save in the storage, we are going to settle a unknown certificate
Expand Down Expand Up @@ -370,7 +371,7 @@ func (a *AggSender) getNextHeightAndPreviousLER(
// buildCertificate builds a certificate from the bridge events
func (a *AggSender) buildCertificate(ctx context.Context,
certParams *types.CertificateBuildParams,
lastSentCertificateInfo *types.CertificateInfo, createdAt int64) (*agglayer.Certificate, error) {
lastSentCertificateInfo *types.CertificateInfo) (*agglayer.Certificate, error) {
if certParams.IsEmpty() {
return nil, errNoBridgesAndClaims
}
Expand All @@ -381,7 +382,7 @@ func (a *AggSender) buildCertificate(ctx context.Context,
return nil, fmt.Errorf("error getting imported bridge exits: %w", err)
}

depositCount := certParams.MaxDepoitCount()
depositCount := certParams.MaxDepositCount()

exitRoot, err := a.l2Syncer.GetExitRootByIndex(ctx, depositCount)
if err != nil {
Expand All @@ -393,11 +394,11 @@ func (a *AggSender) buildCertificate(ctx context.Context,
return nil, fmt.Errorf("error getting next height and previous LER: %w", err)
}

meta := &types.CertificateMetadata{
FromBlock: certParams.FromBlock,
ToBlock: certParams.ToBlock,
CreatedAt: uint64(createdAt),
}
meta := types.NewCertificateMetadata(
certParams.FromBlock,
uint32(certParams.ToBlock-certParams.FromBlock),
certParams.CreatedAt,
)

return &agglayer.Certificate{
NetworkID: a.l2Syncer.OriginNetwork(),
Expand Down Expand Up @@ -575,7 +576,8 @@ func (a *AggSender) getImportedBridgeExits(
},
},
ProofLeafLER: &agglayer.MerkleProof{
Root: claim.MainnetExitRoot,
Root: tree.CalculateRoot(ibe.BridgeExit.Hash(),
claim.ProofLocalExitRoot, ibe.GlobalIndex.LeafIndex),
Proof: claim.ProofLocalExitRoot,
},
ProofLERToRER: &agglayer.MerkleProof{
Expand Down Expand Up @@ -682,7 +684,7 @@ func (a *AggSender) updateCertificateStatus(ctx context.Context,
}

localCert.Status = agglayerCert.Status
localCert.UpdatedAt = time.Now().UTC().UnixMilli()
localCert.UpdatedAt = uint32(time.Now().UTC().Unix())
if err := a.storage.UpdateCertificate(ctx, *localCert); err != nil {
a.log.Errorf("error updating certificate %s status in storage: %w", agglayerCert.ID(), err)
return fmt.Errorf("error updating certificate. Err: %w", err)
Expand Down Expand Up @@ -797,17 +799,24 @@ func NewCertificateInfoFromAgglayerCertHeader(c *agglayer.CertificateHeader) *ty
if c == nil {
return nil
}
now := uint32(time.Now().UTC().Unix())
meta := types.NewCertificateMetadataFromHash(c.Metadata)
now := time.Now().UTC().UnixMilli()
toBlock := meta.FromBlock + uint64(meta.Offset)
createdAt := meta.CreatedAt

if meta.Version < 1 {
toBlock = meta.ToBlock
createdAt = now
}

res := &types.CertificateInfo{
Height: c.Height,
CertificateID: c.CertificateID,
NewLocalExitRoot: c.NewLocalExitRoot,
FromBlock: meta.FromBlock,
ToBlock: meta.ToBlock,
ToBlock: toBlock,
Status: c.Status,
CreatedAt: int64(meta.CreatedAt),
CreatedAt: createdAt,
UpdatedAt: now,
SignedCertificate: "na/agglayer header",
}
Expand Down
32 changes: 11 additions & 21 deletions aggsender/aggsender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ func TestGetImportedBridgeExits(t *testing.T) {
},
},
ProofLeafLER: &agglayer.MerkleProof{
Root: common.HexToHash("0xbbba"),
Root: common.HexToHash("0xc52019815b51acf67a715cae6794a20083d63fd9af45783b7adf69123dae92c8"),
Proof: mockProof,
},
ProofLERToRER: &agglayer.MerkleProof{
Expand Down Expand Up @@ -491,7 +491,7 @@ func TestGetImportedBridgeExits(t *testing.T) {
},
},
ProofLeafLER: &agglayer.MerkleProof{
Root: common.HexToHash("0xbbb"),
Root: common.HexToHash("0x105e0f1144e57f6fb63f1dfc5083b1f59be3512be7cf5e63523779ad14a4d987"),
Proof: mockProof,
},
ProofLERToRER: &agglayer.MerkleProof{
Expand Down Expand Up @@ -677,7 +677,7 @@ func TestBuildCertificate(t *testing.T) {
},
},
ProofLeafLER: &agglayer.MerkleProof{
Root: common.HexToHash("0xbbba"),
Root: common.HexToHash("0xc52019815b51acf67a715cae6794a20083d63fd9af45783b7adf69123dae92c8"),
Proof: mockProof,
},
ProofLERToRER: &agglayer.MerkleProof{
Expand Down Expand Up @@ -790,7 +790,7 @@ func TestBuildCertificate(t *testing.T) {
Bridges: tt.bridges,
Claims: tt.claims,
}
cert, err := aggSender.buildCertificate(context.Background(), certParam, &tt.lastSentCertificateInfo, 0)
cert, err := aggSender.buildCertificate(context.Background(), certParam, &tt.lastSentCertificateInfo)

if tt.expectedError {
require.Error(t, err)
Expand Down Expand Up @@ -1705,18 +1705,6 @@ func TestSendCertificate_NoClaims(t *testing.T) {
mockL1InfoTreeSyncer.AssertExpectations(t)
}

func TestMetadataConversions(t *testing.T) {
fromBlock := uint64(123567890)
toBlock := uint64(123567890)
createdAt := uint64(0)
meta := aggsendertypes.NewCertificateMetadata(fromBlock, toBlock, createdAt)
c := meta.ToHash()
extractBlock := aggsendertypes.NewCertificateMetadataFromHash(c)
require.Equal(t, fromBlock, extractBlock.FromBlock)
require.Equal(t, toBlock, extractBlock.ToBlock)
require.Equal(t, createdAt, extractBlock.CreatedAt)
}

func TestExtractFromCertificateMetadataToBlock(t *testing.T) {
t.Parallel()

Expand All @@ -1727,19 +1715,21 @@ func TestExtractFromCertificateMetadataToBlock(t *testing.T) {
}{
{
name: "Valid metadata",
metadata: aggsendertypes.NewCertificateMetadata(0, 123567890, 123567890).ToHash(),
metadata: aggsendertypes.NewCertificateMetadata(0, 1000, 123567890).ToHash(),
expected: aggsendertypes.CertificateMetadata{
Version: 1,
FromBlock: 0,
ToBlock: 123567890,
Offset: 1000,
CreatedAt: 123567890,
},
},
{
name: "Zero metadata",
metadata: aggsendertypes.NewCertificateMetadata(0, 0, 0).ToHash(),
expected: aggsendertypes.CertificateMetadata{
Version: 1,
FromBlock: 0,
ToBlock: 0,
Offset: 0,
CreatedAt: 0,
},
},
Expand Down Expand Up @@ -2033,8 +2023,8 @@ func certInfoToCertHeader(t *testing.T, certInfo *aggsendertypes.CertificateInfo
Status: agglayer.Pending,
Metadata: aggsendertypes.NewCertificateMetadata(
certInfo.FromBlock,
certInfo.ToBlock,
uint64(certInfo.CreatedAt),
uint32(certInfo.FromBlock-certInfo.ToBlock),
certInfo.CreatedAt,
).ToHash(),
}
}
Expand Down
Loading

0 comments on commit e53a878

Please sign in to comment.