-
Notifications
You must be signed in to change notification settings - Fork 170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Cairo0 Class Hash #2111
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2111 +/- ##
==========================================
+ Coverage 78.41% 78.55% +0.14%
==========================================
Files 102 103 +1
Lines 9205 9396 +191
==========================================
+ Hits 7218 7381 +163
- Misses 1351 1368 +17
- Partials 636 647 +11 ☔ View full report in Codecov by Sentry. |
576d121
to
f3478de
Compare
83460fc
to
96cce04
Compare
96cce04
to
c5c3ae4
Compare
c5c3ae4
to
e9692e2
Compare
a926956
to
be4f41c
Compare
var wg sync.WaitGroup | ||
var externalEntryPointHash, l1HandlerEntryPointHash, constructorEntryPointHash, builtInsHash, dataHash *felt.Felt | ||
var hintedClassHash *felt.Felt | ||
var hintedClassHashErr error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can improve this logic by:
- replace
sync.WaitGroup
withconc.NewWaitGroup()
- move common logic for EntryPoints in lambda and reuse it for
External
,L1Handler
andConstructor
slices - as a consequence remove all digest variables below
i.e.:
var externalEntryPointHash, l1HandlerEntryPointHash, constructorEntryPointHash, builtInsHash, dataHash *felt.Felt
var hintedClassHash *felt.Felt
var hintedClassHashErr error
entryPointsDigest := func(entryPoints []starknet.EntryPoint) *felt.Felt {
var epDigest crypto.PedersenDigest
for _, ep := range entryPoints {
epDigest.Update(ep.Selector, ep.Offset)
}
return epDigest.Finish()
}
wg := conc.NewWaitGroup()
wg.Go(func() {
externalEntryPointHash = entryPointsDigest(definition.EntryPoints.External)
})
wg.Go(func() {
l1HandlerEntryPointHash = entryPointsDigest(definition.EntryPoints.L1Handler)
})
wg.Go(func() {
constructorEntryPointHash = entryPointsDigest(definition.EntryPoints.Constructor)
})
wg.Go(func() {
var builtInsDigest crypto.PedersenDigest
for _, builtIn := range program.Builtins {
builtInHex := hex.EncodeToString([]byte(builtIn))
builtInFelt, err := new(felt.Felt).SetString("0x" + builtInHex)
if err != nil {
return
}
builtInsDigest.Update(builtInFelt)
}
builtInsHash = builtInsDigest.Finish()
})
wg.Go(func() {
hintedClassHash, hintedClassHashErr = computeHintedClassHash(definition.Abi, definition.Program)
})
wg.Go(func() {
var dataDigest crypto.PedersenDigest
for _, data := range program.Data {
dataFelt, err := new(felt.Felt).SetString(data)
if err != nil {
return
}
dataDigest.Update(dataFelt)
}
dataHash = dataDigest.Finish()
})
wg.Wait()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and btw are you sure that .SetString("0x" + builtInHex)
is necessery?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, hex.EncodeToString
outputs the hexadecimal representation without 0x
prefix. felt.SetString
requires the parsed string to have 0x
prefix. You can check felt_test.go
and verify the usage.
Here's a quick code snippet that you can verify hex encoding output in go playground:
package main
import (
"encoding/hex"
"fmt"
)
func main() {
// Sample data to encode
data := []byte("Hello, Hex Encoding!")
// Encode the data to hexadecimal string
hexString := hex.EncodeToString(data)
// Print the result
fmt.Printf("Original: %s\n", data)
fmt.Printf("Hex encoded: %s\n", hexString)
}
// computeHintedClassHash calculates the hinted class hash by hashing the JSON combination | ||
// of ABI and Program. | ||
func computeHintedClassHash(abi, program json.RawMessage) (*felt.Felt, error) { | ||
var mProgram Program |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does "m" mean in mProgram
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modified program :D
core/class.go
Outdated
} | ||
|
||
// Combine both ABI and Program JSON strings | ||
var hintedClassHashJSON strings.Builder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to replace it with bytes.Buffer
it has almost the same API, but there is no need to cast to []byte from string at the bottom because we can just call buffer.Bytes()
if err := json.Unmarshal(jsonBytes, &jsonData); err != nil { | ||
return "", err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't jsonData
is the same as value
at this point ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed value
from any
to json.RawMessage
be4f41c
to
e493ea1
Compare
Description
This PR replaces the implementation of the Cairo0 class hash function from FFI to non-FFI (i.e. implement it directly in Golang).
Rationale
Why this function was implemented using FFI:
Using FFI removes the inconveniences. However, this means that other applications using Juno as a library must also do Rust compilation. It is not library-friendly at all means. While we also have
starknet/rust
andvm/rust
, removingcore/rust
would at least reduce the surface area of using FFI, making it more library-friendly.Now that new Cairo0 classes are no longer available, we can rewrite it in a more brute-force manner. That is, do a bunch of string formatting. The performance comparison shows that it is about 27% slower than using FFI (due to a bunch of string formatting), I think it's still worth switching over to the non-FFI implementation.
Test suites
Tested this non-FFI implementation against all cairo0 class hashes on Starknet mainnet and sepolia, all passes.
FFI vs NoFFI