Skip to content

Commit

Permalink
Cairo Zero Parser (#40)
Browse files Browse the repository at this point in the history
* feat: rename program to starknet

* chore(makefile): add pre-commit

* fix: format issues

* feat: add zero parser and test (#23)

* Remove unused package

* Update Json structure

* Update parsing tests

---------

Co-authored-by: Rodrigo <rodrodpino@gmail.com>
  • Loading branch information
krafugo and rodrigo-pino committed Sep 13, 2023
1 parent 4949807 commit b8004e5
Show file tree
Hide file tree
Showing 10 changed files with 562 additions and 31 deletions.
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build clean test help
.PHONY: build clean test help format staticcheck pre-commit

BINARY_DIR := bin
BINARY_NAME := cairo-vm
Expand Down Expand Up @@ -30,3 +30,11 @@ clean:
test:
@echo "Running tests..."
@go test ./...

format:
@gofumpt -l -w .

staticcheck:
@staticcheck ./...

pre-commit: format staticcheck build test clean
2 changes: 1 addition & 1 deletion cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: cairo-vm <path_to_file>")
fmt.Println("Usage: cairo-vm <path_to_file>")
os.Exit(1)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/parsers/starknet/hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const (
FieldSqrtName HintName = "FieldSqrt"
DebugPrintName HintName = "DebugPrint"
AllocConstantSizeName HintName = "AllocConstantSize"
//Name Deprecated hints
// Name Deprecated hints
AssertCurrentAccessIndicesIsEmptyName HintName = "AssertCurrentAccessIndicesIsEmpty"
AssertAllAccessesUsedName HintName = "AssertAllAccessesUsed"
AssertAllKeysUsedName HintName = "AssertAllKeysUsed"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,23 +131,23 @@ func (hints *Hints) MarshalJSON() ([]byte, error) {
return json.Marshal(rawHints)
}

type Program struct {
type StarknetProgram struct {
// Prime is fixed to be 0x800000000000011000000000000000000000000000000000000000000000001 and wont fit in a f.Felt
Bytecode []f.Element `json:"bytecode"`
CompilerVersion string `json:"compiler_version"`
EntryPoints EntryPointByType `json:"entry_points_by_type"`
Hints []Hints `json:"hints" validate:"required"`
}

func ProgramFromFile(pathToFile string) (*Program, error) {
func StarknetProgramFromFile(pathToFile string) (*StarknetProgram, error) {
content, error := os.ReadFile(pathToFile)
if error != nil {
return nil, error
}
return ProgramFromJSON(content)
return StarknetProgramFromJSON(content)
}

func ProgramFromJSON(content json.RawMessage) (*Program, error) {
var program Program
return &program, json.Unmarshal(content, &program)
func StarknetProgramFromJSON(content json.RawMessage) (*StarknetProgram, error) {
var starknet StarknetProgram
return &starknet, json.Unmarshal(content, &starknet)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ func TestCompilerVersionParsing(t *testing.T) {
"compiler_version": "2.1.0"
}
`)
program, err := ProgramFromJSON(testData)
starknet, err := StarknetProgramFromJSON(testData)
require.NoError(t, err)
assert.Equal(t, "2.1.0", program.CompilerVersion)
assert.Equal(t, "2.1.0", starknet.CompilerVersion)
}

func TestByteCodeParsing(t *testing.T) {
Expand All @@ -30,11 +30,10 @@ func TestByteCodeParsing(t *testing.T) {
]
}
`)
program, err := ProgramFromJSON(testData)
starknet, err := StarknetProgramFromJSON(testData)
require.NoError(t, err)
assert.Len(t, program.Bytecode, 4)
assert.Equal(t, "482680017ffa8000", program.Bytecode[2].Text(16))

assert.Len(t, starknet.Bytecode, 4)
assert.Equal(t, "482680017ffa8000", starknet.Bytecode[2].Text(16))
}

func TestEmptyEntryPointTypeParsing(t *testing.T) {
Expand All @@ -47,14 +46,13 @@ func TestEmptyEntryPointTypeParsing(t *testing.T) {
}
}
`)
program, err := ProgramFromJSON(testData)
starknet, err := StarknetProgramFromJSON(testData)
require.NoError(t, err)

entryPoints := program.EntryPoints
entryPoints := starknet.EntryPoints
assert.Empty(t, entryPoints.External)
assert.Empty(t, entryPoints.L1Handler)
assert.Empty(t, entryPoints.Constructor)

}

func TestEntryPointInfoParsing(t *testing.T) {
Expand Down Expand Up @@ -83,10 +81,10 @@ func TestEntryPointInfoParsing(t *testing.T) {
}
}
`)
program, err := ProgramFromJSON(testData)
starknet, err := StarknetProgramFromJSON(testData)
require.NoError(t, err)

entryPoints := program.EntryPoints
entryPoints := starknet.EntryPoints
assert.Len(t, entryPoints.External, 1)

entryPointInfo := entryPoints.External[0]
Expand Down Expand Up @@ -135,18 +133,18 @@ func TestHintsParsing(t *testing.T) {
]
}
`)
program, err := ProgramFromJSON(testData)
starknet, err := StarknetProgramFromJSON(testData)
require.NoError(t, err)

hints := program.Hints
hints := starknet.Hints
assert.Len(t, hints, 5)

hint := hints[0].Hints[0]
assert.Equal(t, hint.Name, TestLessThanOrEqualName)
_, ok := hint.Args.(*TestLessThanOrEqual)
assert.True(t, ok)

assert.NoError(t, v.Struct(program))
assert.NoError(t, v.Struct(starknet))
}

func TestInvalidBuiltin(t *testing.T) {
Expand All @@ -167,7 +165,6 @@ func TestInvalidBuiltin(t *testing.T) {
}
}
`)
_, err := ProgramFromJSON(testData)
_, err := StarknetProgramFromJSON(testData)
assert.Error(t, err)

}
109 changes: 109 additions & 0 deletions pkg/parsers/zero/zero.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package zero

import (
"encoding/json"
starknetParser "github.com/NethermindEth/cairo-vm-go/pkg/parsers/starknet"
"os"
)

type FlowTrackingData struct {
ApTracking ApTracking `json:"ap_tracking"`
ReferenceIds map[string]uint64 `json:"reference_ids"`
}

type ApTracking struct {
Group int `json:"group"`
Offset int `json:"offset"`
}

type Location struct {
EndCol uint64 `json:"end_col"`
EndLine uint64 `json:"end_line"`
InputFile map[string]string `json:"input_file"`
StartCol uint64 `json:"start_col"`
StartLine uint64 `json:"start_line"`
}

type HintLocation struct {
Location Location `json:"location"`
NPrefixNewlines uint64 `json:"n_prefix_newlines"`
}

type InstructionLocation struct {
AccessibleScopes []string `json:"accessible_scopes"`
FlowTrackingData FlowTrackingData `json:"flow_tracking_data"`
Hints []HintLocation `json:"hints"`
Inst Location `json:"inst"`
}

type DebugInfo struct {
FileContents map[string]string `json:"file_contents"`
InstructionLocations map[string]InstructionLocation `json:"instruction_locations"`
SourceCode string `json:"source_code"`
SourcePath string `json:"source_path"`
}

type Hint struct {
AccessibleScopes []string `json:"accessible_scopes"`
Code string `json:"code"`
FlowTrackingData FlowTrackingData `json:"flow_tracking_data"`
}

type Reference struct {
ApTrackingData ApTracking `json:"ap_tracking_data"`
Pc uint64 `json:"pc"`
Value string `json:"value"`
}

type ReferenceManager struct {
References []Reference
}

type AttributeScope struct {
StartPc uint64 `json:"start_pc"`
EndPc uint64 `json:"end_pc"`
FlowTrackingData FlowTrackingData `json:"flow_tracking_data"`
AccessibleScopes []string `json:"accessible_scopes"`
}

type ZeroProgram struct {
Prime string `json:"prime"`
Data []string `json:"data"`
Builtins []starknetParser.Builtin `json:"builtins"`
Hints map[string][]Hint `json:"hints"`
CompilerVersion string `json:"version"`
MainScope string `json:"main_scope"`
Identifiers map[string]any `json:"identifiers"`
ReferenceManager ReferenceManager `json:"reference_manager"`
Attributes []AttributeScope `json:"attributes"`
DebugInfo DebugInfo `json:"debug_info"`
}

func (z ZeroProgram) MarshalToFile(filepath string) error {
// Marshal Output struct into JSON bytes
data, err := json.MarshalIndent(z, "", " ")
if err != nil {
return err
}

// Write JSON bytes to file
err = os.WriteFile(filepath, data, 0644)
if err != nil {
return err
}

return nil
}

func ZeroProgramFromFile(filepath string) (zero *ZeroProgram, err error) {
content, err := os.ReadFile(filepath)
if err != nil {
return
}
return ZeroProgramFromJSON(content)
}

func ZeroProgramFromJSON(content json.RawMessage) (*ZeroProgram, error) {
var zero ZeroProgram
return &zero, json.Unmarshal(content, &zero)
}
Loading

0 comments on commit b8004e5

Please sign in to comment.