diff --git a/agglayer/errors_test.go b/agglayer/errors_test.go index a226ab69d..142930263 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) - } 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 3086caa54..000000000 --- a/agglayer/proof_generation_error.go +++ /dev/null @@ -1,661 +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" -) - -// ProofGenerationError is a struct that represents an error that occurs when generating a proof. -type ProofGenerationError struct { - GenerationType string - InnerErrors []error -} - -// String is the implementation of the Error interface -func (p *ProofGenerationError) Error() 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{}) (error, 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, &MismatchImportedExitsRootError{}) - case InvalidNullifierPathErrorType: - p.InnerErrors = append(p.InnerErrors, &InvalidNullifierPathError{}) - case InvalidBalancePathErrorType: - p.InnerErrors = append(p.InnerErrors, &InvalidBalancePathError{}) - case BalanceOverflowInBridgeExitErrorType: - p.InnerErrors = append(p.InnerErrors, &BalanceOverflowInBridgeExitError{}) - case BalanceUnderflowInBridgeExitErrorType: - p.InnerErrors = append(p.InnerErrors, &BalanceUnderflowInBridgeExitError{}) - case CannotExitToSameNetworkErrorType: - p.InnerErrors = append(p.InnerErrors, &CannotExitToSameNetworkError{}) - case InvalidMessageOriginNetworkErrorType: - p.InnerErrors = append(p.InnerErrors, &InvalidMessageOriginNetworkError{}) - 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, &InvalidSignatureError{}) - case InvalidImportedBridgeExitErrorType: - invalidImportedBridgeExit := &InvalidImportedBridgeExitError{} - 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) Error() string { - return e.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) Error() 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 -} - -// InvalidPreviousLocalExitRootError is a struct that represents an error that occurs when -// the previous local exit root is invalid. -type InvalidPreviousLocalExitRootError struct { - *DeclaredComputedError -} - -func NewInvalidPreviousLocalExitRoot() *InvalidPreviousLocalExitRootError { - return &InvalidPreviousLocalExitRootError{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidPreviousLERErrorType}, - } -} - -// InvalidPreviousBalanceRootError is a struct that represents an error that occurs when -// the previous balance root is invalid. -type InvalidPreviousBalanceRootError struct { - *DeclaredComputedError -} - -func NewInvalidPreviousBalanceRoot() *InvalidPreviousBalanceRootError { - return &InvalidPreviousBalanceRootError{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidPreviousBalanceRootErrorType}, - } -} - -// InvalidPreviousNullifierRootError is a struct that represents an error that occurs when -// the previous nullifier root is invalid. -type InvalidPreviousNullifierRootError struct { - *DeclaredComputedError -} - -func NewInvalidPreviousNullifierRoot() *InvalidPreviousNullifierRootError { - return &InvalidPreviousNullifierRootError{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidPreviousNullifierRootErrorType}, - } -} - -// InvalidNewLocalExitRootError is a struct that represents an error that occurs when -// the new local exit root is invalid. -type InvalidNewLocalExitRootError struct { - *DeclaredComputedError -} - -func NewInvalidNewLocalExitRoot() *InvalidNewLocalExitRootError { - return &InvalidNewLocalExitRootError{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidNewLocalExitRootErrorType}, - } -} - -// InvalidNewBalanceRootError is a struct that represents an error that occurs when -// the new balance root is invalid. -type InvalidNewBalanceRootError struct { - *DeclaredComputedError -} - -func NewInvalidNewBalanceRoot() *InvalidNewBalanceRootError { - return &InvalidNewBalanceRootError{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidNewBalanceRootErrorType}, - } -} - -// InvalidNewNullifierRootError is a struct that represents an error that occurs when -// the new nullifier root is invalid. -type InvalidNewNullifierRootError struct { - *DeclaredComputedError -} - -func NewInvalidNewNullifierRoot() *InvalidNewNullifierRootError { - return &InvalidNewNullifierRootError{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidNewNullifierRootErrorType}, - } -} - -// InvalidImportedExitsRootError is a struct that represents an error that occurs when -// the imported exits root is invalid. -type InvalidImportedExitsRootError struct { - *DeclaredComputedError -} - -func NewInvalidImportedExitsRoot() *InvalidImportedExitsRootError { - return &InvalidImportedExitsRootError{ - DeclaredComputedError: &DeclaredComputedError{ErrType: InvalidImportedExitsRootErrorType}, - } -} - -// MismatchImportedExitsRootError 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 MismatchImportedExitsRootError struct{} - -// String is the implementation of the Error interface -func (e *MismatchImportedExitsRootError) Error() 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) -} - -// InvalidNullifierPathError is a struct that represents an error that occurs when -// the provided nullifier path is invalid. -type InvalidNullifierPathError struct{} - -// String is the implementation of the Error interface -func (e *InvalidNullifierPathError) Error() string { - return fmt.Sprintf("%s: The provided nullifier path is invalid", InvalidNullifierPathErrorType) -} - -// InvalidBalancePathError is a struct that represents an error that occurs when -// the provided balance path is invalid. -type InvalidBalancePathError struct{} - -// String is the implementation of the Error interface -func (e *InvalidBalancePathError) Error() string { - return fmt.Sprintf("%s: The provided balance path is invalid", InvalidBalancePathErrorType) -} - -// BalanceOverflowInBridgeExitError is a struct that represents an error that occurs when -// bridge exit led to balance overflow. -type BalanceOverflowInBridgeExitError struct{} - -// String is the implementation of the Error interface -func (e *BalanceOverflowInBridgeExitError) Error() string { - return fmt.Sprintf("%s: The imported bridge exit led to balance overflow.", BalanceOverflowInBridgeExitErrorType) -} - -// BalanceUnderflowInBridgeExitError is a struct that represents an error that occurs when -// bridge exit led to balance underflow. -type BalanceUnderflowInBridgeExitError struct{} - -// String is the implementation of the Error interface -func (e *BalanceUnderflowInBridgeExitError) Error() string { - return fmt.Sprintf("%s: The imported bridge exit led to balance underflow.", BalanceUnderflowInBridgeExitErrorType) -} - -// CannotExitToSameNetworkError is a struct that represents an error that occurs when -// the user tries to exit to the same network. -type CannotExitToSameNetworkError struct{} - -// String is the implementation of the Error interface -func (e *CannotExitToSameNetworkError) Error() string { - return fmt.Sprintf("%s: The provided bridge exit goes to the sender’s own network which is not permitted.", - CannotExitToSameNetworkErrorType) -} - -// InvalidMessageOriginNetworkError is a struct that represents an error that occurs when -// the origin network of the message is invalid. -type InvalidMessageOriginNetworkError struct{} - -// String is the implementation of the Error interface -func (e *InvalidMessageOriginNetworkError) Error() 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 -} - -func (e *TokenInfoError) Error() string { - return fmt.Sprintf("token info %v, is nested %t", e.TokenInfo.String(), e.isNested) -} - -// InvalidL1TokenInfoError is a struct that represents an error that occurs when -// the L1 token info is invalid. -type InvalidL1TokenInfoError struct { - *TokenInfoError -} - -// NewInvalidL1TokenInfo returns a new instance of InvalidL1TokenInfo. -func NewInvalidL1TokenInfo() *InvalidL1TokenInfoError { - return &InvalidL1TokenInfoError{ - TokenInfoError: &TokenInfoError{isNested: true}, - } -} - -// String is the implementation of the Error interface -func (e *InvalidL1TokenInfoError) String() string { - return fmt.Sprintf("%s: The L1 token info is invalid. %s", - InvalidL1TokenInfoErrorType, e.TokenInfo.String()) -} - -// MissingTokenBalanceProofError is a struct that represents an error that occurs when -// the token balance proof is missing. -type MissingTokenBalanceProofError struct { - *TokenInfoError -} - -// NewMissingTokenBalanceProof returns a new instance of MissingTokenBalanceProof. -func NewMissingTokenBalanceProof() *MissingTokenBalanceProofError { - return &MissingTokenBalanceProofError{ - TokenInfoError: &TokenInfoError{isNested: true}, - } -} - -// String is the implementation of the Error interface -func (e *MissingTokenBalanceProofError) String() string { - return fmt.Sprintf("%s: The provided token is missing a balance proof. %s", - MissingTokenBalanceProofErrorType, e.TokenInfo.String()) -} - -// DuplicateTokenBalanceProofError is a struct that represents an error that occurs when -// the token balance proof is duplicated. -type DuplicateTokenBalanceProofError struct { - *TokenInfoError -} - -// NewDuplicateTokenBalanceProof returns a new instance of DuplicateTokenBalanceProof. -func NewDuplicateTokenBalanceProof() *DuplicateTokenBalanceProofError { - return &DuplicateTokenBalanceProofError{ - TokenInfoError: &TokenInfoError{isNested: true}, - } -} - -// String is the implementation of the Error interface -func (e *DuplicateTokenBalanceProofError) String() string { - return fmt.Sprintf("%s: The provided token comes with multiple balance proofs. %s", - DuplicateTokenBalanceProofErrorType, e.TokenInfo.String()) -} - -// InvalidSignatureError is a struct that represents an error that occurs when -// the signature is invalid. -type InvalidSignatureError struct{} - -// String is the implementation of the Error interface -func (e *InvalidSignatureError) Error() 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) Error() string { - return fmt.Sprintf("%s: An unknown error occurred.", UnknownErrorType) -} - -// InvalidImportedBridgeExitError is a struct that represents an error that occurs when -// the imported bridge exit is invalid. -type InvalidImportedBridgeExitError struct { - GlobalIndex *GlobalIndex `json:"global_index"` - ErrorType string `json:"error_type"` -} - -// String is the implementation of the Error interface -func (e *InvalidImportedBridgeExitError) Error() 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 *InvalidImportedBridgeExitError) 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 a28ad9a94..000000000 --- a/agglayer/proof_verification_error.go +++ /dev/null @@ -1,168 +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 []error -} - -// String is the implementation of the Error interface -func (p *ProofVerificationError) Error() 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{}) (error, error) { - switch key { - case VersionMismatchErrorType: - versionMismatch := &VersionMismatchError{} - if err := versionMismatch.Unmarshal(value); err != nil { - return nil, err - } - return versionMismatch, nil - case CoreErrorType: - core := &CoreError{} - if err := core.Unmarshal(value); err != nil { - return nil, err - } - return core, nil - case RecursionErrorType: - recursion := &RecursionError{} - if err := recursion.Unmarshal(value); err != nil { - return nil, err - } - return recursion, nil - case PlankErrorType: - plank := &PlankError{} - if err := plank.Unmarshal(value); err != nil { - return nil, err - } - return plank, nil - case Groth16ErrorType: - groth16 := &Groth16Error{} - if err := groth16.Unmarshal(value); err != nil { - return nil, err - } - return groth16, nil - case InvalidPublicValuesErrorType: - return &InvalidPublicValuesError{}, 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 -} - -// VersionMismatchError is an error that is returned when the version of the proof is -// different from the version of the core. -type VersionMismatchError struct { - StringError -} - -// String is the implementation of the Error interface -func (e *VersionMismatchError) String() string { - return fmt.Sprintf("%s: %s", VersionMismatchErrorType, e.StringError) -} - -func (e *VersionMismatchError) Error() string { - return e.String() -} - -// CoreError is an error that is returned when the core machine verification fails. -type CoreError struct { - StringError -} - -// String is the implementation of the Error interface -func (e *CoreError) Error() string { - return fmt.Sprintf("%s: Core machine verification error: %s", CoreErrorType, e.StringError) -} - -// RecursionError is an error that is returned when the recursion verification fails. -type RecursionError struct { - StringError -} - -// String is the implementation of the Error interface -func (e *RecursionError) Error() string { - return fmt.Sprintf("%s: Recursion verification error: %s", RecursionErrorType, e.StringError) -} - -// PlankError is an error that is returned when the plank verification fails. -type PlankError struct { - StringError -} - -// String is the implementation of the Error interface -func (e *PlankError) Error() string { - return fmt.Sprintf("%s: Plank verification error: %s", PlankErrorType, e.StringError) -} - -// Groth16Error is an error that is returned when the Groth16Error verification fails. -type Groth16Error struct { - StringError -} - -// String is the implementation of the Error interface -func (e *Groth16Error) Error() string { - return fmt.Sprintf("%s: Groth16 verification error: %s", Groth16ErrorType, e.StringError) -} - -// InvalidPublicValuesError is an error that is returned when the public values are invalid. -type InvalidPublicValuesError struct{} - -// String is the implementation of the Error interface -func (e *InvalidPublicValuesError) Error() 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 4b1b4029b..000000000 --- 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 6884676a4..000000000 --- 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 87946f168..000000000 --- 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 dc6b8cade..000000000 --- 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 62c5578ce..000000000 --- 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 680370e24..000000000 --- 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 2060d2eee..000000000 --- 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 458b07c06..000000000 --- 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 348ffa5f2..000000000 --- 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 06d739a94..000000000 --- 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 a92aca80d..000000000 --- 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 fe3c420a4..000000000 --- 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 b52cd73fd..000000000 --- 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 8138a5ee0..000000000 --- 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 []error -} - -// String is the implementation of the Error interface -func (p *TypeConversionError) Error() 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{}) (error, error) { - switch key { - case MultipleL1InfoRootErrorType: - p.InnerErrors = append(p.InnerErrors, &MultipleL1InfoRootError{}) - 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 := &L1InfoRootIncorrectError{} - 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 -} - -// MultipleL1InfoRootError is an error that is returned when the imported bridge exits -// refer to different L1 info roots. -type MultipleL1InfoRootError struct{} - -// String is the implementation of the Error interface -func (e *MultipleL1InfoRootError) Error() 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 MismatchNewLocalExitRootError struct { - *DeclaredComputedError -} - -func NewMismatchNewLocalExitRoot() *MismatchNewLocalExitRootError { - return &MismatchNewLocalExitRootError{ - DeclaredComputedError: &DeclaredComputedError{ErrType: MismatchNewLocalExitRootErrorType}, - } -} - -// BalanceOverflowError is an error that is returned when the given token balance cannot overflow. -type BalanceOverflowError struct { - *TokenInfoError -} - -// NewBalanceOverflow returns a new BalanceOverflow error. -func NewBalanceOverflow() *BalanceOverflowError { - return &BalanceOverflowError{ - TokenInfoError: &TokenInfoError{}, - } -} - -// String is the implementation of the Error interface -func (e *BalanceOverflowError) Error() string { - return fmt.Sprintf("%s: The given token balance cannot overflow. %s", - BalanceOverflowErrorType, e.TokenInfo.String()) -} - -// BalanceUnderflowError is an error that is returned when the given token balance cannot be negative. -type BalanceUnderflowError struct { - *TokenInfoError -} - -// NewBalanceOverflow returns a new BalanceOverflow error. -func NewBalanceUnderflow() *BalanceUnderflowError { - return &BalanceUnderflowError{ - TokenInfoError: &TokenInfoError{}, - } -} - -// String is the implementation of the Error interface -func (e *BalanceUnderflowError) Error() 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 -} - -// BalanceProofGenerationFailedError is a struct that represents an error that occurs when -// the balance proof for the given token cannot be generated. -type BalanceProofGenerationFailedError struct { - *TokenInfoError - *SmtError -} - -func NewBalanceProofGenerationFailed() *BalanceProofGenerationFailedError { - return &BalanceProofGenerationFailedError{ - TokenInfoError: &TokenInfoError{}, - SmtError: &SmtError{}, - } -} - -// String is the implementation of the Error interface -func (e *BalanceProofGenerationFailedError) Error() 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 *BalanceProofGenerationFailedError) 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"]) -} - -// NullifierPathGenerationFailedError is a struct that represents an error that occurs when -// the nullifier path for the given imported bridge exit cannot be generated.. -type NullifierPathGenerationFailedError struct { - GlobalIndex *GlobalIndex `json:"global_index"` - *SmtError -} - -func NewNullifierPathGenerationFailed() *NullifierPathGenerationFailedError { - return &NullifierPathGenerationFailedError{ - SmtError: &SmtError{}, - } -} - -// String is the implementation of the Error interface -func (e *NullifierPathGenerationFailedError) Error() 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 *NullifierPathGenerationFailedError) 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) -} - -// L1InfoRootIncorrectError is an error that is returned when the L1 Info Root is invalid or unsettled -type L1InfoRootIncorrectError 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 *L1InfoRootIncorrectError) Error() 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 *L1InfoRootIncorrectError) 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 652f1ce39..ebbc954ff 100644 --- a/agglayer/types.go +++ b/agglayer/types.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "math/big" + "reflect" "slices" "strings" @@ -559,13 +560,15 @@ func (c *ImportedBridgeExit) Hash() common.Hash { ) } -type GenericPPError struct { +var _ error = (*GenericError)(nil) + +type GenericError struct { Key string Value string } -func (p *GenericPPError) Error() 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 @@ -640,36 +643,16 @@ func (c *CertificateHeader) UnmarshalJSON(data []byte) error { var ppError 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 { + ppError = &GenericError{ + Key: errKey, + Value: fmt.Sprintf("failed to marshal the agglayer error to the JSON. Raw value: %+v\nReason: %+v", + errValueRaw, err), } + } else { + ppError = &GenericError{Key: errKey, Value: string(errValueJSON)} } } @@ -682,6 +665,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, errors.New("unsupported target type") + } +} + // ClockConfiguration represents the configuration of the epoch clock // returned by the interop_GetEpochConfiguration RPC call type ClockConfiguration struct { diff --git a/agglayer/types_test.go b/agglayer/types_test.go index cfffdc3e2..d0dea0f97 100644 --- a/agglayer/types_test.go +++ b/agglayer/types_test.go @@ -40,9 +40,9 @@ func TestBridgeExitHash(t *testing.T) { bridge.Hash().String(), "metadata is a hashed and it's empty,use it") } -func TestMGenericPPError(t *testing.T) { - err := GenericPPError{"test", "value"} - require.Equal(t, "Generic error: test: value", err.Error()) +func TestGenericError_Error(t *testing.T) { + err := GenericError{"test", "value"} + require.Equal(t, "[Agglayer Error] test: value", err.Error()) } func TestCertificateHeaderID(t *testing.T) { @@ -306,12 +306,34 @@ func TestGlobalIndex_UnmarshalFromMap(t *testing.T) { } func TestUnmarshalCertificateHeaderUnknownError(t *testing.T) { - 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 - 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) }