Skip to content

Commit

Permalink
fix: Various pessimistic proofs fixes and adaption to kurtosis-cdk
Browse files Browse the repository at this point in the history
…pessimistic proof branch (#165)

* fix: certificate with no importedBridges set '[]' instead of 'null'

* fix: certificate with no importedBridges set '[]' instead of 'null'

* feat: adapt to kurtosis-cdk pp

* feat: change para SaveCertificatesToFiles to SaveCertificatesToFilesPath

* fix: get candidate and proven certificates as well

* fix: remove test

* fix: small changes

* fix: db tx rollback

* fix: replace existing certificate

* fix: lint and coverage

* feat: check for nil fields in certificate

* feat: no claims test

* fix: comments

* fix: lint

* fix: shallow copy imported bridge exits and bridge exits

* fix: local_config for debug

* fix: cdk-erigon-node-001 rename to cdk-erigon-rpc-001

* feat: add logs to check cert

* feat: store hash as text, add logs

* fix: lint

* fix: bump kurtosis-cdk version to 0.2.18

* fix: comments

* fix: string conversion error on BridgeExit

* fix: lint

* fix: update minter key

* fix: e2e

* fix: e2e tests

---------

Co-authored-by: joanestebanr <[email protected]>
Co-authored-by: Victor Castell <[email protected]>
  • Loading branch information
3 people authored Nov 8, 2024
1 parent 61fe7f6 commit d4cf2db
Show file tree
Hide file tree
Showing 17 changed files with 746 additions and 169 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
with:
repository: 0xPolygon/kurtosis-cdk
path: "kurtosis-cdk"
ref: "v0.2.15"
ref: "v0.2.18"

- name: Setup Bats and bats libs
uses: bats-core/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-resequence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ jobs:
run: |
mkdir -p ci_logs
cd ci_logs
kurtosis service logs cdk-v1 cdk-erigon-node-001 --all > cdk-erigon-node-001.log
kurtosis service logs cdk-v1 cdk-erigon-rpc-001 --all > cdk-erigon-rpc-001.log
kurtosis service logs cdk-v1 cdk-erigon-sequencer-001 --all > cdk-erigon-sequencer-001.log
kurtosis service logs cdk-v1 zkevm-agglayer-001 --all > zkevm-agglayer-001.log
kurtosis service logs cdk-v1 zkevm-prover-001 --all > zkevm-prover-001.log
Expand Down
4 changes: 3 additions & 1 deletion agglayer/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ 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) {
response, err := rpc.JSONRPCCall(c.url, "interop_sendCertificate", certificate)
certificateToSend := certificate.CopyWithDefaulting()

response, err := rpc.JSONRPCCall(c.url, "interop_sendCertificate", certificateToSend)
if err != nil {
return common.Hash{}, err
}
Expand Down
127 changes: 127 additions & 0 deletions agglayer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,30 @@ type Certificate struct {
Metadata common.Hash `json:"metadata"`
}

func (c *Certificate) String() string {
res := fmt.Sprintf("NetworkID: %d, Height: %d, PrevLocalExitRoot: %s, NewLocalExitRoot: %s, Metadata: %s\n",
c.NetworkID, c.Height, common.Bytes2Hex(c.PrevLocalExitRoot[:]),
common.Bytes2Hex(c.NewLocalExitRoot[:]), common.Bytes2Hex(c.Metadata[:]))

if c.BridgeExits == nil {
res += " BridgeExits: nil\n"
} else {
for i, bridgeExit := range c.BridgeExits {
res += fmt.Sprintf(", BridgeExit[%d]: %s\n", i, bridgeExit.String())
}
}

if c.ImportedBridgeExits == nil {
res += " ImportedBridgeExits: nil\n"
} else {
for i, importedBridgeExit := range c.ImportedBridgeExits {
res += fmt.Sprintf(" ImportedBridgeExit[%d]: %s\n", i, importedBridgeExit.String())
}
}

return res
}

// Hash returns a hash that uniquely identifies the certificate
func (c *Certificate) Hash() common.Hash {
bridgeExitsHashes := make([][]byte, len(c.BridgeExits))
Expand Down Expand Up @@ -131,19 +155,54 @@ type SignedCertificate struct {
Signature *Signature `json:"signature"`
}

func (s *SignedCertificate) String() string {
return fmt.Sprintf("Certificate:%s,\nSignature: %s", s.Certificate.String(), s.Signature.String())
}

// CopyWithDefaulting returns a shallow copy of the signed certificate
func (s *SignedCertificate) CopyWithDefaulting() *SignedCertificate {
certificateCopy := *s.Certificate

if certificateCopy.BridgeExits == nil {
certificateCopy.BridgeExits = make([]*BridgeExit, 0)
}

if certificateCopy.ImportedBridgeExits == nil {
certificateCopy.ImportedBridgeExits = make([]*ImportedBridgeExit, 0)
}

signature := s.Signature
if signature == nil {
signature = &Signature{}
}

return &SignedCertificate{
Certificate: &certificateCopy,
Signature: signature,
}
}

// Signature is the data structure that will hold the signature of the given certificate
type Signature struct {
R common.Hash `json:"r"`
S common.Hash `json:"s"`
OddParity bool `json:"odd_y_parity"`
}

func (s *Signature) String() string {
return fmt.Sprintf("R: %s, S: %s, OddParity: %t", s.R.String(), s.S.String(), s.OddParity)
}

// TokenInfo encapsulates the information to uniquely identify a token on the origin network.
type TokenInfo struct {
OriginNetwork uint32 `json:"origin_network"`
OriginTokenAddress common.Address `json:"origin_token_address"`
}

func (t *TokenInfo) String() string {
return fmt.Sprintf("OriginNetwork: %d, OriginTokenAddress: %s", t.OriginNetwork, t.OriginTokenAddress.String())
}

// GlobalIndex represents the global index of an imported bridge exit
type GlobalIndex struct {
MainnetFlag bool `json:"mainnet_flag"`
Expand All @@ -159,6 +218,11 @@ func (g *GlobalIndex) Hash() common.Hash {
)
}

func (g *GlobalIndex) String() string {
return fmt.Sprintf("MainnetFlag: %t, RollupIndex: %d, LeafIndex: %d",
g.MainnetFlag, g.RollupIndex, g.LeafIndex)
}

// BridgeExit represents a token bridge exit
type BridgeExit struct {
LeafType LeafType `json:"leaf_type"`
Expand All @@ -169,6 +233,20 @@ type BridgeExit struct {
Metadata []byte `json:"metadata"`
}

func (b *BridgeExit) String() string {
res := fmt.Sprintf("LeafType: %s, DestinationNetwork: %d, DestinationAddress: %s, Amount: %s, Metadata: %s",
b.LeafType.String(), b.DestinationNetwork, b.DestinationAddress.String(),
b.Amount.String(), common.Bytes2Hex(b.Metadata))

if b.TokenInfo == nil {
res += ", TokenInfo: nil"
} else {
res += fmt.Sprintf(", TokenInfo: %s", b.TokenInfo.String())
}

return res
}

// Hash returns a hash that uniquely identifies the bridge exit
func (b *BridgeExit) Hash() common.Hash {
if b.Amount == nil {
Expand Down Expand Up @@ -252,6 +330,10 @@ func (m *MerkleProof) Hash() common.Hash {
)
}

func (m *MerkleProof) String() string {
return fmt.Sprintf("Root: %s, Proof: %v", m.Root.String(), m.Proof)
}

// L1InfoTreeLeafInner represents the inner part of the L1 info tree leaf
type L1InfoTreeLeafInner struct {
GlobalExitRoot common.Hash `json:"global_exit_root"`
Expand Down Expand Up @@ -281,6 +363,11 @@ func (l *L1InfoTreeLeafInner) MarshalJSON() ([]byte, error) {
})
}

func (l *L1InfoTreeLeafInner) String() string {
return fmt.Sprintf("GlobalExitRoot: %s, BlockHash: %s, Timestamp: %d",
l.GlobalExitRoot.String(), l.BlockHash.String(), l.Timestamp)
}

// L1InfoTreeLeaf represents the leaf of the L1 info tree
type L1InfoTreeLeaf struct {
L1InfoTreeIndex uint32 `json:"l1_info_tree_index"`
Expand All @@ -294,11 +381,21 @@ func (l *L1InfoTreeLeaf) Hash() common.Hash {
return l.Inner.Hash()
}

func (l *L1InfoTreeLeaf) String() string {
return fmt.Sprintf("L1InfoTreeIndex: %d, RollupExitRoot: %s, MainnetExitRoot: %s, Inner: %s",
l.L1InfoTreeIndex,
common.Bytes2Hex(l.RollupExitRoot[:]),
common.Bytes2Hex(l.MainnetExitRoot[:]),
l.Inner.String(),
)
}

// Claim is the interface that will be implemented by the different types of claims
type Claim interface {
Type() string
Hash() common.Hash
MarshalJSON() ([]byte, error)
String() string
}

// ClaimFromMainnnet represents a claim originating from the mainnet
Expand Down Expand Up @@ -335,6 +432,11 @@ func (c *ClaimFromMainnnet) Hash() common.Hash {
)
}

func (c *ClaimFromMainnnet) String() string {
return fmt.Sprintf("ProofLeafMER: %s, ProofGERToL1Root: %s, L1Leaf: %s",
c.ProofLeafMER.String(), c.ProofGERToL1Root.String(), c.L1Leaf.String())
}

// ClaimFromRollup represents a claim originating from a rollup
type ClaimFromRollup struct {
ProofLeafLER *MerkleProof `json:"proof_leaf_ler"`
Expand Down Expand Up @@ -372,13 +474,38 @@ func (c *ClaimFromRollup) Hash() common.Hash {
)
}

func (c *ClaimFromRollup) String() string {
return fmt.Sprintf("ProofLeafLER: %s, ProofLERToRER: %s, ProofGERToL1Root: %s, L1Leaf: %s",
c.ProofLeafLER.String(), c.ProofLERToRER.String(), c.ProofGERToL1Root.String(), c.L1Leaf.String())
}

// ImportedBridgeExit represents a token bridge exit originating on another network but claimed on the current network.
type ImportedBridgeExit struct {
BridgeExit *BridgeExit `json:"bridge_exit"`
ClaimData Claim `json:"claim_data"`
GlobalIndex *GlobalIndex `json:"global_index"`
}

func (c *ImportedBridgeExit) String() string {
var res string

if c.BridgeExit == nil {
res = "BridgeExit: nil"
} else {
res = fmt.Sprintf("BridgeExit: %s", c.BridgeExit.String())
}

if c.GlobalIndex == nil {
res += ", GlobalIndex: nil"
} else {
res += fmt.Sprintf(", GlobalIndex: %s", c.GlobalIndex.String())
}

res += fmt.Sprintf("ClaimData: %s", c.ClaimData.String())

return res
}

// Hash returns a hash that uniquely identifies the imported bridge exit
func (c *ImportedBridgeExit) Hash() common.Hash {
return crypto.Keccak256Hash(
Expand Down
88 changes: 88 additions & 0 deletions agglayer/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,91 @@ func TestMarshalJSON(t *testing.T) {
log.Info(string(data))
require.Equal(t, expectedSignedCertificateyMetadataJSON, string(data))
}

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

t.Run("copy with non-nil fields", func(t *testing.T) {
t.Parallel()

original := &SignedCertificate{
Certificate: &Certificate{
NetworkID: 1,
Height: 100,
PrevLocalExitRoot: [32]byte{0x01},
NewLocalExitRoot: [32]byte{0x02},
BridgeExits: []*BridgeExit{
{
LeafType: LeafTypeAsset,
TokenInfo: &TokenInfo{OriginNetwork: 1, OriginTokenAddress: common.HexToAddress("0x123")},
DestinationNetwork: 2,
DestinationAddress: common.HexToAddress("0x456"),
Amount: big.NewInt(1000),
Metadata: []byte{0x01, 0x02},
},
},
ImportedBridgeExits: []*ImportedBridgeExit{
{
BridgeExit: &BridgeExit{
LeafType: LeafTypeMessage,
TokenInfo: &TokenInfo{OriginNetwork: 1, OriginTokenAddress: common.HexToAddress("0x789")},
DestinationNetwork: 3,
DestinationAddress: common.HexToAddress("0xabc"),
Amount: big.NewInt(2000),
Metadata: []byte{0x03, 0x04},
},
ClaimData: &ClaimFromMainnnet{},
GlobalIndex: &GlobalIndex{MainnetFlag: true, RollupIndex: 1, LeafIndex: 2},
},
},
Metadata: common.HexToHash("0xdef"),
},
Signature: &Signature{
R: common.HexToHash("0x111"),
S: common.HexToHash("0x222"),
OddParity: true,
},
}

certificateCopy := original.CopyWithDefaulting()

require.NotNil(t, certificateCopy)
require.NotSame(t, original, certificateCopy)
require.NotSame(t, original.Certificate, certificateCopy.Certificate)
require.Same(t, original.Signature, certificateCopy.Signature)
require.Equal(t, original, certificateCopy)
})

t.Run("copy with nil BridgeExits, ImportedBridgeExits and Signature", func(t *testing.T) {
t.Parallel()

original := &SignedCertificate{
Certificate: &Certificate{
NetworkID: 1,
Height: 100,
PrevLocalExitRoot: [32]byte{0x01},
NewLocalExitRoot: [32]byte{0x02},
BridgeExits: nil,
ImportedBridgeExits: nil,
Metadata: common.HexToHash("0xdef"),
},
Signature: nil,
}

certificateCopy := original.CopyWithDefaulting()

require.NotNil(t, certificateCopy)
require.NotSame(t, original, certificateCopy)
require.NotSame(t, original.Certificate, certificateCopy.Certificate)
require.NotNil(t, certificateCopy.Signature)
require.Equal(t, original.NetworkID, certificateCopy.NetworkID)
require.Equal(t, original.Height, certificateCopy.Height)
require.Equal(t, original.PrevLocalExitRoot, certificateCopy.PrevLocalExitRoot)
require.Equal(t, original.NewLocalExitRoot, certificateCopy.NewLocalExitRoot)
require.Equal(t, original.Metadata, certificateCopy.Metadata)
require.NotNil(t, certificateCopy.BridgeExits)
require.NotNil(t, certificateCopy.ImportedBridgeExits)
require.Empty(t, certificateCopy.BridgeExits)
require.Empty(t, certificateCopy.ImportedBridgeExits)
})
}
Loading

0 comments on commit d4cf2db

Please sign in to comment.