From 0b191c55684efe772704a829eb4ca0e09638fa43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= <93934272+Stefan-Ethernal@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:17:15 +0100 Subject: [PATCH] feat: use the `GenericError` for all the errors originating from the agglayer (#227) * chore: update the versions.json * Remove PPError interface and use the error instead * Remove non-applicable test cases * Rename * test: increase UT coverage * test: certificate status unmarshal json * test: TestMerkleProofString * test: TestGlobalIndexString * test: move helper functions to a separate file * test: TestL1InfoTreeLeafString * test: TestClaimType * test: parallel execution, renames --- agglayer/client_test.go | 2 +- agglayer/errors_test.go | 45 -- agglayer/proof_generation_error.go | 657 ------------------ agglayer/proof_verification_error.go | 164 ----- .../errors_with_declared_computed_data.json | 45 -- .../errors_with_token_info.json | 29 - .../errors_without_inner_data.json | 38 - .../invalid_imported_bridge_exit_errors.json | 48 -- .../invalid_signer_error.json | 21 - .../random_unmarshal_errors.json | 12 - .../errors_with_inner_data.json | 22 - .../errors_without_inner_data.json | 6 - .../errors_with_declared_computed_data.json | 6 - .../errors_with_token_info.json | 26 - .../errors_without_inner_data.json | 6 - .../l1_info_root_incorrect_error.json | 11 - ...ullifier_path_generation_failed_error.json | 20 - agglayer/type_conversion_error.go | 306 -------- agglayer/types.go | 128 ++-- agglayer/types_helpers_test.go | 71 ++ agglayer/types_test.go | 559 ++++++++++++++- crates/cdk/versions.json | 12 +- 22 files changed, 699 insertions(+), 1535 deletions(-) delete mode 100644 agglayer/proof_generation_error.go delete mode 100644 agglayer/proof_verification_error.go delete mode 100644 agglayer/testdata/proof_generation_errors/errors_with_declared_computed_data.json delete mode 100644 agglayer/testdata/proof_generation_errors/errors_with_token_info.json delete mode 100644 agglayer/testdata/proof_generation_errors/errors_without_inner_data.json delete mode 100644 agglayer/testdata/proof_generation_errors/invalid_imported_bridge_exit_errors.json delete mode 100644 agglayer/testdata/proof_generation_errors/invalid_signer_error.json delete mode 100644 agglayer/testdata/proof_generation_errors/random_unmarshal_errors.json delete mode 100644 agglayer/testdata/proof_verification_errors/errors_with_inner_data.json delete mode 100644 agglayer/testdata/proof_verification_errors/errors_without_inner_data.json delete mode 100644 agglayer/testdata/type_conversion_errors/errors_with_declared_computed_data.json delete mode 100644 agglayer/testdata/type_conversion_errors/errors_with_token_info.json delete mode 100644 agglayer/testdata/type_conversion_errors/errors_without_inner_data.json delete mode 100644 agglayer/testdata/type_conversion_errors/l1_info_root_incorrect_error.json delete mode 100644 agglayer/testdata/type_conversion_errors/nullifier_path_generation_failed_error.json delete mode 100644 agglayer/type_conversion_error.go create mode 100644 agglayer/types_helpers_test.go diff --git a/agglayer/client_test.go b/agglayer/client_test.go index c4117eb8..91ec98c5 100644 --- a/agglayer/client_test.go +++ b/agglayer/client_test.go @@ -151,7 +151,7 @@ func TestGetLatestKnownCertificateHeaderWithPrevLERResponse(t *testing.T) { response := rpc.Response{ Result: []byte(`{"network_id":1,"height":0,"epoch_number":223,"certificate_index":0,"certificate_id":"0xf9179d2fbe535814b5a14496e2eed474f49c6131227a9dfc5d2d8caf9e212054","prev_local_exit_root":"0x27ae5ba08d7291c96c8cbddcc148bf48a6d68c7974b94356f53754ef6171d757","new_local_exit_root":"0x7ae06f4a5d0b6da7dd4973fb6ef40d82c9f2680899b3baaf9e564413b59cc160","metadata":"0x00000000000000000000000000000000000000000000000000000000000001a7","status":"Settled"}`), } - jSONRPCCall = func(url, method string, params ...interface{}) (rpc.Response, error) { + jSONRPCCall = func(_, _ string, _ ...interface{}) (rpc.Response, error) { return response, nil } cert, err := sut.GetLatestKnownCertificateHeader(1) diff --git a/agglayer/errors_test.go b/agglayer/errors_test.go index 3ca7b7ed..14293026 100644 --- a/agglayer/errors_test.go +++ b/agglayer/errors_test.go @@ -1,56 +1,11 @@ package agglayer import ( - "encoding/json" - "fmt" - "os" - "path/filepath" "testing" "github.com/stretchr/testify/require" ) -func TestErrorVectors(t *testing.T) { - t.Parallel() - - type testCase struct { - TestName string `json:"test_name"` - ExpectedError string `json:"expected_error"` - CertificateHeaderJSON string `json:"certificate_header"` - } - - files, err := filepath.Glob("testdata/*/*.json") - require.NoError(t, err) - - for _, file := range files { - file := file - - t.Run(file, func(t *testing.T) { - t.Parallel() - - data, err := os.ReadFile(file) - require.NoError(t, err) - - var testCases []*testCase - - require.NoError(t, json.Unmarshal(data, &testCases)) - - for _, tc := range testCases { - certificateHeader := &CertificateHeader{} - err = json.Unmarshal([]byte(tc.CertificateHeaderJSON), certificateHeader) - - if tc.ExpectedError == "" { - require.NoError(t, err, "Test: %s not expected any unmarshal error, but got: %v", tc.TestName, err) - require.NotNil(t, certificateHeader.Error, "Test: %s unpacked error is nil", tc.TestName) - fmt.Println(certificateHeader.Error.String()) - } else { - require.ErrorContains(t, err, tc.ExpectedError, "Test: %s expected error: %s. Got: %v", tc.TestName, tc.ExpectedError, err) - } - } - }) - } -} - func TestConvertMapValue_String(t *testing.T) { t.Parallel() diff --git a/agglayer/proof_generation_error.go b/agglayer/proof_generation_error.go deleted file mode 100644 index fa7012f7..00000000 --- a/agglayer/proof_generation_error.go +++ /dev/null @@ -1,657 +0,0 @@ -package agglayer - -import ( - "errors" - "fmt" - "reflect" - - "github.com/ethereum/go-ethereum/common" -) - -var errNotMap = errors.New("inner error is not a map") - -const ( - InvalidSignerErrorType = "InvalidSigner" - InvalidPreviousLERErrorType = "InvalidPreviousLocalExitRoot" - InvalidPreviousBalanceRootErrorType = "InvalidPreviousBalanceRoot" - InvalidPreviousNullifierRootErrorType = "InvalidPreviousNullifierRoot" - InvalidNewLocalExitRootErrorType = "InvalidNewLocalExitRoot" - InvalidNewBalanceRootErrorType = "InvalidNewBalanceRoot" - InvalidNewNullifierRootErrorType = "InvalidNewNullifierRoot" - InvalidImportedExitsRootErrorType = "InvalidImportedExitsRoot" - MismatchImportedExitsRootErrorType = "MismatchImportedExitsRoot" - InvalidNullifierPathErrorType = "InvalidNullifierPath" - InvalidBalancePathErrorType = "InvalidBalancePath" - BalanceOverflowInBridgeExitErrorType = "BalanceOverflowInBridgeExit" - BalanceUnderflowInBridgeExitErrorType = "BalanceUnderflowInBridgeExit" - CannotExitToSameNetworkErrorType = "CannotExitToSameNetwork" - InvalidMessageOriginNetworkErrorType = "InvalidMessageOriginNetwork" - InvalidL1TokenInfoErrorType = "InvalidL1TokenInfo" - MissingTokenBalanceProofErrorType = "MissingTokenBalanceProof" - DuplicateTokenBalanceProofErrorType = "DuplicateTokenBalanceProof" - InvalidSignatureErrorType = "InvalidSignature" - InvalidImportedBridgeExitErrorType = "InvalidImportedBridgeExit" - UnknownErrorType = "UnknownError" -) - -type PPError interface { - String() string -} - -// ProofGenerationError is a struct that represents an error that occurs when generating a proof. -type ProofGenerationError struct { - GenerationType string - InnerErrors []PPError -} - -// String is the implementation of the Error interface -func (p *ProofGenerationError) String() string { - return fmt.Sprintf("Proof generation error: %s. %s", p.GenerationType, p.InnerErrors) -} - -// Unmarshal unmarshals the data from a map into a ProofGenerationError struct. -func (p *ProofGenerationError) Unmarshal(data interface{}) error { - dataMap, ok := data.(map[string]interface{}) - if !ok { - return errNotMap - } - - generationType, err := convertMapValue[string](dataMap, "generation_type") - if err != nil { - return err - } - - p.GenerationType = generationType - - getPPErrFn := func(key string, value interface{}) (PPError, error) { - switch key { - case InvalidSignerErrorType: - invalidSigner := &InvalidSignerError{} - if err := invalidSigner.UnmarshalFromMap(value); err != nil { - return nil, err - } - return invalidSigner, nil - case InvalidPreviousLERErrorType: - invalidPreviousLER := NewInvalidPreviousLocalExitRoot() - if err := invalidPreviousLER.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidPreviousLER) - case InvalidPreviousBalanceRootErrorType: - invalidPreviousBalanceRoot := NewInvalidPreviousBalanceRoot() - if err := invalidPreviousBalanceRoot.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidPreviousBalanceRoot) - case InvalidPreviousNullifierRootErrorType: - invalidPreviousNullifierRoot := NewInvalidPreviousNullifierRoot() - if err := invalidPreviousNullifierRoot.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidPreviousNullifierRoot) - case InvalidNewLocalExitRootErrorType: - invalidNewLocalExitRoot := NewInvalidNewLocalExitRoot() - if err := invalidNewLocalExitRoot.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidNewLocalExitRoot) - case InvalidNewBalanceRootErrorType: - invalidNewBalanceRoot := NewInvalidNewBalanceRoot() - if err := invalidNewBalanceRoot.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidNewBalanceRoot) - case InvalidNewNullifierRootErrorType: - invalidNewNullifierRoot := NewInvalidNewNullifierRoot() - if err := invalidNewNullifierRoot.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidNewNullifierRoot) - case InvalidImportedExitsRootErrorType: - invalidImportedExitsRoot := NewInvalidImportedExitsRoot() - if err := invalidImportedExitsRoot.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidImportedExitsRoot) - case MismatchImportedExitsRootErrorType: - p.InnerErrors = append(p.InnerErrors, &MismatchImportedExitsRoot{}) - case InvalidNullifierPathErrorType: - p.InnerErrors = append(p.InnerErrors, &InvalidNullifierPath{}) - case InvalidBalancePathErrorType: - p.InnerErrors = append(p.InnerErrors, &InvalidBalancePath{}) - case BalanceOverflowInBridgeExitErrorType: - p.InnerErrors = append(p.InnerErrors, &BalanceOverflowInBridgeExit{}) - case BalanceUnderflowInBridgeExitErrorType: - p.InnerErrors = append(p.InnerErrors, &BalanceUnderflowInBridgeExit{}) - case CannotExitToSameNetworkErrorType: - p.InnerErrors = append(p.InnerErrors, &CannotExitToSameNetwork{}) - case InvalidMessageOriginNetworkErrorType: - p.InnerErrors = append(p.InnerErrors, &InvalidMessageOriginNetwork{}) - case InvalidL1TokenInfoErrorType: - invalidL1TokenInfo := NewInvalidL1TokenInfo() - if err := invalidL1TokenInfo.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidL1TokenInfo) - case MissingTokenBalanceProofErrorType: - missingTokenBalanceProof := NewMissingTokenBalanceProof() - if err := missingTokenBalanceProof.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, missingTokenBalanceProof) - case DuplicateTokenBalanceProofErrorType: - duplicateTokenBalanceProof := NewDuplicateTokenBalanceProof() - if err := duplicateTokenBalanceProof.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, duplicateTokenBalanceProof) - case InvalidSignatureErrorType: - p.InnerErrors = append(p.InnerErrors, &InvalidSignature{}) - case InvalidImportedBridgeExitErrorType: - invalidImportedBridgeExit := &InvalidImportedBridgeExit{} - if err := invalidImportedBridgeExit.UnmarshalFromMap(value); err != nil { - return nil, err - } - p.InnerErrors = append(p.InnerErrors, invalidImportedBridgeExit) - case UnknownErrorType: - p.InnerErrors = append(p.InnerErrors, &UnknownError{}) - default: - return nil, fmt.Errorf("unknown proof generation error type: %s", key) - } - - return nil, nil - } - - errorSourceMap, err := convertMapValue[map[string]interface{}](dataMap, "source") - if err != nil { - // it can be a single error - errSourceString, err := convertMapValue[string](dataMap, "source") - if err != nil { - return err - } - - ppErr, err := getPPErrFn(errSourceString, nil) - if err != nil { - return err - } - - if ppErr != nil { - p.InnerErrors = append(p.InnerErrors, ppErr) - } - - return nil - } - - // there will always be only one key in the source map - for key, value := range errorSourceMap { - ppErr, err := getPPErrFn(key, value) - if err != nil { - return err - } - - if ppErr != nil { - p.InnerErrors = append(p.InnerErrors, ppErr) - } - } - - return nil -} - -// InvalidSignerError is a struct that represents an error that occurs when -// the signer of the certificate is invalid, or the hash that was signed was not valid. -type InvalidSignerError struct { - Declared common.Address `json:"declared"` - Recovered common.Address `json:"recovered"` -} - -// String is the implementation of the Error interface -func (e *InvalidSignerError) String() string { - return fmt.Sprintf("%s. Declared: %s, Computed: %s", - InvalidSignerErrorType, e.Declared.String(), e.Recovered.String()) -} - -func (e *InvalidSignerError) UnmarshalFromMap(data interface{}) error { - dataMap, ok := data.(map[string]interface{}) - if !ok { - return errNotMap - } - - declared, err := convertMapValue[string](dataMap, "declared") - if err != nil { - return err - } - - recovered, err := convertMapValue[string](dataMap, "recovered") - if err != nil { - return err - } - - e.Declared = common.HexToAddress(declared) - e.Recovered = common.HexToAddress(recovered) - - return nil -} - -// DeclaredComputedError is a base struct for errors that have both declared and computed values. -type DeclaredComputedError struct { - Declared common.Hash `json:"declared"` - Computed common.Hash `json:"computed"` - ErrType string -} - -// String is the implementation of the Error interface -func (e *DeclaredComputedError) String() string { - return fmt.Sprintf("%s. Declared: %s, Computed: %s", - e.ErrType, e.Declared.String(), e.Computed.String()) -} - -// UnmarshalFromMap is the implementation of the Error interface -func (e *DeclaredComputedError) UnmarshalFromMap(data interface{}) error { - dataMap, ok := data.(map[string]interface{}) - if !ok { - return errNotMap - } - - declared, err := convertMapValue[string](dataMap, "declared") - if err != nil { - return err - } - - computed, err := convertMapValue[string](dataMap, "computed") - if err != nil { - return err - } - - e.Declared = common.HexToHash(declared) - e.Computed = common.HexToHash(computed) - - return nil -} - -// InvalidPreviousLocalExitRoot is a struct that represents an error that occurs when -// the previous local exit root is invalid. -type InvalidPreviousLocalExitRoot struct { - *DeclaredComputedError -} - -func NewInvalidPreviousLocalExitRoot() *InvalidPreviousLocalExitRoot { - return &InvalidPreviousLocalExitRoot{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidPreviousLERErrorType}, - } -} - -// InvalidPreviousBalanceRoot is a struct that represents an error that occurs when -// the previous balance root is invalid. -type InvalidPreviousBalanceRoot struct { - *DeclaredComputedError -} - -func NewInvalidPreviousBalanceRoot() *InvalidPreviousBalanceRoot { - return &InvalidPreviousBalanceRoot{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidPreviousBalanceRootErrorType}, - } -} - -// InvalidPreviousNullifierRoot is a struct that represents an error that occurs when -// the previous nullifier root is invalid. -type InvalidPreviousNullifierRoot struct { - *DeclaredComputedError -} - -func NewInvalidPreviousNullifierRoot() *InvalidPreviousNullifierRoot { - return &InvalidPreviousNullifierRoot{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidPreviousNullifierRootErrorType}, - } -} - -// InvalidNewLocalExitRoot is a struct that represents an error that occurs when -// the new local exit root is invalid. -type InvalidNewLocalExitRoot struct { - *DeclaredComputedError -} - -func NewInvalidNewLocalExitRoot() *InvalidNewLocalExitRoot { - return &InvalidNewLocalExitRoot{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidNewLocalExitRootErrorType}, - } -} - -// InvalidNewBalanceRoot is a struct that represents an error that occurs when -// the new balance root is invalid. -type InvalidNewBalanceRoot struct { - *DeclaredComputedError -} - -func NewInvalidNewBalanceRoot() *InvalidNewBalanceRoot { - return &InvalidNewBalanceRoot{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidNewBalanceRootErrorType}, - } -} - -// InvalidNewNullifierRoot is a struct that represents an error that occurs when -// the new nullifier root is invalid. -type InvalidNewNullifierRoot struct { - *DeclaredComputedError -} - -func NewInvalidNewNullifierRoot() *InvalidNewNullifierRoot { - return &InvalidNewNullifierRoot{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidNewNullifierRootErrorType}, - } -} - -// InvalidImportedExitsRoot is a struct that represents an error that occurs when -// the imported exits root is invalid. -type InvalidImportedExitsRoot struct { - *DeclaredComputedError -} - -func NewInvalidImportedExitsRoot() *InvalidImportedExitsRoot { - return &InvalidImportedExitsRoot{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidImportedExitsRootErrorType}, - } -} - -// MismatchImportedExitsRoot is a struct that represents an error that occurs when -// the commitment to the list of imported bridge exits but the list of imported bridge exits is empty. -type MismatchImportedExitsRoot struct{} - -// String is the implementation of the Error interface -func (e *MismatchImportedExitsRoot) String() string { - return fmt.Sprintf(`%s: The commitment to the list of imported bridge exits - should be Some if and only if this list is non-empty, should be None otherwise.`, - MismatchImportedExitsRootErrorType) -} - -// InvalidNullifierPath is a struct that represents an error that occurs when -// the provided nullifier path is invalid. -type InvalidNullifierPath struct{} - -// String is the implementation of the Error interface -func (e *InvalidNullifierPath) String() string { - return fmt.Sprintf("%s: The provided nullifier path is invalid", InvalidNullifierPathErrorType) -} - -// InvalidBalancePath is a struct that represents an error that occurs when -// the provided balance path is invalid. -type InvalidBalancePath struct{} - -// String is the implementation of the Error interface -func (e *InvalidBalancePath) String() string { - return fmt.Sprintf("%s: The provided balance path is invalid", InvalidBalancePathErrorType) -} - -// BalanceOverflowInBridgeExit is a struct that represents an error that occurs when -// bridge exit led to balance overflow. -type BalanceOverflowInBridgeExit struct{} - -// String is the implementation of the Error interface -func (e *BalanceOverflowInBridgeExit) String() string { - return fmt.Sprintf("%s: The imported bridge exit led to balance overflow.", BalanceOverflowInBridgeExitErrorType) -} - -// BalanceUnderflowInBridgeExit is a struct that represents an error that occurs when -// bridge exit led to balance underflow. -type BalanceUnderflowInBridgeExit struct{} - -// String is the implementation of the Error interface -func (e *BalanceUnderflowInBridgeExit) String() string { - return fmt.Sprintf("%s: The imported bridge exit led to balance underflow.", BalanceUnderflowInBridgeExitErrorType) -} - -// CannotExitToSameNetwork is a struct that represents an error that occurs when -// the user tries to exit to the same network. -type CannotExitToSameNetwork struct{} - -// String is the implementation of the Error interface -func (e *CannotExitToSameNetwork) String() string { - return fmt.Sprintf("%s: The provided bridge exit goes to the sender’s own network which is not permitted.", - CannotExitToSameNetworkErrorType) -} - -// InvalidMessageOriginNetwork is a struct that represents an error that occurs when -// the origin network of the message is invalid. -type InvalidMessageOriginNetwork struct{} - -// String is the implementation of the Error interface -func (e *InvalidMessageOriginNetwork) String() string { - return fmt.Sprintf("%s: The origin network of the message is invalid.", InvalidMessageOriginNetworkErrorType) -} - -// TokenInfoError is a struct inherited by other errors that have a TokenInfo field. -type TokenInfoError struct { - TokenInfo *TokenInfo `json:"token_info"` - isNested bool -} - -func (e *TokenInfoError) UnmarshalFromMap(data interface{}) error { - dataMap, ok := data.(map[string]interface{}) - if !ok { - return errNotMap - } - - var ( - err error - tokenInfoMap map[string]interface{} - ) - - if e.isNested { - tokenInfoMap, err = convertMapValue[map[string]interface{}](dataMap, "TokenInfo") - if err != nil { - return err - } - } else { - tokenInfoMap = dataMap - } - - originNetwork, err := convertMapValue[uint32](tokenInfoMap, "origin_network") - if err != nil { - return err - } - - originAddress, err := convertMapValue[string](tokenInfoMap, "origin_token_address") - if err != nil { - return err - } - - e.TokenInfo = &TokenInfo{ - OriginNetwork: originNetwork, - OriginTokenAddress: common.HexToAddress(originAddress), - } - - return nil -} - -// InvalidL1TokenInfo is a struct that represents an error that occurs when -// the L1 token info is invalid. -type InvalidL1TokenInfo struct { - *TokenInfoError -} - -// NewInvalidL1TokenInfo returns a new instance of InvalidL1TokenInfo. -func NewInvalidL1TokenInfo() *InvalidL1TokenInfo { - return &InvalidL1TokenInfo{ - TokenInfoError: &TokenInfoError{isNested: true}, - } -} - -// String is the implementation of the Error interface -func (e *InvalidL1TokenInfo) String() string { - return fmt.Sprintf("%s: The L1 token info is invalid. %s", - InvalidL1TokenInfoErrorType, e.TokenInfo.String()) -} - -// MissingTokenBalanceProof is a struct that represents an error that occurs when -// the token balance proof is missing. -type MissingTokenBalanceProof struct { - *TokenInfoError -} - -// NewMissingTokenBalanceProof returns a new instance of MissingTokenBalanceProof. -func NewMissingTokenBalanceProof() *MissingTokenBalanceProof { - return &MissingTokenBalanceProof{ - TokenInfoError: &TokenInfoError{isNested: true}, - } -} - -// String is the implementation of the Error interface -func (e *MissingTokenBalanceProof) String() string { - return fmt.Sprintf("%s: The provided token is missing a balance proof. %s", - MissingTokenBalanceProofErrorType, e.TokenInfo.String()) -} - -// DuplicateTokenBalanceProof is a struct that represents an error that occurs when -// the token balance proof is duplicated. -type DuplicateTokenBalanceProof struct { - *TokenInfoError -} - -// NewDuplicateTokenBalanceProof returns a new instance of DuplicateTokenBalanceProof. -func NewDuplicateTokenBalanceProof() *DuplicateTokenBalanceProof { - return &DuplicateTokenBalanceProof{ - TokenInfoError: &TokenInfoError{isNested: true}, - } -} - -// String is the implementation of the Error interface -func (e *DuplicateTokenBalanceProof) String() string { - return fmt.Sprintf("%s: The provided token comes with multiple balance proofs. %s", - DuplicateTokenBalanceProofErrorType, e.TokenInfo.String()) -} - -// InvalidSignature is a struct that represents an error that occurs when -// the signature is invalid. -type InvalidSignature struct{} - -// String is the implementation of the Error interface -func (e *InvalidSignature) String() string { - return fmt.Sprintf("%s: The provided signature is invalid.", InvalidSignatureErrorType) -} - -// UnknownError is a struct that represents an error that occurs when -// an unknown error is encountered. -type UnknownError struct{} - -// String is the implementation of the Error interface -func (e *UnknownError) String() string { - return fmt.Sprintf("%s: An unknown error occurred.", UnknownErrorType) -} - -// InvalidImportedBridgeExit is a struct that represents an error that occurs when -// the imported bridge exit is invalid. -type InvalidImportedBridgeExit struct { - GlobalIndex *GlobalIndex `json:"global_index"` - ErrorType string `json:"error_type"` -} - -// String is the implementation of the Error interface -func (e *InvalidImportedBridgeExit) String() string { - var errorDescription string - switch e.ErrorType { - case "MismatchGlobalIndexInclusionProof": - errorDescription = "The global index and the inclusion proof do not both correspond " + - "to the same network type: mainnet or rollup." - case "MismatchL1Root": - errorDescription = "The provided L1 info root does not match the one provided in the inclusion proof." - case "MismatchMER": - errorDescription = "The provided MER does not match the one provided in the inclusion proof." - case "MismatchRER": - errorDescription = "The provided RER does not match the one provided in the inclusion proof." - case "InvalidMerklePathLeafToLER": - errorDescription = "The inclusion proof from the leaf to the LER is invalid." - case "InvalidMerklePathLERToRER": - errorDescription = "The inclusion proof from the LER to the RER is invalid." - case "InvalidMerklePathGERToL1Root": - errorDescription = "The inclusion proof from the GER to the L1 info Root is invalid." - case "InvalidExitNetwork": - errorDescription = "The provided imported bridge exit does not target the right destination network." - default: - errorDescription = "An unknown error occurred." - } - - return fmt.Sprintf("%s: Global index: %s. Error type: %s. %s", - InvalidImportedBridgeExitErrorType, e.GlobalIndex.String(), e.ErrorType, errorDescription) -} - -func (e *InvalidImportedBridgeExit) UnmarshalFromMap(data interface{}) error { - dataMap, ok := data.(map[string]interface{}) - if !ok { - return errNotMap - } - - sourceErr, err := convertMapValue[string](dataMap, "source") - if err != nil { - return err - } - - e.ErrorType = sourceErr - - globalIndexMap, err := convertMapValue[map[string]interface{}](dataMap, "global_index") - if err != nil { - return err - } - - e.GlobalIndex = &GlobalIndex{} - return e.GlobalIndex.UnmarshalFromMap(globalIndexMap) -} - -// convertMapValue converts the value of a key in a map to a target type. -func convertMapValue[T any](data map[string]interface{}, key string) (T, error) { - value, ok := data[key] - if !ok { - var zero T - return zero, fmt.Errorf("key %s not found in map", key) - } - - // Try a direct type assertion - if convertedValue, ok := value.(T); ok { - return convertedValue, nil - } - - // If direct assertion fails, handle numeric type conversions - var target T - targetType := reflect.TypeOf(target) - - // Check if value is a float64 (default JSON number type) and target is a numeric type - if floatValue, ok := value.(float64); ok && targetType.Kind() >= reflect.Int && targetType.Kind() <= reflect.Uint64 { - convertedValue, err := convertNumeric(floatValue, targetType) - if err != nil { - return target, fmt.Errorf("conversion error for key %s: %w", key, err) - } - return convertedValue.(T), nil //nolint:forcetypeassert - } - - return target, fmt.Errorf("value of key %s is not of type %T", key, target) -} - -// convertNumeric converts a float64 to the specified numeric type. -func convertNumeric(value float64, targetType reflect.Type) (interface{}, error) { - switch targetType.Kind() { - case reflect.Int: - return int(value), nil - case reflect.Int8: - return int8(value), nil - case reflect.Int16: - return int16(value), nil - case reflect.Int32: - return int32(value), nil - case reflect.Int64: - return int64(value), nil - case reflect.Uint: - return uint(value), nil - case reflect.Uint8: - return uint8(value), nil - case reflect.Uint16: - return uint16(value), nil - case reflect.Uint32: - return uint32(value), nil - case reflect.Uint64: - return uint64(value), nil - case reflect.Float32: - return float32(value), nil - case reflect.Float64: - return value, nil - default: - return nil, errors.New("unsupported target type") - } -} diff --git a/agglayer/proof_verification_error.go b/agglayer/proof_verification_error.go deleted file mode 100644 index dd5c5f74..00000000 --- a/agglayer/proof_verification_error.go +++ /dev/null @@ -1,164 +0,0 @@ -package agglayer - -import "fmt" - -const ( - VersionMismatchErrorType = "VersionMismatch" - CoreErrorType = "Core" - RecursionErrorType = "Recursion" - PlankErrorType = "Plank" - Groth16ErrorType = "Groth16" - InvalidPublicValuesErrorType = "InvalidPublicValues" -) - -// ProofVerificationError is an error that is returned when verifying a proof -type ProofVerificationError struct { - InnerErrors []PPError -} - -// String is the implementation of the Error interface -func (p *ProofVerificationError) String() string { - return fmt.Sprintf("Proof verification error: %v", p.InnerErrors) -} - -// Unmarshal unmarshals the data from a map into a ProofVerificationError struct. -func (p *ProofVerificationError) Unmarshal(data interface{}) error { - getPPErrFn := func(key string, value interface{}) (PPError, error) { - switch key { - case VersionMismatchErrorType: - versionMismatch := &VersionMismatch{} - if err := versionMismatch.Unmarshal(value); err != nil { - return nil, err - } - return versionMismatch, nil - case CoreErrorType: - core := &Core{} - if err := core.Unmarshal(value); err != nil { - return nil, err - } - return core, nil - case RecursionErrorType: - recursion := &Recursion{} - if err := recursion.Unmarshal(value); err != nil { - return nil, err - } - return recursion, nil - case PlankErrorType: - plank := &Plank{} - if err := plank.Unmarshal(value); err != nil { - return nil, err - } - return plank, nil - case Groth16ErrorType: - groth16 := &Groth16{} - if err := groth16.Unmarshal(value); err != nil { - return nil, err - } - return groth16, nil - case InvalidPublicValuesErrorType: - return &InvalidPublicValues{}, nil - default: - return nil, fmt.Errorf("unknown proof verification error type: %v", key) - } - } - - getAndAddInnerErrorFn := func(key string, value interface{}) error { - ppErr, err := getPPErrFn(key, value) - if err != nil { - return err - } - - if ppErr != nil { - p.InnerErrors = append(p.InnerErrors, ppErr) - } - - return nil - } - - dataMap, ok := data.(map[string]interface{}) - if !ok { - // it can be a single error - return getAndAddInnerErrorFn(data.(string), nil) //nolint:forcetypeassert - } - - for key, value := range dataMap { - if err := getAndAddInnerErrorFn(key, value); err != nil { - return err - } - } - - return nil -} - -// StringError is an error that is inherited by other errors that expect a string -// field in the data. -type StringError string - -// Unmarshal unmarshals the data from an interface{} into a StringError. -func (e *StringError) Unmarshal(data interface{}) error { - str, ok := data.(string) - if !ok { - return fmt.Errorf("expected string for StringError, got %T", data) - } - *e = StringError(str) - return nil -} - -// VersionMismatch is an error that is returned when the version of the proof is -// different from the version of the core. -type VersionMismatch struct { - StringError -} - -// String is the implementation of the Error interface -func (e *VersionMismatch) String() string { - return fmt.Sprintf("%s: %s", VersionMismatchErrorType, e.StringError) -} - -// Core is an error that is returned when the core machine verification fails. -type Core struct { - StringError -} - -// String is the implementation of the Error interface -func (e *Core) String() string { - return fmt.Sprintf("%s: Core machine verification error: %s", CoreErrorType, e.StringError) -} - -// Recursion is an error that is returned when the recursion verification fails. -type Recursion struct { - StringError -} - -// String is the implementation of the Error interface -func (e *Recursion) String() string { - return fmt.Sprintf("%s: Recursion verification error: %s", RecursionErrorType, e.StringError) -} - -// Plank is an error that is returned when the plank verification fails. -type Plank struct { - StringError -} - -// String is the implementation of the Error interface -func (e *Plank) String() string { - return fmt.Sprintf("%s: Plank verification error: %s", PlankErrorType, e.StringError) -} - -// Groth16 is an error that is returned when the Groth16 verification fails. -type Groth16 struct { - StringError -} - -// String is the implementation of the Error interface -func (e *Groth16) String() string { - return fmt.Sprintf("%s: Groth16 verification error: %s", Groth16ErrorType, e.StringError) -} - -// InvalidPublicValues is an error that is returned when the public values are invalid. -type InvalidPublicValues struct{} - -// String is the implementation of the Error interface -func (e *InvalidPublicValues) String() string { - return fmt.Sprintf("%s: Invalid public values", InvalidPublicValuesErrorType) -} diff --git a/agglayer/testdata/proof_generation_errors/errors_with_declared_computed_data.json b/agglayer/testdata/proof_generation_errors/errors_with_declared_computed_data.json deleted file mode 100644 index 4b1b4029..00000000 --- a/agglayer/testdata/proof_generation_errors/errors_with_declared_computed_data.json +++ /dev/null @@ -1,45 +0,0 @@ -[ - { - "test_name": "InvalidImportedExitsRoot", - "certificate_header": "{\"network_id\":14,\"height\":1,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedExitsRoot\":{\"declared\":\"0x1116837a43bdc3dd9f114558daf4b26ed4eeeeec\",\"computed\":\"0x20222bfbb55589f7fd0bec3666e3de469111ce3c\"}}}}}}}" - }, - { - "test_name": "InvalidNewBalanceRoot", - "certificate_header": "{\"network_id\":11,\"height\":31,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidNewBalanceRoot\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed4eeeeec\",\"computed\":\"0x20e92bfbb55589f7fd0bec3666e3de469111ce3c\"}}}}}}}" - }, - { - "test_name": "InvalidNewLocalExitRoot", - "certificate_header": "{\"network_id\":3,\"height\":22,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidNewLocalExitRoot\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed49831ec\",\"computed\":\"0x20e92bfbb55589f7fd0bec3666e3de469525ce3c\"}}}}}}}" - }, - { - "test_name": "InvalidNewNullifierRoot", - "certificate_header": "{\"network_id\":2,\"height\":12,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidNewNullifierRoot\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed4ccceec\",\"computed\":\"0x20e92bfbb55589f7fd0bec3666e3de222111ce3c\"}}}}}}}" - }, - { - "test_name": "InvalidPreviousBalanceRoot", - "certificate_header": "{\"network_id\":2,\"height\":11,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidPreviousBalanceRoot\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed49842ec\",\"computed\":\"0x20e92bfbb55589f7fd0bec3666e3de469526de3c\"}}}}}}}" - }, - { - "test_name": "InvalidPreviousLocalExitRoot", - "certificate_header": "{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidPreviousLocalExitRoot\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed49842ed\",\"computed\":\"0x20e92bfbb55589f7fd0bec3666e3de469526de3e\"}}}}}}}" - }, - { - "test_name": "InvalidPreviousNullifierRoot", - "certificate_header": "{\"network_id\":21,\"height\":111,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidPreviousNullifierRoot\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed49842ee\",\"computed\":\"0x20e92bfbb55589f7fd0bec3666e3de469526de3e\"}}}}}}}" - }, - { - "test_name": "InvalidPreviousNullifierRoot_missing_declared", - "expected_error": "key declared not found in map", - "certificate_header": "{\"network_id\":21,\"height\":111,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidPreviousNullifierRoot\":{\"computed\":\"0x20e92bfbb55589f7fd0bec3666e3de469526de3e\"}}}}}}}" - }, - { - "test_name": "InvalidPreviousNullifierRoot_missing_computed", - "expected_error": "key computed not found in map", - "certificate_header": "{\"network_id\":21,\"height\":111,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidPreviousNullifierRoot\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed49842ee\"}}}}}}}" - }, - { - "test_name": "InvalidPreviousNullifierRoot_missing_inner_error", - "expected_error": "not a map", - "certificate_header": "{\"network_id\":21,\"height\":111,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"InvalidPreviousNullifierRoot\"}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/proof_generation_errors/errors_with_token_info.json b/agglayer/testdata/proof_generation_errors/errors_with_token_info.json deleted file mode 100644 index 6884676a..00000000 --- a/agglayer/testdata/proof_generation_errors/errors_with_token_info.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "test_name": "InvalidL1TokenInfo", - "certificate_header":"{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidL1TokenInfo\":{\"TokenInfo\":{\"origin_network\":1,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}}}" - }, - { - "test_name": "MissingTokenBalanceProof", - "certificate_header": "{\"network_id\":2111,\"height\":1,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"MissingTokenBalanceProof\":{\"TokenInfo\":{\"origin_network\":2111,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}}}" - }, - { - "test_name": "DuplicateTokenBalanceProof", - "certificate_header": "{\"network_id\":100000000,\"height\":18446744073709551615,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"DuplicateTokenBalanceProof\":{\"TokenInfo\":{\"origin_network\":10000000000,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}}}" - }, - { - "test_name": "DuplicateTokenBalanceProof_missing_token_info", - "expected_error": "key TokenInfo not found in map", - "certificate_header": "{\"network_id\":100000000,\"height\":18446744073709551615,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"DuplicateTokenBalanceProof\":{}}}}}}}" - }, - { - "test_name": "DuplicateTokenBalanceProof_missing_origin_network", - "expected_error": "key origin_network not found in map", - "certificate_header": "{\"network_id\":100000000,\"height\":18446744073709551615,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"DuplicateTokenBalanceProof\":{\"TokenInfo\":{\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}}}" - }, - { - "test_name": "DuplicateTokenBalanceProof_missing_origin_token_address", - "expected_error": "key origin_token_address not found in map", - "certificate_header": "{\"network_id\":100000000,\"height\":18446744073709551615,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"DuplicateTokenBalanceProof\":{\"TokenInfo\":{\"origin_network\":10000000000}}}}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/proof_generation_errors/errors_without_inner_data.json b/agglayer/testdata/proof_generation_errors/errors_without_inner_data.json deleted file mode 100644 index 87946f16..00000000 --- a/agglayer/testdata/proof_generation_errors/errors_without_inner_data.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "test_name": "MismatchImportedExitsRoot", - "certificate_header": "{\"network_id\":14,\"height\":1,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"MismatchImportedExitsRoot\"}}}}}" - }, - { - "test_name": "InvalidNullifierPath", - "certificate_header": "{\"network_id\":15,\"height\":2,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"InvalidNullifierPath\"}}}}}" - }, - { - "test_name": "InvalidBalancePath", - "certificate_header": "{\"network_id\":16,\"height\":3,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"InvalidBalancePath\"}}}}}" - }, - { - "test_name": "BalanceOverflowInBridgeExit", - "certificate_header": "{\"network_id\":17,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"BalanceOverflowInBridgeExit\"}}}}}" - }, - { - "test_name": "BalanceUnderflowInBridgeExit", - "certificate_header": "{\"network_id\":18,\"height\":5,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"BalanceUnderflowInBridgeExit\"}}}}}" - }, - { - "test_name": "CannotExitToSameNetwork", - "certificate_header": "{\"network_id\":19,\"height\":6,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"CannotExitToSameNetwork\"}}}}}" - }, - { - "test_name": "InvalidMessageOriginNetwork", - "certificate_header": "{\"network_id\":20,\"height\":7,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"InvalidMessageOriginNetwork\"}}}}}" - }, - { - "test_name": "UnknownError", - "certificate_header": "{\"network_id\":21,\"height\":8,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"UnknownError\"}}}}}" - }, - { - "test_name": "InvalidSignature", - "certificate_header": "{\"network_id\":22,\"height\":9,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"InvalidSignature\"}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/proof_generation_errors/invalid_imported_bridge_exit_errors.json b/agglayer/testdata/proof_generation_errors/invalid_imported_bridge_exit_errors.json deleted file mode 100644 index dc6b8cad..00000000 --- a/agglayer/testdata/proof_generation_errors/invalid_imported_bridge_exit_errors.json +++ /dev/null @@ -1,48 +0,0 @@ -[ - { - "test_name": "MismatchGlobalIndexInclusionProof", - "certificate_header": "{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"MismatchGlobalIndexInclusionProof\",\"global_index\":{\"mainnet_flag\":true,\"rollup_index\":0,\"leaf_index\":1}}}}}}}}" - }, - { - "test_name": "MismatchL1Root", - "certificate_header": "{\"network_id\":1,\"height\":1,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"MismatchL1Root\",\"global_index\":{\"mainnet_flag\":true,\"rollup_index\":0,\"leaf_index\":2}}}}}}}}" - }, - { - "test_name": "MismatchMER", - "certificate_header": "{\"network_id\":1,\"height\":2,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"MismatchMER\",\"global_index\":{\"mainnet_flag\":true,\"rollup_index\":0,\"leaf_index\":3}}}}}}}}" - }, - { - "test_name": "MismatchRER", - "certificate_header": "{\"network_id\":1,\"height\":3,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"MismatchRER\",\"global_index\":{\"mainnet_flag\":false,\"rollup_index\":1,\"leaf_index\":4}}}}}}}}" - }, - { - "test_name": "InvalidMerklePathLeafToLER", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"InvalidMerklePathLeafToLER\",\"global_index\":{\"mainnet_flag\":true,\"rollup_index\":0,\"leaf_index\":5}}}}}}}}" - }, - { - "test_name": "InvalidMerklePathLERToRER", - "certificate_header": "{\"network_id\":1,\"height\":5,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"InvalidMerklePathLERToRER\",\"global_index\":{\"mainnet_flag\":false,\"rollup_index\":2,\"leaf_index\":6}}}}}}}}" - }, - { - "test_name": "InvalidMerklePathGERToL1Root", - "certificate_header": "{\"network_id\":1,\"height\":6,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"InvalidMerklePathGERToL1Root\",\"global_index\":{\"mainnet_flag\":true,\"rollup_index\":0,\"leaf_index\":7}}}}}}}}" - }, - { - "test_name": "InvalidExitNetwork", - "certificate_header": "{\"network_id\":1,\"height\":7,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"InvalidExitNetwork\",\"global_index\":{\"mainnet_flag\":false,\"rollup_index\":1,\"leaf_index\":8}}}}}}}}" - }, - { - "test_name": "InvalidExitNetwork_missing_source", - "expected_error": "key source not found in map", - "certificate_header": "{\"network_id\":1,\"height\":7,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"global_index\":{\"mainnet_flag\":false,\"rollup_index\":1,\"leaf_index\":8}}}}}}}}" - }, - { - "test_name": "InvalidExitNetwork_missing_global_index", - "expected_error": "key global_index not found in map", - "certificate_header": "{\"network_id\":1,\"height\":7,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"InvalidExitNetwork\"}}}}}}}" - }, - { - "test_name": "UnknownError", - "certificate_header": "{\"network_id\":1,\"height\":7,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidImportedBridgeExit\":{\"source\":\"UnknownError\",\"global_index\":{\"mainnet_flag\":false,\"rollup_index\":1,\"leaf_index\":8}}}}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/proof_generation_errors/invalid_signer_error.json b/agglayer/testdata/proof_generation_errors/invalid_signer_error.json deleted file mode 100644 index 62c5578c..00000000 --- a/agglayer/testdata/proof_generation_errors/invalid_signer_error.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "test_name": "InvalidSignerError", - "certificate_header": "{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidSigner\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed49842ed\",\"recovered\":\"0x20e92bfbb55589f7fd0bec3666e3de469526de3e\"}}}}}}}" - }, - { - "test_name": "InvalidSignerError_missing_declared", - "expected_error": "key declared not found in map", - "certificate_header": "{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidSigner\":{\"recovered\":\"0x20e92bfbb55589f7fd0bec3666e3de469526de3e\"}}}}}}}" - }, - { - "test_name": "InvalidSignerError_missing_recovered", - "expected_error": "key recovered not found in map", - "certificate_header": "{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":{\"InvalidSigner\":{\"declared\":\"0x5b06837a43bdc3dd9f114558daf4b26ed49842ed\"}}}}}}}" - }, - { - "test_name": "InvalidSignerError_missing_inner_error", - "expected_error": "not a map", - "certificate_header": "{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"source\":\"InvalidSigner\"}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/proof_generation_errors/random_unmarshal_errors.json b/agglayer/testdata/proof_generation_errors/random_unmarshal_errors.json deleted file mode 100644 index 680370e2..00000000 --- a/agglayer/testdata/proof_generation_errors/random_unmarshal_errors.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "test_name": "missing_proof_generation_type", - "certificate_header": "{\"network_id\":14,\"height\":1,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"source\":{\"InvalidImportedExitsRoot\":{\"declared\":\"0x1116837a43bdc3dd9f114558daf4b26ed4eeeeec\",\"computed\":\"0x20222bfbb55589f7fd0bec3666e3de469111ce3c\"}}}}}}}", - "expected_error": "key generation_type not found in map" - }, - { - "test_name": "missing_source", - "certificate_header": "{\"network_id\":14,\"height\":1,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofGenerationError\":{\"generation_type\":\"Native\",\"unknown\":{\"InvalidImportedExitsRoot\":{\"declared\":\"0x1116837a43bdc3dd9f114558daf4b26ed4eeeeec\",\"computed\":\"0x20222bfbb55589f7fd0bec3666e3de469111ce3c\"}}}}}}}", - "expected_error": "key source not found in map" - } -] \ No newline at end of file diff --git a/agglayer/testdata/proof_verification_errors/errors_with_inner_data.json b/agglayer/testdata/proof_verification_errors/errors_with_inner_data.json deleted file mode 100644 index 2060d2ee..00000000 --- a/agglayer/testdata/proof_verification_errors/errors_with_inner_data.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "test_name": "VersionMismatch", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofVerificationError\":{\"VersionMismatch\":\"version1-1\"}}}}}" - }, - { - "test_name": "Core", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofVerificationError\":{\"Core\":\"coreexample\"}}}}}" - }, - { - "test_name": "Recursion", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofVerificationError\":{\"Recursion\":\"recursion error\"}}}}}" - }, - { - "test_name": "Plank", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofVerificationError\":{\"Plank\":\"plank error\"}}}}}" - }, - { - "test_name": "Groth16", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofVerificationError\":{\"Groth16\":\"Groth16 error\"}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/proof_verification_errors/errors_without_inner_data.json b/agglayer/testdata/proof_verification_errors/errors_without_inner_data.json deleted file mode 100644 index 458b07c0..00000000 --- a/agglayer/testdata/proof_verification_errors/errors_without_inner_data.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "test_name": "InvalidPublicValues", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"ProofVerificationError\":\"InvalidPublicValues\"}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/type_conversion_errors/errors_with_declared_computed_data.json b/agglayer/testdata/type_conversion_errors/errors_with_declared_computed_data.json deleted file mode 100644 index 348ffa5f..00000000 --- a/agglayer/testdata/type_conversion_errors/errors_with_declared_computed_data.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "test_name": "MultipleL1InfoRoot", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"MismatchNewLocalExitRoot\":{\"declared\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"computed\":\"0x5b06837a43bdc3dd9f114558daf4b26ed49842ee\"}}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/type_conversion_errors/errors_with_token_info.json b/agglayer/testdata/type_conversion_errors/errors_with_token_info.json deleted file mode 100644 index 06d739a9..00000000 --- a/agglayer/testdata/type_conversion_errors/errors_with_token_info.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "test_name": "MultipleL1InfoRoot", - "certificate_header": "{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"MultipleL1InfoRoot\":{\"origin_network\":1,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}" - }, - { - "test_name": "MismatchNewLocalExitRoot", - "certificate_header": "{\"network_id\":1,\"height\":1,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"MismatchNewLocalExitRoot\":{\"origin_network\":1,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}" - }, - { - "test_name": "BalanceOverflow", - "certificate_header": "{\"network_id\":1,\"height\":2,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"BalanceOverflow\":{\"origin_network\":1,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}" - }, - { - "test_name": "BalanceUnderflow", - "certificate_header": "{\"network_id\":1,\"height\":3,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"BalanceUnderflow\":{\"origin_network\":1,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}" - }, - { - "test_name": "BalanceProofGenerationFailed - KeyAlreadyPresent", - "certificate_header": "{\"network_id\":1,\"height\":4,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"BalanceProofGenerationFailed\":{\"source\":\"KeyAlreadyPresent\",\"token\":{\"origin_network\":1,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}}" - }, - { - "test_name": "BalanceProofGenerationFailed - KeyNotPresent", - "certificate_header": "{\"network_id\":1,\"height\":5,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"BalanceProofGenerationFailed\":{\"source\":\"KeyNotPresent\",\"token\":{\"origin_network\":11,\"origin_token_address\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa2\"}}}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/type_conversion_errors/errors_without_inner_data.json b/agglayer/testdata/type_conversion_errors/errors_without_inner_data.json deleted file mode 100644 index a92aca80..00000000 --- a/agglayer/testdata/type_conversion_errors/errors_without_inner_data.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "test_name": "MultipleL1InfoRoot", - "certificate_header": "{\"network_id\":1,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":\"MultipleL1InfoRoot\"}}}}" - } -] \ No newline at end of file diff --git a/agglayer/testdata/type_conversion_errors/l1_info_root_incorrect_error.json b/agglayer/testdata/type_conversion_errors/l1_info_root_incorrect_error.json deleted file mode 100644 index fe3c420a..00000000 --- a/agglayer/testdata/type_conversion_errors/l1_info_root_incorrect_error.json +++ /dev/null @@ -1,11 +0,0 @@ -[ - { - "test_name": "L1InfoRootIncorrect", - "certificate_header": "{\"network_id\":1,\"height\":6,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"L1InfoRootIncorrect\":{\"leaf_count\":11,\"declared\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"retrieved\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\"}}}}}}" - }, - { - "test_name": "L1InfoRootIncorrect - unmarshal error", - "expected_error": "value of key leaf_count is not of type uint32", - "certificate_header": "{\"network_id\":1,\"height\":6,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"L1InfoRootIncorrect\":{\"leaf_count\":\"invalid\",\"declared\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"retrieved\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\"}}}}}}" - } -] diff --git a/agglayer/testdata/type_conversion_errors/nullifier_path_generation_failed_error.json b/agglayer/testdata/type_conversion_errors/nullifier_path_generation_failed_error.json deleted file mode 100644 index b52cd73f..00000000 --- a/agglayer/testdata/type_conversion_errors/nullifier_path_generation_failed_error.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "test_name": "NullifierPathGenerationFailed - KeyPresent", - "certificate_header": "{\"network_id\":1,\"height\":6,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"NullifierPathGenerationFailed\":{\"source\":\"KeyPresent\",\"global_index\":{\"mainnet_flag\":true,\"rollup_index\":0,\"leaf_index\":1}}}}}}}" - }, - { - "test_name": "NullifierPathGenerationFailed - DepthOutOfBounds", - "certificate_header": "{\"network_id\":1,\"height\":7,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"NullifierPathGenerationFailed\":{\"source\":\"DepthOutOfBounds\",\"global_index\":{\"mainnet_flag\":false,\"rollup_index\":11,\"leaf_index\":123}}}}}}}" - }, - { - "test_name": "NullifierPathGenerationFailed_unknown_SMT_error_code", - "expected_error": "unknown SMT error code", - "certificate_header": "{\"network_id\":1,\"height\":7,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"NullifierPathGenerationFailed\":{\"source\":\"UnknownCode\",\"global_index\":{\"mainnet_flag\":false,\"rollup_index\":11,\"leaf_index\":123}}}}}}}" - }, - { - "test_name": "NullifierPathGenerationFailed_missing_SMT_source", - "expected_error": "error code is not a string", - "certificate_header": "{\"network_id\":1,\"height\":7,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0xa80cd4abb016bbb3c3058f923a88be1ad49d68277366c55554d6f13d62428a1f\",\"new_local_exit_root\":\"0x566244fbf813b6926f6895142979f61ed6706184909cb8c819cd0216202a8aa9\",\"metadata\":\"0x000000000000000000000000000000000000000000000000000000000000001f\",\"status\":{\"InError\":{\"error\":{\"TypeConversionError\":{\"NullifierPathGenerationFailed\":{\"unknown\":\"DepthOutOfBounds\",\"global_index\":{\"mainnet_flag\":false,\"rollup_index\":11,\"leaf_index\":123}}}}}}}" - } -] \ No newline at end of file diff --git a/agglayer/type_conversion_error.go b/agglayer/type_conversion_error.go deleted file mode 100644 index 3d75658f..00000000 --- a/agglayer/type_conversion_error.go +++ /dev/null @@ -1,306 +0,0 @@ -package agglayer - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/common" -) - -const ( - MultipleL1InfoRootErrorType = "MultipleL1InfoRoot" - MismatchNewLocalExitRootErrorType = "MismatchNewLocalExitRoot" - BalanceOverflowErrorType = "BalanceOverflow" - BalanceUnderflowErrorType = "BalanceUnderflow" - BalanceProofGenerationFailedErrorType = "BalanceProofGenerationFailed" - NullifierPathGenerationFailedErrorType = "NullifierPathGenerationFailed" - L1InfoRootIncorrectErrorType = "L1InfoRootIncorrect" -) - -// TypeConversionError is an error that is returned when verifying a certficate -// before generating its proof. -type TypeConversionError struct { - InnerErrors []PPError -} - -// String is the implementation of the Error interface -func (p *TypeConversionError) String() string { - return fmt.Sprintf("Type conversion error: %v", p.InnerErrors) -} - -// Unmarshal unmarshals the data from a map into a ProofGenerationError struct. -func (p *TypeConversionError) Unmarshal(data interface{}) error { - getPPErrFn := func(key string, value interface{}) (PPError, error) { - switch key { - case MultipleL1InfoRootErrorType: - p.InnerErrors = append(p.InnerErrors, &MultipleL1InfoRoot{}) - case MismatchNewLocalExitRootErrorType: - p.InnerErrors = append(p.InnerErrors, NewMismatchNewLocalExitRoot()) - case BalanceOverflowErrorType: - balanceOverflow := NewBalanceOverflow() - if err := balanceOverflow.UnmarshalFromMap(value); err != nil { - return nil, err - } - return balanceOverflow, nil - case BalanceUnderflowErrorType: - balanceUnderflow := NewBalanceUnderflow() - if err := balanceUnderflow.UnmarshalFromMap(value); err != nil { - return nil, err - } - return balanceUnderflow, nil - case BalanceProofGenerationFailedErrorType: - balanceProofGenerationFailed := NewBalanceProofGenerationFailed() - if err := balanceProofGenerationFailed.UnmarshalFromMap(value); err != nil { - return nil, err - } - return balanceProofGenerationFailed, nil - case NullifierPathGenerationFailedErrorType: - nullifierPathGenerationFailed := NewNullifierPathGenerationFailed() - if err := nullifierPathGenerationFailed.UnmarshalFromMap(value); err != nil { - return nil, err - } - return nullifierPathGenerationFailed, nil - case L1InfoRootIncorrectErrorType: - l1InfoRootIncorrect := &L1InfoRootIncorrect{} - if err := l1InfoRootIncorrect.Unmarshal(value); err != nil { - return nil, err - } - return l1InfoRootIncorrect, nil - default: - return nil, fmt.Errorf("unknown type conversion error type: %v", key) - } - - return nil, nil - } - - getAndAddInnerErrorFn := func(key string, value interface{}) error { - ppErr, err := getPPErrFn(key, value) - if err != nil { - return err - } - - if ppErr != nil { - p.InnerErrors = append(p.InnerErrors, ppErr) - } - - return nil - } - - errorSourceMap, ok := data.(map[string]interface{}) - if !ok { - // it can be a single error - return getAndAddInnerErrorFn(data.(string), nil) //nolint:forcetypeassert - } - - for key, value := range errorSourceMap { - if err := getAndAddInnerErrorFn(key, value); err != nil { - return err - } - } - - return nil -} - -// MultipleL1InfoRoot is an error that is returned when the imported bridge exits -// refer to different L1 info roots. -type MultipleL1InfoRoot struct{} - -// String is the implementation of the Error interface -func (e *MultipleL1InfoRoot) String() string { - return fmt.Sprintf(`%s: The imported bridge exits should refer to one and the same L1 info root.`, - MultipleL1InfoRootErrorType) -} - -// MissingNewLocalExitRoot is an error that is returned when the certificate refers to -// a new local exit root which differ from the one computed by the agglayer. -type MismatchNewLocalExitRoot struct { - *DeclaredComputedError -} - -func NewMismatchNewLocalExitRoot() *MismatchNewLocalExitRoot { - return &MismatchNewLocalExitRoot{ - DeclaredComputedError: &DeclaredComputedError{ErrType: MismatchNewLocalExitRootErrorType}, - } -} - -// BalanceOverflow is an error that is returned when the given token balance cannot overflow. -type BalanceOverflow struct { - *TokenInfoError -} - -// NewBalanceOverflow returns a new BalanceOverflow error. -func NewBalanceOverflow() *BalanceOverflow { - return &BalanceOverflow{ - TokenInfoError: &TokenInfoError{}, - } -} - -// String is the implementation of the Error interface -func (e *BalanceOverflow) String() string { - return fmt.Sprintf("%s: The given token balance cannot overflow. %s", - BalanceOverflowErrorType, e.TokenInfo.String()) -} - -// BalanceUnderflow is an error that is returned when the given token balance cannot be negative. -type BalanceUnderflow struct { - *TokenInfoError -} - -// NewBalanceOverflow returns a new BalanceOverflow error. -func NewBalanceUnderflow() *BalanceUnderflow { - return &BalanceUnderflow{ - TokenInfoError: &TokenInfoError{}, - } -} - -// String is the implementation of the Error interface -func (e *BalanceUnderflow) String() string { - return fmt.Sprintf("%s: The given token balance cannot be negative. %s", - BalanceUnderflowErrorType, e.TokenInfo.String()) -} - -// SmtError is a type that is inherited by all errors that occur during SMT operations. -type SmtError struct { - ErrorCode string - Error string -} - -func (e *SmtError) Unmarshal(data interface{}) error { - errCode, ok := data.(string) - if !ok { - return errors.New("error code is not a string") - } - - e.ErrorCode = errCode - - switch errCode { - case "KeyAlreadyPresent": - e.Error = "trying to insert a key already in the SMT" - case "KeyNotPresent": - e.Error = "trying to generate a Merkle proof for a key not in the SMT" - case "KeyPresent": - e.Error = "trying to generate a non-inclusion proof for a key present in the SMT" - case "DepthOutOfBounds": - e.Error = "depth out of bounds" - default: - return fmt.Errorf("unknown SMT error code: %s", errCode) - } - - return nil -} - -// BalanceProofGenerationFailed is a struct that represents an error that occurs when -// the balance proof for the given token cannot be generated. -type BalanceProofGenerationFailed struct { - *TokenInfoError - *SmtError -} - -func NewBalanceProofGenerationFailed() *BalanceProofGenerationFailed { - return &BalanceProofGenerationFailed{ - TokenInfoError: &TokenInfoError{}, - SmtError: &SmtError{}, - } -} - -// String is the implementation of the Error interface -func (e *BalanceProofGenerationFailed) String() string { - return fmt.Sprintf("%s: The balance proof for the given token cannot be generated. TokenInfo: %s. Error type: %s. %s", - BalanceProofGenerationFailedErrorType, e.TokenInfo.String(), - e.SmtError.ErrorCode, e.SmtError.Error) -} - -func (e *BalanceProofGenerationFailed) UnmarshalFromMap(data interface{}) error { - dataMap, ok := data.(map[string]interface{}) - if !ok { - return errNotMap - } - - if err := e.TokenInfoError.UnmarshalFromMap(dataMap["token"]); err != nil { - return err - } - - return e.SmtError.Unmarshal(dataMap["source"]) -} - -// NullifierPathGenerationFailed is a struct that represents an error that occurs when -// the nullifier path for the given imported bridge exit cannot be generated.. -type NullifierPathGenerationFailed struct { - GlobalIndex *GlobalIndex `json:"global_index"` - *SmtError -} - -func NewNullifierPathGenerationFailed() *NullifierPathGenerationFailed { - return &NullifierPathGenerationFailed{ - SmtError: &SmtError{}, - } -} - -// String is the implementation of the Error interface -func (e *NullifierPathGenerationFailed) String() string { - return fmt.Sprintf("%s: The nullifier path for the given imported bridge exit cannot be generated. "+ - "GlobalIndex: %s. Error type: %s. %s", - NullifierPathGenerationFailedErrorType, e.GlobalIndex.String(), - e.SmtError.ErrorCode, e.SmtError.Error) -} - -func (e *NullifierPathGenerationFailed) UnmarshalFromMap(data interface{}) error { - dataMap, ok := data.(map[string]interface{}) - if !ok { - return errNotMap - } - - if err := e.SmtError.Unmarshal(dataMap["source"]); err != nil { - return err - } - - globalIndexMap, err := convertMapValue[map[string]interface{}](dataMap, "global_index") - if err != nil { - return err - } - - e.GlobalIndex = &GlobalIndex{} - return e.GlobalIndex.UnmarshalFromMap(globalIndexMap) -} - -// L1InfoRootIncorrect is an error that is returned when the L1 Info Root is invalid or unsettled -type L1InfoRootIncorrect struct { - Declared common.Hash `json:"declared"` - Retrieved common.Hash `json:"retrieved"` - LeafCount uint32 `json:"leaf_count"` -} - -// String is the implementation of the Error interface -func (e *L1InfoRootIncorrect) String() string { - return fmt.Sprintf("%s: The L1 Info Root is incorrect. Declared: %s, Retrieved: %s, LeafCount: %d", - L1InfoRootIncorrectErrorType, e.Declared.String(), e.Retrieved.String(), e.LeafCount) -} - -// Unmarshal unmarshals the data from a map into a L1InfoRootIncorrect struct. -func (e *L1InfoRootIncorrect) Unmarshal(data interface{}) error { - dataMap, ok := data.(map[string]interface{}) - if !ok { - return errNotMap - } - - declared, err := convertMapValue[string](dataMap, "declared") - if err != nil { - return err - } - - retrieved, err := convertMapValue[string](dataMap, "retrieved") - if err != nil { - return err - } - - leafCount, err := convertMapValue[uint32](dataMap, "leaf_count") - if err != nil { - return err - } - - e.Declared = common.HexToHash(declared) - e.Retrieved = common.HexToHash(retrieved) - e.LeafCount = leafCount - - return nil -} diff --git a/agglayer/types.go b/agglayer/types.go index c00b2345..7b338a9b 100644 --- a/agglayer/types.go +++ b/agglayer/types.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "math/big" + "reflect" "slices" "strings" @@ -58,14 +59,10 @@ func (c CertificateStatus) IsOpen() bool { } // UnmarshalJSON is the implementation of the json.Unmarshaler interface -func (c *CertificateStatus) UnmarshalJSON(data []byte) error { - dataStr := string(data) - - var status string - if strings.Contains(dataStr, "InError") { +func (c *CertificateStatus) UnmarshalJSON(rawStatus []byte) error { + status := strings.Trim(string(rawStatus), "\"") + if strings.Contains(status, "InError") { status = "InError" - } else { - status = string(data) } switch status { @@ -272,7 +269,7 @@ type BridgeExit struct { } func (b *BridgeExit) String() string { - res := fmt.Sprintf("LeafType: %s, DestinationNetwork: %d, DestinationAddress: %s, Amount: %s, Metadata: %s", + 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)) @@ -550,13 +547,15 @@ func (c *ImportedBridgeExit) Hash() common.Hash { ) } -type GenericPPError struct { +var _ error = (*GenericError)(nil) + +type GenericError struct { Key string Value string } -func (p *GenericPPError) String() string { - return fmt.Sprintf("Generic error: %s: %s", p.Key, p.Value) +func (p *GenericError) Error() string { + return fmt.Sprintf("[Agglayer Error] %s: %s", p.Key, p.Value) } // CertificateHeader is the structure returned by the interop_getCertificateHeader RPC call @@ -570,7 +569,7 @@ type CertificateHeader struct { NewLocalExitRoot common.Hash `json:"new_local_exit_root"` Status CertificateStatus `json:"status"` Metadata common.Hash `json:"metadata"` - Error PPError `json:"-"` + Error error `json:"-"` } // ID returns a string with the ident of this cert (height/certID) @@ -587,7 +586,7 @@ func (c *CertificateHeader) String() string { } errors := "" if c.Error != nil { - errors = c.Error.String() + errors = c.Error.Error() } previousLocalExitRoot := nilStr if c.PreviousLocalExitRoot != nil { @@ -629,43 +628,23 @@ func (c *CertificateHeader) UnmarshalJSON(data []byte) error { return err } - var ppError PPError + var agglayerErr error - for key, value := range inErrDataMap { - switch key { - case "ProofGenerationError": - p := &ProofGenerationError{} - if err := p.Unmarshal(value); err != nil { - return err - } - - ppError = p - case "TypeConversionError": - t := &TypeConversionError{} - if err := t.Unmarshal(value); err != nil { - return err - } - - ppError = t - case "ProofVerificationError": - p := &ProofVerificationError{} - if err := p.Unmarshal(value); err != nil { - return err - } - - ppError = p - default: - valueStr, err := json.Marshal(value) - if err != nil { - ppError = &GenericPPError{Key: key, Value: "error marshalling value"} - } else { - ppError = &GenericPPError{Key: key, Value: string(valueStr)} + for errKey, errValueRaw := range inErrDataMap { + errValueJSON, err := json.Marshal(errValueRaw) + if err != nil { + agglayerErr = &GenericError{ + Key: errKey, + Value: fmt.Sprintf("failed to marshal the agglayer error to the JSON. Raw value: %+v\nReason: %+v", + errValueRaw, err), } + } else { + agglayerErr = &GenericError{Key: errKey, Value: string(errValueJSON)} } } c.Status = InError - c.Error = ppError + c.Error = agglayerErr default: return errors.New("invalid status type") } @@ -673,6 +652,67 @@ func (c *CertificateHeader) UnmarshalJSON(data []byte) error { return nil } +// convertMapValue converts the value of a key in a map to a target type. +func convertMapValue[T any](data map[string]interface{}, key string) (T, error) { + value, ok := data[key] + if !ok { + var zero T + return zero, fmt.Errorf("key %s not found in map", key) + } + + // Try a direct type assertion + if convertedValue, ok := value.(T); ok { + return convertedValue, nil + } + + // If direct assertion fails, handle numeric type conversions + var target T + targetType := reflect.TypeOf(target) + + // Check if value is a float64 (default JSON number type) and target is a numeric type + if floatValue, ok := value.(float64); ok && targetType.Kind() >= reflect.Int && targetType.Kind() <= reflect.Uint64 { + convertedValue, err := convertNumeric(floatValue, targetType) + if err != nil { + return target, fmt.Errorf("conversion error for key %s: %w", key, err) + } + return convertedValue.(T), nil //nolint:forcetypeassert + } + + return target, fmt.Errorf("value of key %s is not of type %T", key, target) +} + +// convertNumeric converts a float64 to the specified numeric type. +func convertNumeric(value float64, targetType reflect.Type) (interface{}, error) { + switch targetType.Kind() { + case reflect.Int: + return int(value), nil + case reflect.Int8: + return int8(value), nil + case reflect.Int16: + return int16(value), nil + case reflect.Int32: + return int32(value), nil + case reflect.Int64: + return int64(value), nil + case reflect.Uint: + return uint(value), nil + case reflect.Uint8: + return uint8(value), nil + case reflect.Uint16: + return uint16(value), nil + case reflect.Uint32: + return uint32(value), nil + case reflect.Uint64: + return uint64(value), nil + case reflect.Float32: + return float32(value), nil + case reflect.Float64: + return value, nil + default: + return nil, fmt.Errorf("unsupported target type %v", targetType) + } +} + // ClockConfiguration represents the configuration of the epoch clock // returned by the interop_GetEpochConfiguration RPC call type ClockConfiguration struct { diff --git a/agglayer/types_helpers_test.go b/agglayer/types_helpers_test.go new file mode 100644 index 00000000..1bd03a3f --- /dev/null +++ b/agglayer/types_helpers_test.go @@ -0,0 +1,71 @@ +package agglayer + +import ( + "fmt" + "testing" + + "github.com/0xPolygon/cdk/tree/types" + "github.com/ethereum/go-ethereum/common" +) + +// Helper function to create a dummy TokenInfo +func createDummyTokenInfo(t *testing.T) *TokenInfo { + t.Helper() + + return &TokenInfo{ + OriginNetwork: 1, + OriginTokenAddress: common.HexToAddress("0x2345"), + } +} + +// Helper function to create a dummy GlobalIndex +func createDummyGlobalIndex(t *testing.T) *GlobalIndex { + t.Helper() + + return &GlobalIndex{ + MainnetFlag: false, + RollupIndex: 10, + LeafIndex: 1, + } +} + +// Helper function to create a dummy Claim +func createDummyClaim(t *testing.T) *ClaimFromMainnnet { + t.Helper() + + return &ClaimFromMainnnet{ + ProofLeafMER: &MerkleProof{ + Root: common.HexToHash("0x1234"), + Proof: [common.HashLength]common.Hash{ + common.HexToHash("0x1234"), + common.HexToHash("0x5678"), + }, + }, + ProofGERToL1Root: &MerkleProof{ + Root: common.HexToHash("0x5678"), + Proof: [common.HashLength]common.Hash{ + common.HexToHash("0x5678"), + common.HexToHash("0x1234"), + }, + }, + L1Leaf: &L1InfoTreeLeaf{ + L1InfoTreeIndex: 1, + RollupExitRoot: common.HexToHash("0x987654321"), + MainnetExitRoot: common.HexToHash("0x123456789"), + Inner: &L1InfoTreeLeafInner{}, + }, + } +} + +// 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 +} diff --git a/agglayer/types_test.go b/agglayer/types_test.go index adf8e55a..9c7856af 100644 --- a/agglayer/types_test.go +++ b/agglayer/types_test.go @@ -1,14 +1,19 @@ package agglayer import ( + "bytes" "encoding/json" + "errors" "fmt" "math/big" + "reflect" "testing" + cdkcommon "github.com/0xPolygon/cdk/common" "github.com/0xPolygon/cdk/log" "github.com/0xPolygon/cdk/tree/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" ) @@ -17,7 +22,9 @@ const ( expectedSignedCertificateMetadataJSON = `{"network_id":1,"height":1,"prev_local_exit_root":"0x0000000000000000000000000000000000000000000000000000000000000000","new_local_exit_root":"0x0000000000000000000000000000000000000000000000000000000000000000","bridge_exits":[{"leaf_type":"Transfer","token_info":null,"dest_network":0,"dest_address":"0x0000000000000000000000000000000000000000","amount":"1","metadata":[1,2,3]}],"imported_bridge_exits":[{"bridge_exit":{"leaf_type":"Transfer","token_info":null,"dest_network":0,"dest_address":"0x0000000000000000000000000000000000000000","amount":"1","metadata":null},"claim_data":null,"global_index":{"mainnet_flag":false,"rollup_index":1,"leaf_index":1}}],"metadata":"0x0000000000000000000000000000000000000000000000000000000000000000","signature":{"r":"0x0000000000000000000000000000000000000000000000000000000000000000","s":"0x0000000000000000000000000000000000000000000000000000000000000000","odd_y_parity":false}}` ) -func TestBridgeExitHash(t *testing.T) { +func TestBridgeExit_Hash(t *testing.T) { + t.Parallel() + MetadaHash := common.HexToHash("0x1234") bridge := BridgeExit{ TokenInfo: &TokenInfo{}, @@ -42,14 +49,14 @@ func TestBridgeExitHash(t *testing.T) { bridge.Hash().String(), "metadata is a hashed and it's empty,use it") } -func TestMGenericPPError(t *testing.T) { +func TestGenericError_Error(t *testing.T) { t.Parallel() - err := GenericPPError{"test", "value"} - require.Equal(t, "Generic error: test: value", err.String()) + err := GenericError{"test", "value"} + require.Equal(t, "[Agglayer Error] test: value", err.Error()) } -func TestCertificateHeaderID(t *testing.T) { +func TestCertificateHeader_ID(t *testing.T) { t.Parallel() certificate := CertificateHeader{ @@ -168,11 +175,11 @@ func TestMarshalJSON(t *testing.T) { ClaimData: &ClaimFromMainnnet{ ProofLeafMER: &MerkleProof{ Root: common.HexToHash("0x333"), - Proof: generateTestProof(t), + Proof: createDummyProof(t), }, ProofGERToL1Root: &MerkleProof{ Root: common.HexToHash("0x444"), - Proof: generateTestProof(t), + Proof: createDummyProof(t), }, L1Leaf: &L1InfoTreeLeaf{ L1InfoTreeIndex: 1, @@ -203,15 +210,15 @@ func TestMarshalJSON(t *testing.T) { ClaimData: &ClaimFromRollup{ ProofLeafLER: &MerkleProof{ Root: common.HexToHash("0x333"), - Proof: generateTestProof(t), + Proof: createDummyProof(t), }, ProofLERToRER: &MerkleProof{ Root: common.HexToHash("0x444"), - Proof: generateTestProof(t), + Proof: createDummyProof(t), }, ProofGERToL1Root: &MerkleProof{ Root: common.HexToHash("0x555"), - Proof: generateTestProof(t), + Proof: createDummyProof(t), }, L1Leaf: &L1InfoTreeLeaf{ L1InfoTreeIndex: 2, @@ -435,27 +442,535 @@ func TestGlobalIndex_UnmarshalFromMap(t *testing.T) { } } -func TestUnmarshalCertificateHeaderUnknownError(t *testing.T) { +func TestUnmarshalCertificateHeader_UnknownError(t *testing.T) { t.Parallel() - str := "{\"network_id\":14,\"height\":0,\"epoch_number\":null,\"certificate_index\":null,\"certificate_id\":\"0x3af88c9ca106822bd141fdc680dcb888f4e9d4997fad1645ba3d5d747059eb32\",\"new_local_exit_root\":\"0x625e889ced3c31277c6653229096374d396a2fd3564a8894aaad2ff935d2fc8c\",\"metadata\":\"0x0000000000000000000000000000000000000000000000000000000000002f3d\",\"status\":{\"InError\":{\"error\":{\"ProofVerificationFailed\":{\"Plonk\":\"the verifying key does not match the inner plonk bn254 proof's committed verifying key\"}}}}}" - data := []byte(str) + rawCertificateHeader := `{ + "network_id": 14, + "height": 0, + "epoch_number": null, + "certificate_index": null, + "certificate_id": "0x3af88c9ca106822bd141fdc680dcb888f4e9d4997fad1645ba3d5d747059eb32", + "new_local_exit_root": "0x625e889ced3c31277c6653229096374d396a2fd3564a8894aaad2ff935d2fc8c", + "metadata": "0x0000000000000000000000000000000000000000000000000000000000002f3d", + "status": { + "InError": { + "error": { + "ProofVerificationFailed": { + "Plonk": "the verifying key does not match the inner plonk bn254 proof's committed verifying key" + } + } + } + } + }` + var result *CertificateHeader - err := json.Unmarshal(data, &result) + err := json.Unmarshal([]byte(rawCertificateHeader), &result) require.NoError(t, err) require.NotNil(t, result) - ppError := result.Error.String() - require.Equal(t, `Generic error: ProofVerificationFailed: {"Plonk":"the verifying key does not match the inner plonk bn254 proof's committed verifying key"}`, ppError) + + expectedErr := &GenericError{ + Key: "ProofVerificationFailed", + Value: "{\"Plonk\":\"the verifying key does not match the inner plonk bn254 proof's committed verifying key\"}", + } + + require.Equal(t, expectedErr, result.Error) } -func generateTestProof(t *testing.T) types.Proof { - t.Helper() +func TestConvertNumeric(t *testing.T) { + t.Parallel() - proof := types.Proof{} + tests := []struct { + name string + value float64 + target reflect.Type + expected interface{} + expectedErr error + }{ + // Integer conversions + {"FloatToInt", 42.5, reflect.TypeOf(int(0)), int(42), nil}, + {"FloatToInt8", 127.5, reflect.TypeOf(int8(0)), int8(127), nil}, + {"FloatToInt16", 32767.5, reflect.TypeOf(int16(0)), int16(32767), nil}, + {"FloatToInt32", 2147483647.5, reflect.TypeOf(int32(0)), int32(2147483647), nil}, + {"FloatToInt64", -10000000000000000.9, reflect.TypeOf(int64(0)), int64(-10000000000000000), nil}, + + // Unsigned integer conversions + {"FloatToUint", 42.5, reflect.TypeOf(uint(0)), uint(42), nil}, + {"FloatToUint8", 255.5, reflect.TypeOf(uint8(0)), uint8(255), nil}, + {"FloatToUint16", 65535.5, reflect.TypeOf(uint16(0)), uint16(65535), nil}, + {"FloatToUint32", 4294967295.5, reflect.TypeOf(uint32(0)), uint32(4294967295), nil}, + {"FloatToUint64", 10000000000000000.9, reflect.TypeOf(uint64(0)), uint64(10000000000000000), nil}, + + // Float conversions + {"FloatToFloat32", 3.14, reflect.TypeOf(float32(0)), float32(3.14), nil}, + {"FloatToFloat64", 3.14, reflect.TypeOf(float64(0)), float64(3.14), nil}, + + // Unsupported type + {"UnsupportedType", 3.14, reflect.TypeOf("string"), nil, errors.New("unsupported target type string")}, + } - for i := 0; i < int(types.DefaultHeight); i++ { - proof[i] = common.HexToHash(fmt.Sprintf("0x%x", i)) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + result, err := convertNumeric(tt.value, tt.target) + if tt.expectedErr != nil { + require.ErrorContains(t, err, tt.expectedErr.Error()) + } else { + require.NoError(t, err) + } + require.Equal(t, tt.expected, result) + }) } +} - return proof +func TestCertificate_Hash(t *testing.T) { + t.Parallel() + + // Test inputs + prevLocalExitRoot := [common.HashLength]byte{} + newLocalExitRoot := [common.HashLength]byte{} + copy(prevLocalExitRoot[:], bytes.Repeat([]byte{0x01}, common.HashLength)) + copy(newLocalExitRoot[:], bytes.Repeat([]byte{0x02}, common.HashLength)) + + // Create dummy BridgeExits + bridgeExits := []*BridgeExit{ + { + LeafType: LeafTypeAsset, + TokenInfo: createDummyTokenInfo(t), + DestinationNetwork: 1, + DestinationAddress: common.HexToAddress("0x0000000000000000000000000000000000000001"), + Amount: big.NewInt(100), + Metadata: []byte("metadata1"), + }, + { + LeafType: LeafTypeMessage, + TokenInfo: createDummyTokenInfo(t), + DestinationNetwork: 2, + DestinationAddress: common.HexToAddress("0x0000000000000000000000000000000000000002"), + Amount: big.NewInt(200), + Metadata: []byte("metadata2"), + }, + } + + // Create dummy ImportedBridgeExits + importedBridgeExits := []*ImportedBridgeExit{ + { + BridgeExit: &BridgeExit{ + LeafType: LeafTypeAsset, + TokenInfo: createDummyTokenInfo(t), + DestinationNetwork: 3, + DestinationAddress: common.HexToAddress("0x0000000000000000000000000000000000000003"), + Amount: big.NewInt(300), + Metadata: []byte("metadata3"), + }, + ClaimData: createDummyClaim(t), + GlobalIndex: createDummyGlobalIndex(t), + }, + { + BridgeExit: &BridgeExit{ + LeafType: LeafTypeAsset, + TokenInfo: createDummyTokenInfo(t), + DestinationNetwork: 4, + DestinationAddress: common.HexToAddress("0x0000000000000000000000000000000000000004"), + Amount: big.NewInt(400), + Metadata: []byte("metadata4"), + }, + ClaimData: createDummyClaim(t), + GlobalIndex: createDummyGlobalIndex(t), + }, + } + + metadata := common.HexToHash("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234") + + // Create the certificate + certificate := &Certificate{ + NetworkID: 1, + Height: 100, + PrevLocalExitRoot: prevLocalExitRoot, + NewLocalExitRoot: newLocalExitRoot, + BridgeExits: bridgeExits, + ImportedBridgeExits: importedBridgeExits, + Metadata: metadata, + } + + // Manually calculate the expected hash + bridgeExitsHashes := [][]byte{ + bridgeExits[0].Hash().Bytes(), + bridgeExits[1].Hash().Bytes(), + } + importedBridgeExitsHashes := [][]byte{ + importedBridgeExits[0].Hash().Bytes(), + importedBridgeExits[1].Hash().Bytes(), + } + + bridgeExitsPart := crypto.Keccak256(bridgeExitsHashes...) + importedBridgeExitsPart := crypto.Keccak256(importedBridgeExitsHashes...) + + expectedHash := crypto.Keccak256Hash( + cdkcommon.Uint32ToBytes(1), + cdkcommon.Uint64ToBytes(100), + prevLocalExitRoot[:], + newLocalExitRoot[:], + bridgeExitsPart, + importedBridgeExitsPart, + ) + + // Test the certificate hash + calculatedHash := certificate.Hash() + + require.Equal(t, calculatedHash, expectedHash) +} + +func TestCertificate_HashToSign(t *testing.T) { + t.Parallel() + + c := &Certificate{ + NewLocalExitRoot: common.HexToHash("0xabcd"), + ImportedBridgeExits: []*ImportedBridgeExit{ + { + GlobalIndex: &GlobalIndex{ + MainnetFlag: true, + RollupIndex: 23, + LeafIndex: 1, + }, + }, + { + GlobalIndex: &GlobalIndex{ + MainnetFlag: false, + RollupIndex: 15, + LeafIndex: 2, + }, + }, + }, + } + + globalIndexHashes := make([][]byte, len(c.ImportedBridgeExits)) + for i, importedBridgeExit := range c.ImportedBridgeExits { + globalIndexHashes[i] = importedBridgeExit.GlobalIndex.Hash().Bytes() + } + + expectedHash := crypto.Keccak256Hash( + c.NewLocalExitRoot[:], + crypto.Keccak256Hash(globalIndexHashes...).Bytes(), + ) + + certHash := c.HashToSign() + require.Equal(t, expectedHash, certHash) +} + +func TestClaimFromMainnnet_MarshalJSON(t *testing.T) { + t.Parallel() + + // Test data + merkleProof := &MerkleProof{ + Root: common.HexToHash("0x1"), + Proof: [types.DefaultHeight]common.Hash{ + common.HexToHash("0x2"), + common.HexToHash("0x3"), + }, + } + + l1InfoTreeLeaf := &L1InfoTreeLeaf{ + L1InfoTreeIndex: 42, + RollupExitRoot: [common.HashLength]byte{0xaa, 0xbb, 0xcc}, + MainnetExitRoot: [common.HashLength]byte{0xdd, 0xee, 0xff}, + Inner: &L1InfoTreeLeafInner{ + GlobalExitRoot: common.HexToHash("0x1"), + BlockHash: common.HexToHash("0x2"), + Timestamp: 1672531200, // Example timestamp + }, + } + + claim := &ClaimFromMainnnet{ + ProofLeafMER: merkleProof, + ProofGERToL1Root: merkleProof, + L1Leaf: l1InfoTreeLeaf, + } + + // Marshal the ClaimFromMainnnet struct to JSON + expectedJSON, err := claim.MarshalJSON() + require.NoError(t, err) + + var actualClaim ClaimFromMainnnet + err = json.Unmarshal(expectedJSON, &actualClaim) + require.NoError(t, err) +} + +func TestBridgeExit_String(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + bridgeExit *BridgeExit + expectedOutput string + }{ + { + name: "With TokenInfo", + bridgeExit: &BridgeExit{ + LeafType: LeafTypeAsset, + TokenInfo: createDummyTokenInfo(t), + DestinationNetwork: 100, + DestinationAddress: common.HexToAddress("0x2"), + Amount: big.NewInt(1000), + Metadata: []byte{0x01, 0x02, 0x03}, + }, + expectedOutput: "LeafType: Transfer, DestinationNetwork: 100, DestinationAddress: 0x0000000000000000000000000000000000000002, Amount: 1000, Metadata: 010203, TokenInfo: OriginNetwork: 1, OriginTokenAddress: 0x0000000000000000000000000000000000002345", + }, + { + name: "Without TokenInfo", + bridgeExit: &BridgeExit{ + LeafType: LeafTypeMessage, + DestinationNetwork: 200, + DestinationAddress: common.HexToAddress("0x1"), + Amount: big.NewInt(5000), + Metadata: []byte{0xff, 0xee, 0xdd}, + }, + expectedOutput: "LeafType: Message, DestinationNetwork: 200, DestinationAddress: 0x0000000000000000000000000000000000000001, Amount: 5000, Metadata: ffeedd, TokenInfo: nil", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + actualOutput := tt.bridgeExit.String() + require.Equal(t, tt.expectedOutput, actualOutput) + }) + } +} + +func TestCertificateStatus_UnmarshalJSON(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + input string + expected CertificateStatus + expectError bool + }{ + { + name: "Valid status - Pending", + input: `"Pending"`, + expected: Pending, + expectError: false, + }, + { + name: "Valid status - Proven", + input: `"Proven"`, + expected: Proven, + expectError: false, + }, + { + name: "Valid status - Candidate", + input: `"Candidate"`, + expected: Candidate, + expectError: false, + }, + { + name: "Valid status - InError", + input: `"InError"`, + expected: InError, + expectError: false, + }, + { + name: "Valid status - Settled", + input: `"Settled"`, + expected: Settled, + expectError: false, + }, + { + name: "Invalid status", + input: `"InvalidStatus"`, + expected: 0, // Unchanged (default value of CertificateStatus) + expectError: true, + }, + { + name: "Contains 'InError' string", + input: `"SomeStringWithInError"`, + expected: InError, + expectError: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + var status CertificateStatus + err := json.Unmarshal([]byte(tt.input), &status) + + if tt.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.expected, status) + } + }) + } +} + +func TestMerkleProof_String(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + proof MerkleProof + expected string + }{ + { + name: "Empty Root and Empty Proof", + proof: MerkleProof{ + Root: common.Hash{}, + Proof: [types.DefaultHeight]common.Hash{}, + }, + expected: fmt.Sprintf("Root: %s, Proof: %v", common.Hash{}.String(), [types.DefaultHeight]common.Hash{}), + }, + { + name: "Non-Empty Root and Empty Proof", + proof: MerkleProof{ + Root: common.HexToHash("0xabc123"), + Proof: [types.DefaultHeight]common.Hash{}, + }, + expected: fmt.Sprintf("Root: %s, Proof: %v", common.HexToHash("0xabc123").String(), [types.DefaultHeight]common.Hash{}), + }, + { + name: "Non-Empty Root and Partially Populated Proof", + proof: MerkleProof{ + Root: common.HexToHash("0xabc123"), + Proof: [types.DefaultHeight]common.Hash{ + common.HexToHash("0xdef456"), + common.HexToHash("0x123789"), + }, + }, + expected: fmt.Sprintf("Root: %s, Proof: %v", + common.HexToHash("0xabc123").String(), + [types.DefaultHeight]common.Hash{ + common.HexToHash("0xdef456"), + common.HexToHash("0x123789"), + }), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + result := tt.proof.String() + require.Equal(t, tt.expected, result) + }) + } +} + +func TestGlobalIndexString(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + input GlobalIndex + expected string + }{ + { + name: "All fields zero", + input: GlobalIndex{ + MainnetFlag: false, + RollupIndex: 0, + LeafIndex: 0, + }, + expected: "MainnetFlag: false, RollupIndex: 0, LeafIndex: 0", + }, + { + name: "MainnetFlag true, non-zero indices", + input: GlobalIndex{ + MainnetFlag: true, + RollupIndex: 123, + LeafIndex: 456, + }, + expected: "MainnetFlag: true, RollupIndex: 123, LeafIndex: 456", + }, + { + name: "MainnetFlag false, large indices", + input: GlobalIndex{ + MainnetFlag: false, + RollupIndex: 4294967295, // Maximum value of uint32 + LeafIndex: 2147483647, // Large but within uint32 range + }, + expected: "MainnetFlag: false, RollupIndex: 4294967295, LeafIndex: 2147483647", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + result := tt.input.String() + require.Equal(t, tt.expected, result) + }) + } +} + +func TestL1InfoTreeLeafString(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + input L1InfoTreeLeaf + expected string + }{ + { + name: "With valid Inner", + input: L1InfoTreeLeaf{ + L1InfoTreeIndex: 1, + RollupExitRoot: common.HexToHash("0x01"), + MainnetExitRoot: common.HexToHash("0x02"), + Inner: &L1InfoTreeLeafInner{ + GlobalExitRoot: common.HexToHash("0x03"), + BlockHash: common.HexToHash("0x04"), + Timestamp: 1234567890, + }, + }, + expected: "L1InfoTreeIndex: 1, RollupExitRoot: 0x0000000000000000000000000000000000000000000000000000000000000001, " + + "MainnetExitRoot: 0x0000000000000000000000000000000000000000000000000000000000000002, " + + "Inner: GlobalExitRoot: 0x0000000000000000000000000000000000000000000000000000000000000003, " + + "BlockHash: 0x0000000000000000000000000000000000000000000000000000000000000004, Timestamp: 1234567890", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + result := tt.input.String() + require.Equal(t, tt.expected, result) + }) + } +} + +func TestClaimType(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + claim Claim + expectedType string + }{ + { + name: "Mainnet claim", + claim: &ClaimFromMainnnet{}, + expectedType: "Mainnet", + }, + { + name: "Rollup claim", + claim: &ClaimFromRollup{}, + expectedType: "Rollup", + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + t.Parallel() + + actualType := c.claim.Type() + require.Equal(t, c.expectedType, actualType) + }) + } } diff --git a/crates/cdk/versions.json b/crates/cdk/versions.json index 39bfb4dc..d2612714 100644 --- a/crates/cdk/versions.json +++ b/crates/cdk/versions.json @@ -1,12 +1,12 @@ { - "agglayer_image": "ghcr.io/agglayer/agglayer:0.2.0-rc.5", - "cdk_erigon_node_image": "hermeznetwork/cdk-erigon:v2.1.2", - "cdk_node_image": "ghcr.io/0xpolygon/cdk:0.4.0-beta8", + "agglayer_image": "ghcr.io/agglayer/agglayer:0.2.0-rc.17", + "cdk_erigon_node_image": "hermeznetwork/cdk-erigon:v2.60.0", + "cdk_node_image": "ghcr.io/0xpolygon/cdk:0.4.0", "cdk_validium_node_image": "0xpolygon/cdk-validium-node:0.7.0-cdk", - "zkevm_bridge_proxy_image": "haproxy:3.0-bookworm", - "zkevm_bridge_service_image": "hermeznetwork/zkevm-bridge-service:v0.6.0-RC1", + "zkevm_bridge_proxy_image": "haproxy:3.1-bookworm", + "zkevm_bridge_service_image": "hermeznetwork/zkevm-bridge-service:v0.6.0-RC2", "zkevm_bridge_ui_image": "leovct/zkevm-bridge-ui:multi-network", - "zkevm_contracts_image": "leovct/zkevm-contracts:v8.0.0-rc.4-fork.12", + "zkevm_contracts_image": "leovct/zkevm-contracts:v8.0.0-fork.12", "zkevm_da_image": "0xpolygon/cdk-data-availability:0.0.10", "zkevm_node_image": "hermeznetwork/zkevm-node:v0.7.3", "zkevm_pool_manager_image": "hermeznetwork/zkevm-pool-manager:v0.1.2",