@@ -118,15 +118,9 @@ func (c *SierraClass) Version() uint64 {
118118}
119119
120120func (c * SierraClass ) Hash () (felt.Felt , error ) {
121- externalEntryPointsHash := crypto .PoseidonArray (
122- flattenSierraEntryPoints (c .EntryPoints .External )... ,
123- )
124- l1HandlerEntryPointsHash := crypto .PoseidonArray (
125- flattenSierraEntryPoints (c .EntryPoints .L1Handler )... ,
126- )
127- constructorHash := crypto .PoseidonArray (
128- flattenSierraEntryPoints (c .EntryPoints .Constructor )... ,
129- )
121+ externalEntryPointsHash := sierraEntryPointsHash (c .EntryPoints .External )
122+ l1HandlerEntryPointsHash := sierraEntryPointsHash (c .EntryPoints .L1Handler )
123+ constructorHash := sierraEntryPointsHash (c .EntryPoints .Constructor )
130124 return crypto .PoseidonArray (
131125 felt.NewFromBytes [felt.Felt ]([]byte ("CONTRACT_CLASS_V" + c .SemanticVersion )),
132126 & externalEntryPointsHash ,
@@ -216,20 +210,20 @@ var compiledClassV1Prefix = felt.NewFromBytes[felt.Felt]([]byte("COMPILED_CLASS_
216210
217211// Hash computes the class hash using the specified hash version
218212func (c * CasmClass ) Hash (version CasmHashVersion ) felt.Felt {
219- h := NewCasmHasher (version )
213+ hasher := NewCasmHasher (version )
220214
221215 var bytecodeHash felt.Felt
222216 if len (c .BytecodeSegmentLengths .Children ) == 0 {
223- bytecodeHash = h .HashArray (c .Bytecode ... )
217+ bytecodeHash = hasher .HashArray (c .Bytecode ... )
224218 } else {
225- bytecodeHash = SegmentedBytecodeHash (c .Bytecode , c .BytecodeSegmentLengths .Children , h )
219+ bytecodeHash = SegmentedBytecodeHash (c .Bytecode , c .BytecodeSegmentLengths .Children , hasher )
226220 }
227221
228- externalEntryPointsHash := h . HashArray ( flattenCompiledEntryPoints ( c .External , h ) ... )
229- l1HandlerEntryPointsHash := h . HashArray ( flattenCompiledEntryPoints ( c .L1Handler , h ) ... )
230- constructorHash := h . HashArray ( flattenCompiledEntryPoints ( c .Constructor , h ) ... )
222+ externalEntryPointsHash := compiledEntryPointsHash ( c .External , hasher )
223+ l1HandlerEntryPointsHash := compiledEntryPointsHash ( c .L1Handler , hasher )
224+ constructorHash := compiledEntryPointsHash ( c .Constructor , hasher )
231225
232- return h .HashArray (
226+ return hasher .HashArray (
233227 compiledClassV1Prefix ,
234228 & externalEntryPointsHash ,
235229 & l1HandlerEntryPointsHash ,
@@ -241,13 +235,13 @@ func (c *CasmClass) Hash(version CasmHashVersion) felt.Felt {
241235func SegmentedBytecodeHash (
242236 bytecode []* felt.Felt ,
243237 segmentLengths []SegmentLengths ,
244- h Hasher ,
238+ hasher Hasher ,
245239) felt.Felt {
246240 var startingOffset uint64
247241 var digestSegment func (segments []SegmentLengths ) (uint64 , felt.Felt )
248242 digestSegment = func (segments []SegmentLengths ) (uint64 , felt.Felt ) {
249243 var totalLength uint64
250- digest := h .NewDigest ()
244+ digest := hasher .NewDigest ()
251245
252246 for _ , segment := range segments {
253247 var curSegmentLength uint64
@@ -256,7 +250,7 @@ func SegmentedBytecodeHash(
256250 if len (segment .Children ) == 0 {
257251 curSegmentLength = segment .Length
258252 segmentBytecode := bytecode [startingOffset : startingOffset + segment .Length ]
259- curSegmentHash = h .HashArray (segmentBytecode ... )
253+ curSegmentHash = hasher .HashArray (segmentBytecode ... )
260254 } else {
261255 curSegmentLength , curSegmentHash = digestSegment (segment .Children )
262256 }
@@ -277,33 +271,40 @@ func SegmentedBytecodeHash(
277271 return hash
278272}
279273
280- func flattenSierraEntryPoints ( entryPoints [] SierraEntryPoint ) [] * felt. Felt {
281- result := make ([] * felt.Felt , len ( entryPoints ) * 2 )
282- for i , entryPoint := range entryPoints {
283- // It is important that Selector is first because the order
284- // influences the class hash.
285- result [ 2 * i ] = entryPoint . Selector
286- result [ 2 * i + 1 ] = felt. NewFromUint64 [felt. Felt ]( entryPoint . Index )
274+ // Order matters (selector then index): it influences the class hash.
275+ func sierraEntryPointsHash ( entryPoints [] SierraEntryPoint ) felt.Felt {
276+ var digest crypto. PoseidonDigest
277+ for _ , ep := range entryPoints {
278+ var index felt. Felt
279+ index . SetUint64 ( ep . Index )
280+ digest . Update ( ep . Selector , & index )
287281 }
288- return result
289- }
290-
291- func flattenCompiledEntryPoints (entryPoints []CasmEntryPoint , h Hasher ) []* felt.Felt {
292- result := make ([]* felt.Felt , len (entryPoints )* 3 )
293- for i , entryPoint := range entryPoints {
294- // It is important that Selector is first, then Offset is second because the order
295- // influences the class hash.
296- result [3 * i ] = entryPoint .Selector
297- result [3 * i + 1 ] = felt.NewFromUint64 [felt.Felt ](entryPoint .Offset )
298- builtins := make ([]* felt.Felt , len (entryPoint .Builtins ))
299- for idx , buil := range entryPoint .Builtins {
300- builtins [idx ] = felt.NewFromBytes [felt.Felt ]([]byte (buil ))
301- }
302- builtinsHash := h .HashArray (builtins ... )
303- result [3 * i + 2 ] = & builtinsHash
282+ return digest .Finish ()
283+ }
284+
285+ // Order matters (selector, offset, builtins hash): it influences the class hash.
286+ func compiledEntryPointsHash (entryPoints []CasmEntryPoint , hasher Hasher ) felt.Felt {
287+ digest := hasher .NewDigest ()
288+ // Passing &offset and &builtinsHash to digest.Update (an interface call)
289+ // makes the compiler heap-allocate them. Declaring them once and reusing
290+ // them keeps that to a single allocation instead of one per entry point.
291+ var offset , builtinsHash felt.Felt
292+ for _ , ep := range entryPoints {
293+ offset .SetUint64 (ep .Offset )
294+ builtinsHash = compiledBuiltinsHash (ep .Builtins , hasher )
295+ digest .Update (ep .Selector , & offset , & builtinsHash )
304296 }
297+ return digest .Finish ()
298+ }
305299
306- return result
300+ func compiledBuiltinsHash (builtins []string , hasher Hasher ) felt.Felt {
301+ digest := hasher .NewDigest ()
302+ var b felt.Felt
303+ for i := range builtins {
304+ b .SetBytes ([]byte (builtins [i ]))
305+ digest .Update (& b )
306+ }
307+ return digest .Finish ()
307308}
308309
309310func VerifyClassHashes (classes map [felt.Felt ]ClassDefinition ) error {
0 commit comments