1+ /*
2+ Copyright IBM Corp. All Rights Reserved.
3+
4+ SPDX-License-Identifier: Apache-2.0
5+ */
6+
7+ package validation
8+
9+ import (
10+ "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
11+ )
12+
13+ // Error codes for validation failures
14+ const (
15+ // Amount validation errors
16+ ErrCodeInvalidAmount = "invalid-amount"
17+ ErrCodeNegativeAmount = "negative-amount"
18+ ErrCodeZeroAmount = "zero-amount"
19+ ErrCodeAmountOverflow = "amount-overflow"
20+ ErrCodeAmountExceedsMax = "amount-exceeds-max"
21+
22+ // Address validation errors
23+ ErrCodeInvalidAddress = "invalid-address"
24+ ErrCodeEmptyAddress = "empty-address"
25+ ErrCodeMalformedAddress = "malformed-address"
26+
27+ // Metadata validation errors
28+ ErrCodeInvalidMetadata = "invalid-metadata"
29+ ErrCodeMetadataTooLarge = "metadata-too-large"
30+ ErrCodeMetadataTypeMismatch = "metadata-type-mismatch"
31+
32+ // Token type validation errors
33+ ErrCodeInvalidTokenType = "invalid-token-type"
34+ ErrCodeEmptyTokenType = "empty-token-type"
35+ ErrCodeUnknownTokenType = "unknown-token-type"
36+
37+ // General validation errors
38+ ErrCodeInvalidInput = "invalid-input"
39+ ErrCodeEmptyWallet = "empty-wallet"
40+ )
41+
42+ // MaxMetadataSize is the maximum size of metadata in bytes
43+ const MaxMetadataSize = 1024 * 10 // 10KB
44+
45+ // MaxAddressLength is the maximum length of an address
46+ const MaxAddressLength = 256
47+
48+ // InvalidAmountError indicates a token amount validation failure
49+ type InvalidAmountError struct {
50+ Code string
51+ Message string
52+ Value interface {}
53+ }
54+
55+ func (e * InvalidAmountError ) Error () string {
56+ return errors .Errorf ("%s: %s" , e .Code , e .Message ).Error ()
57+ }
58+
59+ // InvalidAddressError indicates an address validation failure
60+ type InvalidAddressError struct {
61+ Code string
62+ Message string
63+ Address interface {}
64+ }
65+
66+ func (e * InvalidAddressError ) Error () string {
67+ return errors .Errorf ("%s: %s" , e .Code , e .Message ).Error ()
68+ }
69+
70+ // InvalidMetadataError indicates a metadata validation failure
71+ type InvalidMetadataError struct {
72+ Code string
73+ Message string
74+ Key string
75+ }
76+
77+ func (e * InvalidMetadataError ) Error () string {
78+ return errors .Errorf ("%s: %s" , e .Code , e .Message ).Error ()
79+ }
80+
81+ // InvalidTokenTypeError indicates a token type validation failure
82+ type InvalidTokenTypeError struct {
83+ Code string
84+ Message string
85+ Type string
86+ }
87+
88+ func (e * InvalidTokenTypeError ) Error () string {
89+ return errors .Errorf ("%s: %s" , e .Code , e .Message ).Error ()
90+ }
91+
92+ // ValidationError is a generic validation error with a code
93+ type ValidationError struct {
94+ Code string
95+ Message string
96+ }
97+
98+ func (e * ValidationError ) Error () string {
99+ return errors .Errorf ("%s: %s" , e .Code , e .Message ).Error ()
100+ }
101+
102+ // NewInvalidAmountError creates a new InvalidAmountError
103+ func NewInvalidAmountError (code , message string , value interface {}) * InvalidAmountError {
104+ return & InvalidAmountError {Code : code , Message : message , Value : value }
105+ }
106+
107+ // NewInvalidAddressError creates a new InvalidAddressError
108+ func NewInvalidAddressError (code , message string , address interface {}) * InvalidAddressError {
109+ return & InvalidAddressError {Code : code , Message : message , Address : address }
110+ }
111+
112+ // NewInvalidMetadataError creates a new InvalidMetadataError
113+ func NewInvalidMetadataError (code , message , key string ) * InvalidMetadataError {
114+ return & InvalidMetadataError {Code : code , Message : message , Key : key }
115+ }
116+
117+ // NewInvalidTokenTypeError creates a new InvalidTokenTypeError
118+ func NewInvalidTokenTypeError (code , message , tokenType string ) * InvalidTokenTypeError {
119+ return & InvalidTokenTypeError {Code : code , Message : message , Type : tokenType }
120+ }
121+
122+ // NewValidationError creates a new ValidationError
123+ func NewValidationError (code , message string ) * ValidationError {
124+ return & ValidationError {Code : code , Message : message }
125+ }
126+
127+ // ValidateAmount validates a token amount value
128+ func ValidateAmount (value uint64 , maxValue uint64 ) error {
129+ if value == 0 {
130+ return NewInvalidAmountError (ErrCodeZeroAmount , "token amount must be greater than zero" , value )
131+ }
132+
133+ if maxValue > 0 && value > maxValue {
134+ return NewInvalidAmountError (ErrCodeAmountExceedsMax , "token amount exceeds maximum allowed value" , value )
135+ }
136+
137+ return nil
138+ }
139+
140+ // ValidateAddress validates a recipient address
141+ func ValidateAddress (address []byte ) error {
142+ if len (address ) == 0 {
143+ return NewInvalidAddressError (ErrCodeEmptyAddress , "address cannot be empty" , nil )
144+ }
145+
146+ if len (address ) > MaxAddressLength {
147+ return NewInvalidAddressError (ErrCodeMalformedAddress , "address exceeds maximum length" , len (address ))
148+ }
149+
150+ return nil
151+ }
152+
153+ // ValidateTokenType validates a token type
154+ func ValidateTokenType (tokenType string ) error {
155+ if tokenType == "" {
156+ return NewInvalidTokenTypeError (ErrCodeEmptyTokenType , "token type cannot be empty" , tokenType )
157+ }
158+
159+ return nil
160+ }
161+
162+ // ValidateMetadata validates metadata fields
163+ func ValidateMetadata (metadata map [string ]interface {}) error {
164+ if metadata == nil {
165+ return nil
166+ }
167+
168+ for key , value := range metadata {
169+ if len (key ) == 0 {
170+ return NewInvalidMetadataError (ErrCodeInvalidMetadata , "metadata key cannot be empty" , key )
171+ }
172+
173+ // Check size for byte slice values
174+ if bytes , ok := value .([]byte ); ok {
175+ if len (bytes ) > MaxMetadataSize {
176+ return NewInvalidMetadataError (ErrCodeMetadataTooLarge , "metadata value exceeds maximum size" , key )
177+ }
178+ }
179+ }
180+
181+ return nil
182+ }
183+
184+ // ValidateTransferValues validates transfer values and owners
185+ func ValidateTransferValues (values []uint64 , owners [][]byte , maxValue uint64 ) error {
186+ if len (values ) == 0 {
187+ return NewValidationError (ErrCodeInvalidInput , "values cannot be empty" )
188+ }
189+
190+ if len (owners ) == 0 {
191+ return NewValidationError (ErrCodeInvalidInput , "owners cannot be empty" )
192+ }
193+
194+ if len (values ) != len (owners ) {
195+ return NewValidationError (ErrCodeInvalidInput , "values and owners must have the same length" )
196+ }
197+
198+ for i , v := range values {
199+ if err := ValidateAmount (v , maxValue ); err != nil {
200+ return errors .Wrapf (err , "value at index %d" , i )
201+ }
202+ }
203+
204+ for i , o := range owners {
205+ if err := ValidateAddress (o ); err != nil {
206+ return errors .Wrapf (err , "owner at index %d" , i )
207+ }
208+ }
209+
210+ return nil
211+ }
212+
213+ // ValidateRedeemValue validates a redeem value
214+ func ValidateRedeemValue (value uint64 , maxValue uint64 ) error {
215+ return ValidateAmount (value , maxValue )
216+ }
0 commit comments