From 9bad6dccd795b8fc24e3d452425c7ca02e7aa868 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 18:44:50 +0530 Subject: [PATCH 01/14] Add basic air public input technology --- cmd/cli/main.go | 30 ++++++++++++++++++++++++++++++ pkg/runners/zero/zero.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 4e1ed773..6c843997 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "fmt" "math" "os" @@ -20,6 +21,8 @@ func main() { var traceLocation string var memoryLocation string var layoutName string + var airPublicInputLocation string + var airPrivateInputLocation string app := &cli.App{ Name: "cairo-vm", Usage: "A cairo virtual machine", @@ -81,6 +84,18 @@ func main() { Required: false, Destination: &layoutName, }, + &cli.StringFlag{ + Name: "air_public_input", + Usage: "location to store the air_public_input", + Required: false, + Destination: &airPublicInputLocation, + }, + &cli.StringFlag{ + Name: "air_private_input", + Usage: "location to store the air_private_input", + Required: false, + Destination: &airPrivateInputLocation, + }, }, Action: func(ctx *cli.Context) error { // TODO: move this action's body to a separate function to decrease the @@ -167,6 +182,21 @@ func main() { } } + if proofmode && airPublicInputLocation != "" { + airPublicInput, err := runner.GetAirPublicInput() + if err != nil { + return err + } + airPublicInputJson, err := json.MarshalIndent(airPublicInput, "", " ") + if err != nil { + return err + } + err = os.WriteFile(airPublicInputLocation, airPublicInputJson, 0644) + if err != nil { + return fmt.Errorf("cannot write air_public_input: %w", err) + } + } + fmt.Println("Success!") output := runner.Output() if len(output) > 0 { diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index 9980524d..a554ca86 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -418,3 +418,38 @@ func (runner *ZeroRunner) Output() []*fp.Element { } return output } + +func (runner *ZeroRunner) GetAirPublicInput() (AirPublicInput, error) { + rcMin, rcMax := runner.getPermRangeCheckLimits() + return AirPublicInput{ + Layout: runner.layout.Name, + RcMin: rcMin, + RcMax: rcMax, + // optimise this away + NSteps: len(runner.vm.RelocateTrace()), + DynamicParams: nil, + MemorySegments: make(map[string]AirMemorySegmentEntry), + PublicMemory: make([]AirPublicMemoryEntry, 0), + }, nil +} + +type AirPublicInput struct { + Layout string `json:"layout"` + RcMin uint16 `json:"rc_min"` + RcMax uint16 `json:"rc_max"` + NSteps int `json:"n_steps"` + DynamicParams interface{} `json:"dynamic_params"` + MemorySegments map[string]AirMemorySegmentEntry `json:"memory_segments"` + PublicMemory []AirPublicMemoryEntry `json:"public_memory"` +} + +type AirMemorySegmentEntry struct { + BeginAddr int `json:"begin_addr"` + StopPtr int `json:"stop_ptr"` +} + +type AirPublicMemoryEntry struct { + Address uint16 `json:"address"` + Value string `json:"value"` + Page uint16 `json:"page"` +} From 18c87206d1262bdb3490d6f4ee601a0c79677b63 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 20:39:38 +0530 Subject: [PATCH 02/14] Iterate on air private input --- cmd/cli/main.go | 48 ++++++++++++++++++++++++++++--------- pkg/runners/zero/zero.go | 51 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 11 deletions(-) diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 6c843997..7a0eff81 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "os" + "path/filepath" hintrunner "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/zero" zero "github.com/NethermindEth/cairo-vm-go/pkg/parsers/zero" @@ -182,18 +183,43 @@ func main() { } } - if proofmode && airPublicInputLocation != "" { - airPublicInput, err := runner.GetAirPublicInput() - if err != nil { - return err - } - airPublicInputJson, err := json.MarshalIndent(airPublicInput, "", " ") - if err != nil { - return err + if proofmode { + if airPublicInputLocation != "" { + airPublicInput, err := runner.GetAirPublicInput() + if err != nil { + return err + } + airPublicInputJson, err := json.MarshalIndent(airPublicInput, "", " ") + if err != nil { + return err + } + err = os.WriteFile(airPublicInputLocation, airPublicInputJson, 0644) + if err != nil { + return fmt.Errorf("cannot write air_public_input: %w", err) + } } - err = os.WriteFile(airPublicInputLocation, airPublicInputJson, 0644) - if err != nil { - return fmt.Errorf("cannot write air_public_input: %w", err) + + if airPrivateInputLocation != "" { + tracePath, err := filepath.Abs(traceLocation) + if err != nil { + return err + } + memoryPath, err := filepath.Abs(memoryLocation) + if err != nil { + return err + } + airPrivateInput, err := runner.GetAirPrivateInput(tracePath, memoryPath) + if err != nil { + return err + } + airPrivateInputJson, err := json.MarshalIndent(airPrivateInput, "", " ") + if err != nil { + return err + } + err = os.WriteFile(airPrivateInputLocation, airPrivateInputJson, 0644) + if err != nil { + return fmt.Errorf("cannot write air_private_input: %w", err) + } } } diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index a554ca86..d4097bae 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -3,6 +3,7 @@ package zero import ( "errors" "fmt" + "math/big" "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner" "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" @@ -453,3 +454,53 @@ type AirPublicMemoryEntry struct { Value string `json:"value"` Page uint16 `json:"page"` } + +func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirPrivateInput, error) { + airPrivateInput := AirPrivateInput{ + TracePath: tracePath, + MemoryPath: memoryPath, + } + + for _, bRunner := range runner.layout.Builtins { + builtinName := bRunner.Runner.String() + builtinSegment, ok := runner.vm.Memory.FindSegmentWithBuiltin(builtinName) + if ok { + switch builtinName { + case "range_check": + { + var builtinValue []AirPrivateBuiltinValue + for index, value := range builtinSegment.Data { + // some checks might be missing here + if !value.Known() { + continue + } + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + builtinValue = append(builtinValue, AirPrivateBuiltinValue{Index: index, Value: fmt.Sprintf("0x%x", &valueBig)}) + } + airPrivateInput.RangeCheck = builtinValue + } + } + } + } + + return airPrivateInput, nil +} + +type AirPrivateInput struct { + TracePath string `json:"trace_path"` + MemoryPath string `json:"memory_path"` + Output []AirPrivateBuiltinValue `json:"output,omitempty"` + Pedersen []AirPrivateBuiltinValue `json:"pedersen,omitempty"` + RangeCheck []AirPrivateBuiltinValue `json:"range_check,omitempty"` + Ecdsa []AirPrivateBuiltinValue `json:"ecdsa,omitempty"` + Bitwise []AirPrivateBuiltinValue `json:"bitwise,omitempty"` + EcOp []AirPrivateBuiltinValue `json:"ec_op,omitempty"` + Keccak []AirPrivateBuiltinValue `json:"keccak,omitempty"` + Poseidon []AirPrivateBuiltinValue `json:"poseidon,omitempty"` +} + +type AirPrivateBuiltinValue struct { + Index int `json:"index"` + Value string `json:"value"` +} From 06afaa7c5e0ef0725a092b6fb6c8d9cad8a10256 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 21:15:54 +0530 Subject: [PATCH 03/14] Iterate on air private input with bitwise --- pkg/runners/zero/zero.go | 80 +++++++++++++++++++++++++++++++------- pkg/vm/builtins/bitwise.go | 6 +-- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index d4097bae..50ab9c50 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math/big" + "sort" "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner" "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" @@ -465,20 +466,63 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP builtinName := bRunner.Runner.String() builtinSegment, ok := runner.vm.Memory.FindSegmentWithBuiltin(builtinName) if ok { + // some checks might be missing here switch builtinName { case "range_check": { - var builtinValue []AirPrivateBuiltinValue + var builtinValues []AirPrivateBuiltinIndexValue for index, value := range builtinSegment.Data { - // some checks might be missing here if !value.Known() { continue } valueBig := big.Int{} value.Felt.BigInt(&valueBig) - builtinValue = append(builtinValue, AirPrivateBuiltinValue{Index: index, Value: fmt.Sprintf("0x%x", &valueBig)}) + builtinValues = append(builtinValues, AirPrivateBuiltinIndexValue{Index: index, Value: fmt.Sprintf("0x%x", &valueBig)}) + } + airPrivateInput.RangeCheck = builtinValues + } + case "bitwise": + { + { + valueMapping := make(map[int]AirPrivateBuiltinIndexXY) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/builtins.CellsPerBitwise, index%builtins.CellsPerBitwise + if typ >= 2 { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinIndexXY{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + if typ == 0 { + builtinValue.X = fmt.Sprintf("0x%x", &valueBig) + } else { + builtinValue.Y = fmt.Sprintf("0x%x", &valueBig) + } + valueMapping[idx] = builtinValue + } + + var builtinValues []AirPrivateBuiltinIndexXY + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Bitwise = builtinValues } - airPrivateInput.RangeCheck = builtinValue } } } @@ -488,19 +532,25 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP } type AirPrivateInput struct { - TracePath string `json:"trace_path"` - MemoryPath string `json:"memory_path"` - Output []AirPrivateBuiltinValue `json:"output,omitempty"` - Pedersen []AirPrivateBuiltinValue `json:"pedersen,omitempty"` - RangeCheck []AirPrivateBuiltinValue `json:"range_check,omitempty"` - Ecdsa []AirPrivateBuiltinValue `json:"ecdsa,omitempty"` - Bitwise []AirPrivateBuiltinValue `json:"bitwise,omitempty"` - EcOp []AirPrivateBuiltinValue `json:"ec_op,omitempty"` - Keccak []AirPrivateBuiltinValue `json:"keccak,omitempty"` - Poseidon []AirPrivateBuiltinValue `json:"poseidon,omitempty"` + TracePath string `json:"trace_path"` + MemoryPath string `json:"memory_path"` + Output []AirPrivateBuiltinIndexValue `json:"output,omitempty"` + Pedersen []AirPrivateBuiltinIndexValue `json:"pedersen,omitempty"` + RangeCheck []AirPrivateBuiltinIndexValue `json:"range_check,omitempty"` + Ecdsa []AirPrivateBuiltinIndexValue `json:"ecdsa,omitempty"` + Bitwise []AirPrivateBuiltinIndexXY `json:"bitwise,omitempty"` + EcOp []AirPrivateBuiltinIndexValue `json:"ec_op,omitempty"` + Keccak []AirPrivateBuiltinIndexValue `json:"keccak,omitempty"` + Poseidon []AirPrivateBuiltinIndexValue `json:"poseidon,omitempty"` } -type AirPrivateBuiltinValue struct { +type AirPrivateBuiltinIndexValue struct { Index int `json:"index"` Value string `json:"value"` } + +type AirPrivateBuiltinIndexXY struct { + Index int `json:"index"` + X string `json:"x"` + Y string `json:"y"` +} diff --git a/pkg/vm/builtins/bitwise.go b/pkg/vm/builtins/bitwise.go index b498a321..6832d303 100644 --- a/pkg/vm/builtins/bitwise.go +++ b/pkg/vm/builtins/bitwise.go @@ -10,7 +10,7 @@ import ( const BitwiseName = "bitwise" -const cellsPerBitwise = 5 +const CellsPerBitwise = 5 const inputCellsPerBitwise = 2 const instancesPerComponentBitwise = 1 @@ -25,7 +25,7 @@ func (b *Bitwise) CheckWrite( } func (b *Bitwise) InferValue(segment *memory.Segment, offset uint64) error { - bitwiseIndex := offset % cellsPerBitwise + bitwiseIndex := offset % CellsPerBitwise // input cell if bitwiseIndex < inputCellsPerBitwise { return errors.New("cannot infer value from input cell") @@ -98,5 +98,5 @@ func (b *Bitwise) String() string { } func (b *Bitwise) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, b.ratio, inputCellsPerBitwise, instancesPerComponentBitwise, cellsPerBitwise) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, b.ratio, inputCellsPerBitwise, instancesPerComponentBitwise, CellsPerBitwise) } From 3f921f73a62749a6dc3a2d26f6cefff7d95e9711 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 21:32:59 +0530 Subject: [PATCH 04/14] Iterate on air private input with poseidon --- pkg/runners/zero/zero.go | 139 ++++++++++++++++++++++++------------ pkg/vm/builtins/poseidon.go | 14 ++-- 2 files changed, 101 insertions(+), 52 deletions(-) diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index 50ab9c50..2c2a159a 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -470,59 +470,101 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP switch builtinName { case "range_check": { - var builtinValues []AirPrivateBuiltinIndexValue + var builtinValues []AirPrivateBuiltinRangeCheck for index, value := range builtinSegment.Data { if !value.Known() { continue } valueBig := big.Int{} value.Felt.BigInt(&valueBig) - builtinValues = append(builtinValues, AirPrivateBuiltinIndexValue{Index: index, Value: fmt.Sprintf("0x%x", &valueBig)}) + builtinValues = append(builtinValues, AirPrivateBuiltinRangeCheck{Index: index, Value: fmt.Sprintf("0x%x", &valueBig)}) } airPrivateInput.RangeCheck = builtinValues } case "bitwise": { - { - valueMapping := make(map[int]AirPrivateBuiltinIndexXY) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, typ := index/builtins.CellsPerBitwise, index%builtins.CellsPerBitwise - if typ >= 2 { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinIndexXY{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - if typ == 0 { - builtinValue.X = fmt.Sprintf("0x%x", &valueBig) - } else { - builtinValue.Y = fmt.Sprintf("0x%x", &valueBig) - } - valueMapping[idx] = builtinValue + valueMapping := make(map[int]AirPrivateBuiltinBitwise) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/builtins.CellsPerBitwise, index%builtins.CellsPerBitwise + if typ >= 2 { + continue } - var builtinValues []AirPrivateBuiltinIndexXY + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinBitwise{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + if typ == 0 { + builtinValue.X = fmt.Sprintf("0x%x", &valueBig) + } else { + builtinValue.Y = fmt.Sprintf("0x%x", &valueBig) + } + valueMapping[idx] = builtinValue + } + + var builtinValues []AirPrivateBuiltinBitwise + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Bitwise = builtinValues + + } + case "poseidon": + { + valueMapping := make(map[int]AirPrivateBuiltinPoseidon) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, stateIndex := index/builtins.CellsPerPoseidon, index%builtins.CellsPerPoseidon + if stateIndex >= builtins.InputCellsPerPoseidon { + continue + } - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinPoseidon{Index: idx} } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + if stateIndex == 0 { + builtinValue.InputS0 = fmt.Sprintf("0x%x", &valueBig) + } else if stateIndex == 1 { + builtinValue.InputS1 = fmt.Sprintf("0x%x", &valueBig) + } else if stateIndex == 2 { + builtinValue.InputS2 = fmt.Sprintf("0x%x", &valueBig) } + valueMapping[idx] = builtinValue + } + + var builtinValues []AirPrivateBuiltinPoseidon - airPrivateInput.Bitwise = builtinValues + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Poseidon = builtinValues } } } @@ -534,23 +576,30 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP type AirPrivateInput struct { TracePath string `json:"trace_path"` MemoryPath string `json:"memory_path"` - Output []AirPrivateBuiltinIndexValue `json:"output,omitempty"` - Pedersen []AirPrivateBuiltinIndexValue `json:"pedersen,omitempty"` - RangeCheck []AirPrivateBuiltinIndexValue `json:"range_check,omitempty"` - Ecdsa []AirPrivateBuiltinIndexValue `json:"ecdsa,omitempty"` - Bitwise []AirPrivateBuiltinIndexXY `json:"bitwise,omitempty"` - EcOp []AirPrivateBuiltinIndexValue `json:"ec_op,omitempty"` - Keccak []AirPrivateBuiltinIndexValue `json:"keccak,omitempty"` - Poseidon []AirPrivateBuiltinIndexValue `json:"poseidon,omitempty"` + Output []AirPrivateBuiltinRangeCheck `json:"output,omitempty"` + Pedersen []AirPrivateBuiltinRangeCheck `json:"pedersen,omitempty"` + RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check,omitempty"` + Ecdsa []AirPrivateBuiltinRangeCheck `json:"ecdsa,omitempty"` + Bitwise []AirPrivateBuiltinBitwise `json:"bitwise,omitempty"` + EcOp []AirPrivateBuiltinRangeCheck `json:"ec_op,omitempty"` + Keccak []AirPrivateBuiltinRangeCheck `json:"keccak,omitempty"` + Poseidon []AirPrivateBuiltinPoseidon `json:"poseidon,omitempty"` } -type AirPrivateBuiltinIndexValue struct { +type AirPrivateBuiltinRangeCheck struct { Index int `json:"index"` Value string `json:"value"` } -type AirPrivateBuiltinIndexXY struct { +type AirPrivateBuiltinBitwise struct { Index int `json:"index"` X string `json:"x"` Y string `json:"y"` } + +type AirPrivateBuiltinPoseidon struct { + Index int `json:"index"` + InputS0 string `json:"input_s0"` + InputS1 string `json:"input_s1"` + InputS2 string `json:"input_s2"` +} diff --git a/pkg/vm/builtins/poseidon.go b/pkg/vm/builtins/poseidon.go index 0a809313..3fd031db 100644 --- a/pkg/vm/builtins/poseidon.go +++ b/pkg/vm/builtins/poseidon.go @@ -8,8 +8,8 @@ import ( ) const PoseidonName = "poseidon" -const cellsPerPoseidon = 6 -const inputCellsPerPoseidon = 3 +const CellsPerPoseidon = 6 +const InputCellsPerPoseidon = 3 const instancesPerComponentPoseidon = 1 type Poseidon struct { @@ -27,13 +27,13 @@ func (p *Poseidon) InferValue(segment *mem.Segment, offset uint64) error { mv := mem.MemoryValueFromFieldElement(&value) return segment.Write(offset, &mv) } - poseidonIndex := offset % cellsPerPoseidon - if poseidonIndex < inputCellsPerPoseidon { + poseidonIndex := offset % CellsPerPoseidon + if poseidonIndex < InputCellsPerPoseidon { return errors.New("cannot infer value") } baseOffset := offset - poseidonIndex - poseidonInputValues := make([]*fp.Element, inputCellsPerPoseidon) - for i := 0; i < inputCellsPerPoseidon; i++ { + poseidonInputValues := make([]*fp.Element, InputCellsPerPoseidon) + for i := 0; i < InputCellsPerPoseidon; i++ { mv := segment.Peek(baseOffset + uint64(i)) if !mv.Known() { return errors.New("cannot infer value") @@ -56,7 +56,7 @@ func (p *Poseidon) InferValue(segment *mem.Segment, offset uint64) error { } func (p *Poseidon) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, p.ratio, inputCellsPerPoseidon, instancesPerComponentPoseidon, cellsPerPoseidon) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, p.ratio, InputCellsPerPoseidon, instancesPerComponentPoseidon, CellsPerPoseidon) } func (p *Poseidon) String() string { From 0876b0063d936ae51b4907ccdadb7e8772427721 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 21:38:17 +0530 Subject: [PATCH 05/14] Iterate on air private input with pedersen --- cmd/cli/main.go | 2 +- pkg/runners/zero/zero.go | 50 ++++++++++++++++++++++++++++++++++++- pkg/vm/builtins/pedersen.go | 6 ++--- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 7a0eff81..7bdd2357 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -212,7 +212,7 @@ func main() { if err != nil { return err } - airPrivateInputJson, err := json.MarshalIndent(airPrivateInput, "", " ") + airPrivateInputJson, err := json.MarshalIndent(airPrivateInput, "", " ") if err != nil { return err } diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index 2c2a159a..fc603e47 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -566,6 +566,48 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP airPrivateInput.Poseidon = builtinValues } + case "pedersen": + { + valueMapping := make(map[int]AirPrivateBuiltinPedersen) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/builtins.CellsPerPedersen, index%builtins.CellsPerPedersen + if typ == 2 { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinPedersen{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + if typ == 0 { + builtinValue.X = fmt.Sprintf("0x%x", &valueBig) + } else { + builtinValue.Y = fmt.Sprintf("0x%x", &valueBig) + } + valueMapping[idx] = builtinValue + } + + var builtinValues []AirPrivateBuiltinPedersen + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Pedersen = builtinValues + + } } } } @@ -577,7 +619,7 @@ type AirPrivateInput struct { TracePath string `json:"trace_path"` MemoryPath string `json:"memory_path"` Output []AirPrivateBuiltinRangeCheck `json:"output,omitempty"` - Pedersen []AirPrivateBuiltinRangeCheck `json:"pedersen,omitempty"` + Pedersen []AirPrivateBuiltinPedersen `json:"pedersen,omitempty"` RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check,omitempty"` Ecdsa []AirPrivateBuiltinRangeCheck `json:"ecdsa,omitempty"` Bitwise []AirPrivateBuiltinBitwise `json:"bitwise,omitempty"` @@ -603,3 +645,9 @@ type AirPrivateBuiltinPoseidon struct { InputS1 string `json:"input_s1"` InputS2 string `json:"input_s2"` } + +type AirPrivateBuiltinPedersen struct { + Index int `json:"index"` + X string `json:"x"` + Y string `json:"y"` +} diff --git a/pkg/vm/builtins/pedersen.go b/pkg/vm/builtins/pedersen.go index 6391e090..7fee2491 100644 --- a/pkg/vm/builtins/pedersen.go +++ b/pkg/vm/builtins/pedersen.go @@ -9,7 +9,7 @@ import ( ) const PedersenName = "pedersen" -const cellsPerPedersen = 3 +const CellsPerPedersen = 3 const inputCellsPerPedersen = 2 const instancesPerComponentPedersen = 1 @@ -22,7 +22,7 @@ func (p *Pedersen) CheckWrite(segment *mem.Segment, offset uint64, value *mem.Me } func (p *Pedersen) InferValue(segment *mem.Segment, offset uint64) error { - hashIndex := offset % cellsPerPedersen + hashIndex := offset % CellsPerPedersen // input cell if hashIndex < inputCellsPerPedersen { return errors.New("cannot infer value") @@ -61,5 +61,5 @@ func (p *Pedersen) String() string { } func (p *Pedersen) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, p.ratio, inputCellsPerPedersen, instancesPerComponentPedersen, cellsPerPedersen) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, p.ratio, inputCellsPerPedersen, instancesPerComponentPedersen, CellsPerPedersen) } From 10160ec36eacf7a169695dcd80853319486743d4 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 21:53:11 +0530 Subject: [PATCH 06/14] Iterate on air private input with ecop --- pkg/runners/zero/zero.go | 79 +++++++++++++++++++++++++++++++++++----- pkg/vm/builtins/ecop.go | 12 +++--- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index fc603e47..317b3034 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -477,7 +477,8 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP } valueBig := big.Int{} value.Felt.BigInt(&valueBig) - builtinValues = append(builtinValues, AirPrivateBuiltinRangeCheck{Index: index, Value: fmt.Sprintf("0x%x", &valueBig)}) + valueHex := fmt.Sprintf("0x%x", &valueBig) + builtinValues = append(builtinValues, AirPrivateBuiltinRangeCheck{Index: index, Value: valueHex}) } airPrivateInput.RangeCheck = builtinValues } @@ -500,10 +501,11 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP valueBig := big.Int{} value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) if typ == 0 { - builtinValue.X = fmt.Sprintf("0x%x", &valueBig) + builtinValue.X = valueHex } else { - builtinValue.Y = fmt.Sprintf("0x%x", &valueBig) + builtinValue.Y = valueHex } valueMapping[idx] = builtinValue } @@ -521,7 +523,6 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP } airPrivateInput.Bitwise = builtinValues - } case "poseidon": { @@ -542,12 +543,13 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP valueBig := big.Int{} value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) if stateIndex == 0 { - builtinValue.InputS0 = fmt.Sprintf("0x%x", &valueBig) + builtinValue.InputS0 = valueHex } else if stateIndex == 1 { - builtinValue.InputS1 = fmt.Sprintf("0x%x", &valueBig) + builtinValue.InputS1 = valueHex } else if stateIndex == 2 { - builtinValue.InputS2 = fmt.Sprintf("0x%x", &valueBig) + builtinValue.InputS2 = valueHex } valueMapping[idx] = builtinValue } @@ -585,10 +587,11 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP valueBig := big.Int{} value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) if typ == 0 { - builtinValue.X = fmt.Sprintf("0x%x", &valueBig) + builtinValue.X = valueHex } else { - builtinValue.Y = fmt.Sprintf("0x%x", &valueBig) + builtinValue.Y = valueHex } valueMapping[idx] = builtinValue } @@ -606,7 +609,54 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP } airPrivateInput.Pedersen = builtinValues + } + case "ec_op": + { + valueMapping := make(map[int]AirPrivateBuiltinEcOp) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/builtins.CellsPerEcOp, index%builtins.CellsPerEcOp + if typ >= builtins.InputCellsPerEcOp { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinEcOp{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if typ == 0 { + builtinValue.PX = valueHex + } else if typ == 1 { + builtinValue.PY = valueHex + } else if typ == 2 { + builtinValue.QX = valueHex + } else if typ == 3 { + builtinValue.QY = valueHex + } else if typ == 4 { + builtinValue.M = valueHex + } + valueMapping[idx] = builtinValue + } + var builtinValues []AirPrivateBuiltinEcOp + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.EcOp = builtinValues } } } @@ -623,7 +673,7 @@ type AirPrivateInput struct { RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check,omitempty"` Ecdsa []AirPrivateBuiltinRangeCheck `json:"ecdsa,omitempty"` Bitwise []AirPrivateBuiltinBitwise `json:"bitwise,omitempty"` - EcOp []AirPrivateBuiltinRangeCheck `json:"ec_op,omitempty"` + EcOp []AirPrivateBuiltinEcOp `json:"ec_op,omitempty"` Keccak []AirPrivateBuiltinRangeCheck `json:"keccak,omitempty"` Poseidon []AirPrivateBuiltinPoseidon `json:"poseidon,omitempty"` } @@ -651,3 +701,12 @@ type AirPrivateBuiltinPedersen struct { X string `json:"x"` Y string `json:"y"` } + +type AirPrivateBuiltinEcOp struct { + Index int `json:"index"` + PX string `json:"p_x"` + PY string `json:"p_y"` + M string `json:"m"` + QX string `json:"q_x"` + QY string `json:"q_y"` +} diff --git a/pkg/vm/builtins/ecop.go b/pkg/vm/builtins/ecop.go index 211d2fb4..6ba690e3 100644 --- a/pkg/vm/builtins/ecop.go +++ b/pkg/vm/builtins/ecop.go @@ -11,8 +11,8 @@ import ( ) const EcOpName = "ec_op" -const cellsPerEcOp = 7 -const inputCellsPerEcOp = 5 +const CellsPerEcOp = 7 +const InputCellsPerEcOp = 5 const instancesPerComponentEcOp = 1 var feltThree fp.Element = fp.Element( @@ -44,8 +44,8 @@ func (e *EcOp) InferValue(segment *mem.Segment, offset uint64) error { return segment.Write(offset, &mv) } // get the current slot index and verify it is an output cell - ecopIndex := offset % cellsPerEcOp - if ecopIndex < inputCellsPerEcOp { + ecopIndex := offset % CellsPerEcOp + if ecopIndex < InputCellsPerEcOp { return errors.New("cannot infer value from input cell") } @@ -99,7 +99,7 @@ func (e *EcOp) InferValue(segment *mem.Segment, offset uint64) error { } // store the resulting point `r` - outputOff := inputOff + inputCellsPerEcOp + outputOff := inputOff + InputCellsPerEcOp // store the x and y coordinates of the resulting point e.cache[outputOff] = r.X @@ -111,7 +111,7 @@ func (e *EcOp) InferValue(segment *mem.Segment, offset uint64) error { } func (e *EcOp) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, e.ratio, inputCellsPerEcOp, instancesPerComponentEcOp, cellsPerEcOp) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, e.ratio, InputCellsPerEcOp, instancesPerComponentEcOp, CellsPerEcOp) } // structure to represent a point in the elliptic curve From b5e5d1e614e564573ae738f03eb9eb34de5b622a Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 22:18:08 +0530 Subject: [PATCH 07/14] Iterate on air private input with poseidon --- .../keccak_builtin.starknet_with_keccak.cairo | 18 +++++ pkg/runners/zero/zero.go | 69 ++++++++++++++++++- pkg/vm/builtins/keccak.go | 16 ++--- 3 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 integration_tests/cairo_zero_file_tests/keccak_builtin.starknet_with_keccak.cairo diff --git a/integration_tests/cairo_zero_file_tests/keccak_builtin.starknet_with_keccak.cairo b/integration_tests/cairo_zero_file_tests/keccak_builtin.starknet_with_keccak.cairo new file mode 100644 index 00000000..be6e1717 --- /dev/null +++ b/integration_tests/cairo_zero_file_tests/keccak_builtin.starknet_with_keccak.cairo @@ -0,0 +1,18 @@ +%builtins keccak +from starkware.cairo.common.cairo_builtins import KeccakBuiltin +from starkware.cairo.common.keccak_state import KeccakBuiltinState + +func main{keccak_ptr: KeccakBuiltin*}() { + assert keccak_ptr[0].input = KeccakBuiltinState(1, 2, 3, 4, 5, 6, 7, 8); + let result = keccak_ptr[0].output; + let keccak_ptr = keccak_ptr + KeccakBuiltin.SIZE; + assert result.s0 = 528644516554364142278482415480021626364691973678134577961206; + assert result.s1 = 768681319646568210457759892191562701823009052229295869963057; + assert result.s2 = 1439835513376369408063324968379272676079109225238241190228026; + assert result.s3 = 1150396629165612276474514703759718478742374517669870754478270; + assert result.s4 = 1515147102575186161827863034255579930572231617017100845406254; + assert result.s5 = 1412568161597072838250338588041800080889949791225997426843744; + assert result.s6 = 982235455376248641031519404605670648838699214888770304613539; + assert result.s7 = 1339947803093378278438908448344904300127577306141693325151040; + return (); +} diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index 317b3034..32b53b7c 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -658,6 +658,60 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP airPrivateInput.EcOp = builtinValues } + case "keccak": + { + valueMapping := make(map[int]AirPrivateBuiltinKeccak) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, stateIndex := index/builtins.CellsPerKeccak, index%builtins.CellsPerKeccak + if stateIndex >= builtins.InputCellsPerKeccak { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinKeccak{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if stateIndex == 0 { + builtinValue.InputS0 = valueHex + } else if stateIndex == 1 { + builtinValue.InputS1 = valueHex + } else if stateIndex == 2 { + builtinValue.InputS2 = valueHex + } else if stateIndex == 3 { + builtinValue.InputS3 = valueHex + } else if stateIndex == 4 { + builtinValue.InputS4 = valueHex + } else if stateIndex == 5 { + builtinValue.InputS5 = valueHex + } else if stateIndex == 6 { + builtinValue.InputS6 = valueHex + } else if stateIndex == 7 { + builtinValue.InputS7 = valueHex + } + valueMapping[idx] = builtinValue + } + + var builtinValues []AirPrivateBuiltinKeccak + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Keccak = builtinValues + } } } } @@ -668,13 +722,12 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP type AirPrivateInput struct { TracePath string `json:"trace_path"` MemoryPath string `json:"memory_path"` - Output []AirPrivateBuiltinRangeCheck `json:"output,omitempty"` Pedersen []AirPrivateBuiltinPedersen `json:"pedersen,omitempty"` RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check,omitempty"` Ecdsa []AirPrivateBuiltinRangeCheck `json:"ecdsa,omitempty"` Bitwise []AirPrivateBuiltinBitwise `json:"bitwise,omitempty"` EcOp []AirPrivateBuiltinEcOp `json:"ec_op,omitempty"` - Keccak []AirPrivateBuiltinRangeCheck `json:"keccak,omitempty"` + Keccak []AirPrivateBuiltinKeccak `json:"keccak,omitempty"` Poseidon []AirPrivateBuiltinPoseidon `json:"poseidon,omitempty"` } @@ -710,3 +763,15 @@ type AirPrivateBuiltinEcOp struct { QX string `json:"q_x"` QY string `json:"q_y"` } + +type AirPrivateBuiltinKeccak struct { + Index int `json:"index"` + InputS0 string `json:"input_s0"` + InputS1 string `json:"input_s1"` + InputS2 string `json:"input_s2"` + InputS3 string `json:"input_s3"` + InputS4 string `json:"input_s4"` + InputS5 string `json:"input_s5"` + InputS6 string `json:"input_s6"` + InputS7 string `json:"input_s7"` +} diff --git a/pkg/vm/builtins/keccak.go b/pkg/vm/builtins/keccak.go index 00e135fb..ff03027c 100644 --- a/pkg/vm/builtins/keccak.go +++ b/pkg/vm/builtins/keccak.go @@ -18,8 +18,8 @@ import ( // const KeccakName = "keccak" -const cellsPerKeccak = 16 -const inputCellsPerKeccak = 8 +const CellsPerKeccak = 16 +const InputCellsPerKeccak = 8 const instancesPerComponentKeccak = 16 type Keccak struct { @@ -37,14 +37,14 @@ func (k *Keccak) InferValue(segment *memory.Segment, offset uint64) error { mv := memory.MemoryValueFromFieldElement(&value) return segment.Write(offset, &mv) } - hashIndex := offset % cellsPerKeccak - if hashIndex < inputCellsPerKeccak { + hashIndex := offset % CellsPerKeccak + if hashIndex < InputCellsPerKeccak { return errors.New("cannot infer value") } startOffset := offset - hashIndex var data [200]byte - for i := uint64(0); i < inputCellsPerKeccak; i++ { + for i := uint64(0); i < InputCellsPerKeccak; i++ { value := segment.Peek(startOffset + i) if !value.Known() { return fmt.Errorf("cannot infer value: input value at offset %d is unknown", startOffset+i) @@ -70,12 +70,12 @@ func (k *Keccak) InferValue(segment *memory.Segment, offset uint64) error { binary.LittleEndian.PutUint64(output[i*8:i*8+8], dataU64[i]) } - for i := 0; i < inputCellsPerKeccak; i++ { + for i := 0; i < InputCellsPerKeccak; i++ { var bytes [32]byte copy(bytes[:], output[i*25:i*25+25]) //This is 25*8 bits which is smaller than max felt 252 bits so no need to check the error v, _ := fp.LittleEndian.Element(&bytes) - k.cache[startOffset+inputCellsPerKeccak+uint64(i)] = v + k.cache[startOffset+InputCellsPerKeccak+uint64(i)] = v } value = k.cache[offset] mv := memory.MemoryValueFromFieldElement(&value) @@ -87,5 +87,5 @@ func (k *Keccak) String() string { } func (k *Keccak) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, k.ratio, inputCellsPerKeccak, instancesPerComponentKeccak, cellsPerKeccak) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, k.ratio, InputCellsPerKeccak, instancesPerComponentKeccak, CellsPerKeccak) } From 48642b6db809dcce20f7b4864c9f06df47b5194f Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 22:44:53 +0530 Subject: [PATCH 08/14] Clean up empty json response --- pkg/runners/zero/zero.go | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index 32b53b7c..0646de41 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -470,7 +470,7 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP switch builtinName { case "range_check": { - var builtinValues []AirPrivateBuiltinRangeCheck + builtinValues := make([]AirPrivateBuiltinRangeCheck, 0) for index, value := range builtinSegment.Data { if !value.Known() { continue @@ -510,7 +510,7 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP valueMapping[idx] = builtinValue } - var builtinValues []AirPrivateBuiltinBitwise + builtinValues := make([]AirPrivateBuiltinBitwise, 0) sortedIndexes := make([]int, 0, len(valueMapping)) for index := range valueMapping { @@ -554,7 +554,7 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP valueMapping[idx] = builtinValue } - var builtinValues []AirPrivateBuiltinPoseidon + builtinValues := make([]AirPrivateBuiltinPoseidon, 0) sortedIndexes := make([]int, 0, len(valueMapping)) for index := range valueMapping { @@ -596,7 +596,7 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP valueMapping[idx] = builtinValue } - var builtinValues []AirPrivateBuiltinPedersen + builtinValues := make([]AirPrivateBuiltinPedersen, 0) sortedIndexes := make([]int, 0, len(valueMapping)) for index := range valueMapping { @@ -644,7 +644,7 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP valueMapping[idx] = builtinValue } - var builtinValues []AirPrivateBuiltinEcOp + builtinValues := make([]AirPrivateBuiltinEcOp, 0) sortedIndexes := make([]int, 0, len(valueMapping)) for index := range valueMapping { @@ -698,7 +698,7 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP valueMapping[idx] = builtinValue } - var builtinValues []AirPrivateBuiltinKeccak + builtinValues := make([]AirPrivateBuiltinKeccak, 0) sortedIndexes := make([]int, 0, len(valueMapping)) for index := range valueMapping { @@ -712,23 +712,27 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP airPrivateInput.Keccak = builtinValues } + case "ecdsa": + { + } } } } + fmt.Println(airPrivateInput) return airPrivateInput, nil } type AirPrivateInput struct { TracePath string `json:"trace_path"` MemoryPath string `json:"memory_path"` - Pedersen []AirPrivateBuiltinPedersen `json:"pedersen,omitempty"` - RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check,omitempty"` - Ecdsa []AirPrivateBuiltinRangeCheck `json:"ecdsa,omitempty"` - Bitwise []AirPrivateBuiltinBitwise `json:"bitwise,omitempty"` - EcOp []AirPrivateBuiltinEcOp `json:"ec_op,omitempty"` - Keccak []AirPrivateBuiltinKeccak `json:"keccak,omitempty"` - Poseidon []AirPrivateBuiltinPoseidon `json:"poseidon,omitempty"` + Pedersen []AirPrivateBuiltinPedersen `json:"pedersen"` + RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check"` + Ecdsa []AirPrivateBuiltinRangeCheck `json:"ecdsa"` + Bitwise []AirPrivateBuiltinBitwise `json:"bitwise"` + EcOp []AirPrivateBuiltinEcOp `json:"ec_op"` + Keccak []AirPrivateBuiltinKeccak `json:"keccak"` + Poseidon []AirPrivateBuiltinPoseidon `json:"poseidon"` } type AirPrivateBuiltinRangeCheck struct { From 239d08292d978c22545ebec88d01b4808e0b2460 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 14 Aug 2024 23:41:49 +0530 Subject: [PATCH 09/14] Iterate on air private input with ecdsa --- cmd/cli/main.go | 2 +- pkg/runners/zero/zero.go | 51 ++++++++++++++++++++++++++++++++++++++-- pkg/vm/builtins/ecdsa.go | 16 ++++++------- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 7bdd2357..7a0eff81 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -212,7 +212,7 @@ func main() { if err != nil { return err } - airPrivateInputJson, err := json.MarshalIndent(airPrivateInput, "", " ") + airPrivateInputJson, err := json.MarshalIndent(airPrivateInput, "", " ") if err != nil { return err } diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index 0646de41..99117a16 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -714,12 +714,47 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP } case "ecdsa": { + ecdsaRunner, ok := bRunner.Runner.(*builtins.ECDSA) + if !ok { + return AirPrivateInput{}, fmt.Errorf("expected ECDSARunner") + } + + builtinValues := make([]AirPrivateBuiltinECDSA, 0) + for addrOffset, signature := range ecdsaRunner.Signatures { + idx := addrOffset / builtins.CellsPerECDSA + pubKey, err := builtinSegment.Read(addrOffset) + if err != nil { + return AirPrivateInput{}, err + } + msg, err := builtinSegment.Read(addrOffset + 1) + if err != nil { + return AirPrivateInput{}, err + } + + pubKeyBig := big.Int{} + msgBig := big.Int{} + pubKey.Felt.BigInt(&pubKeyBig) + msg.Felt.BigInt(&msgBig) + pubKeyHex := fmt.Sprintf("0x%x", &pubKeyBig) + msgHex := fmt.Sprintf("0x%x", &msgBig) + + rBig := new(big.Int).SetBytes(signature.R[:]) + sBig := new(big.Int).SetBytes(signature.S[:]) + frModulusBig, _ := new(big.Int).SetString("3618502788666131213697322783095070105526743751716087489154079457884512865583", 10) + wBig := new(big.Int).ModInverse(sBig, frModulusBig) + signatureInput := AirPrivateBuiltinECDSASignatureInput{ + R: fmt.Sprintf("0x%x", rBig), + W: fmt.Sprintf("0x%x", wBig), + } + + builtinValues = append(builtinValues, AirPrivateBuiltinECDSA{Index: int(idx), PubKey: pubKeyHex, Msg: msgHex, SignatureInput: signatureInput}) + } + airPrivateInput.Ecdsa = builtinValues } } } } - fmt.Println(airPrivateInput) return airPrivateInput, nil } @@ -728,7 +763,7 @@ type AirPrivateInput struct { MemoryPath string `json:"memory_path"` Pedersen []AirPrivateBuiltinPedersen `json:"pedersen"` RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check"` - Ecdsa []AirPrivateBuiltinRangeCheck `json:"ecdsa"` + Ecdsa []AirPrivateBuiltinECDSA `json:"ecdsa"` Bitwise []AirPrivateBuiltinBitwise `json:"bitwise"` EcOp []AirPrivateBuiltinEcOp `json:"ec_op"` Keccak []AirPrivateBuiltinKeccak `json:"keccak"` @@ -779,3 +814,15 @@ type AirPrivateBuiltinKeccak struct { InputS6 string `json:"input_s6"` InputS7 string `json:"input_s7"` } + +type AirPrivateBuiltinECDSA struct { + Index int `json:"index"` + PubKey string `json:"pubkey"` + Msg string `json:"msg"` + SignatureInput AirPrivateBuiltinECDSASignatureInput `json:"signature_input"` +} + +type AirPrivateBuiltinECDSASignatureInput struct { + R string `json:"r"` + W string `json:"w"` +} diff --git a/pkg/vm/builtins/ecdsa.go b/pkg/vm/builtins/ecdsa.go index 9b11e6f2..587cf8ad 100644 --- a/pkg/vm/builtins/ecdsa.go +++ b/pkg/vm/builtins/ecdsa.go @@ -12,18 +12,18 @@ import ( const ECDSAName = "ecdsa" const inputCellsPerECDSA = 2 -const cellsPerECDSA = 2 +const CellsPerECDSA = 2 const instancesPerComponentECDSA = 1 type ECDSA struct { - signatures map[uint64]ecdsa.Signature + Signatures map[uint64]ecdsa.Signature ratio uint64 } // verify_ecdsa_signature(message_hash, public_key, sig_r, sig_s) func (e *ECDSA) CheckWrite(segment *memory.Segment, offset uint64, value *memory.MemoryValue) error { - ecdsaIndex := offset % cellsPerECDSA + ecdsaIndex := offset % CellsPerECDSA pubOffset := offset - ecdsaIndex msgOffset := pubOffset + 1 @@ -58,7 +58,7 @@ func (e *ECDSA) CheckWrite(segment *memory.Segment, offset uint64, value *memory } pubKey := &ecdsa.PublicKey{A: key} - sig, ok := e.signatures[pubOffset] + sig, ok := e.Signatures[pubOffset] if !ok { return fmt.Errorf("signature is missing from ECDSA builtin") } @@ -117,8 +117,8 @@ Hint that will call this function looks like this: }, */ func (e *ECDSA) AddSignature(pubOffset uint64, r, s *fp.Element) error { - if e.signatures == nil { - e.signatures = make(map[uint64]ecdsa.Signature) + if e.Signatures == nil { + e.Signatures = make(map[uint64]ecdsa.Signature) } bytes := make([]byte, 0, 64) rBytes := r.Bytes() @@ -132,7 +132,7 @@ func (e *ECDSA) AddSignature(pubOffset uint64, r, s *fp.Element) error { return err } - e.signatures[pubOffset] = sig + e.Signatures[pubOffset] = sig return nil } @@ -141,7 +141,7 @@ func (e *ECDSA) String() string { } func (e *ECDSA) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, e.ratio, inputCellsPerECDSA, instancesPerComponentECDSA, cellsPerECDSA) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, e.ratio, inputCellsPerECDSA, instancesPerComponentECDSA, CellsPerECDSA) } // recoverY recovers the y and -y coordinate of x. True y can be either y or -y From 8ddbad32195b382f7bfe31e74f120725191aee19 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Thu, 15 Aug 2024 12:46:51 +0530 Subject: [PATCH 10/14] Some refactoring --- pkg/runners/zero/air_input.go | 414 ++++++++++++++++++++++++++++++++++ pkg/runners/zero/zero.go | 408 --------------------------------- 2 files changed, 414 insertions(+), 408 deletions(-) create mode 100644 pkg/runners/zero/air_input.go diff --git a/pkg/runners/zero/air_input.go b/pkg/runners/zero/air_input.go new file mode 100644 index 00000000..c727dbb3 --- /dev/null +++ b/pkg/runners/zero/air_input.go @@ -0,0 +1,414 @@ +package zero + +import ( + "fmt" + "math/big" + "sort" + + "github.com/NethermindEth/cairo-vm-go/pkg/vm/builtins" +) + +func (runner *ZeroRunner) GetAirPublicInput() (AirPublicInput, error) { + rcMin, rcMax := runner.getPermRangeCheckLimits() + return AirPublicInput{ + Layout: runner.layout.Name, + RcMin: rcMin, + RcMax: rcMax, + NSteps: len(runner.vm.Trace), + DynamicParams: nil, + MemorySegments: make(map[string]AirMemorySegmentEntry), + PublicMemory: make([]AirPublicMemoryEntry, 0), + }, nil +} + +type AirPublicInput struct { + Layout string `json:"layout"` + RcMin uint16 `json:"rc_min"` + RcMax uint16 `json:"rc_max"` + NSteps int `json:"n_steps"` + DynamicParams interface{} `json:"dynamic_params"` + MemorySegments map[string]AirMemorySegmentEntry `json:"memory_segments"` + PublicMemory []AirPublicMemoryEntry `json:"public_memory"` +} + +type AirMemorySegmentEntry struct { + BeginAddr int `json:"begin_addr"` + StopPtr int `json:"stop_ptr"` +} + +type AirPublicMemoryEntry struct { + Address uint16 `json:"address"` + Value string `json:"value"` + Page uint16 `json:"page"` +} + +func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirPrivateInput, error) { + airPrivateInput := AirPrivateInput{ + TracePath: tracePath, + MemoryPath: memoryPath, + } + + for _, bRunner := range runner.layout.Builtins { + builtinName := bRunner.Runner.String() + builtinSegment, ok := runner.vm.Memory.FindSegmentWithBuiltin(builtinName) + if ok { + // some checks might be missing here + switch builtinName { + case "range_check": + { + builtinValues := make([]AirPrivateBuiltinRangeCheck, 0) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + builtinValues = append(builtinValues, AirPrivateBuiltinRangeCheck{Index: index, Value: valueHex}) + } + airPrivateInput.RangeCheck = builtinValues + } + case "bitwise": + { + valueMapping := make(map[int]AirPrivateBuiltinBitwise) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/builtins.CellsPerBitwise, index%builtins.CellsPerBitwise + if typ >= 2 { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinBitwise{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if typ == 0 { + builtinValue.X = valueHex + } else { + builtinValue.Y = valueHex + } + valueMapping[idx] = builtinValue + } + + builtinValues := make([]AirPrivateBuiltinBitwise, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Bitwise = builtinValues + } + case "poseidon": + { + valueMapping := make(map[int]AirPrivateBuiltinPoseidon) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, stateIndex := index/builtins.CellsPerPoseidon, index%builtins.CellsPerPoseidon + if stateIndex >= builtins.InputCellsPerPoseidon { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinPoseidon{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if stateIndex == 0 { + builtinValue.InputS0 = valueHex + } else if stateIndex == 1 { + builtinValue.InputS1 = valueHex + } else if stateIndex == 2 { + builtinValue.InputS2 = valueHex + } + valueMapping[idx] = builtinValue + } + + builtinValues := make([]AirPrivateBuiltinPoseidon, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Poseidon = builtinValues + } + case "pedersen": + { + valueMapping := make(map[int]AirPrivateBuiltinPedersen) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/builtins.CellsPerPedersen, index%builtins.CellsPerPedersen + if typ == 2 { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinPedersen{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if typ == 0 { + builtinValue.X = valueHex + } else { + builtinValue.Y = valueHex + } + valueMapping[idx] = builtinValue + } + + builtinValues := make([]AirPrivateBuiltinPedersen, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Pedersen = builtinValues + } + case "ec_op": + { + valueMapping := make(map[int]AirPrivateBuiltinEcOp) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/builtins.CellsPerEcOp, index%builtins.CellsPerEcOp + if typ >= builtins.InputCellsPerEcOp { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinEcOp{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if typ == 0 { + builtinValue.PX = valueHex + } else if typ == 1 { + builtinValue.PY = valueHex + } else if typ == 2 { + builtinValue.QX = valueHex + } else if typ == 3 { + builtinValue.QY = valueHex + } else if typ == 4 { + builtinValue.M = valueHex + } + valueMapping[idx] = builtinValue + } + + builtinValues := make([]AirPrivateBuiltinEcOp, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.EcOp = builtinValues + } + case "keccak": + { + valueMapping := make(map[int]AirPrivateBuiltinKeccak) + for index, value := range builtinSegment.Data { + if !value.Known() { + continue + } + idx, stateIndex := index/builtins.CellsPerKeccak, index%builtins.CellsPerKeccak + if stateIndex >= builtins.InputCellsPerKeccak { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinKeccak{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if stateIndex == 0 { + builtinValue.InputS0 = valueHex + } else if stateIndex == 1 { + builtinValue.InputS1 = valueHex + } else if stateIndex == 2 { + builtinValue.InputS2 = valueHex + } else if stateIndex == 3 { + builtinValue.InputS3 = valueHex + } else if stateIndex == 4 { + builtinValue.InputS4 = valueHex + } else if stateIndex == 5 { + builtinValue.InputS5 = valueHex + } else if stateIndex == 6 { + builtinValue.InputS6 = valueHex + } else if stateIndex == 7 { + builtinValue.InputS7 = valueHex + } + valueMapping[idx] = builtinValue + } + + builtinValues := make([]AirPrivateBuiltinKeccak, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + builtinValue := valueMapping[index] + builtinValues = append(builtinValues, builtinValue) + } + + airPrivateInput.Keccak = builtinValues + } + case "ecdsa": + { + ecdsaRunner, ok := bRunner.Runner.(*builtins.ECDSA) + if !ok { + return AirPrivateInput{}, fmt.Errorf("expected ECDSARunner") + } + + builtinValues := make([]AirPrivateBuiltinECDSA, 0) + for addrOffset, signature := range ecdsaRunner.Signatures { + idx := addrOffset / builtins.CellsPerECDSA + pubKey, err := builtinSegment.Read(addrOffset) + if err != nil { + return AirPrivateInput{}, err + } + msg, err := builtinSegment.Read(addrOffset + 1) + if err != nil { + return AirPrivateInput{}, err + } + + pubKeyBig := big.Int{} + msgBig := big.Int{} + pubKey.Felt.BigInt(&pubKeyBig) + msg.Felt.BigInt(&msgBig) + pubKeyHex := fmt.Sprintf("0x%x", &pubKeyBig) + msgHex := fmt.Sprintf("0x%x", &msgBig) + + rBig := new(big.Int).SetBytes(signature.R[:]) + sBig := new(big.Int).SetBytes(signature.S[:]) + frModulusBig, _ := new(big.Int).SetString("3618502788666131213697322783095070105526743751716087489154079457884512865583", 10) + wBig := new(big.Int).ModInverse(sBig, frModulusBig) + signatureInput := AirPrivateBuiltinECDSASignatureInput{ + R: fmt.Sprintf("0x%x", rBig), + W: fmt.Sprintf("0x%x", wBig), + } + + builtinValues = append(builtinValues, AirPrivateBuiltinECDSA{Index: int(idx), PubKey: pubKeyHex, Msg: msgHex, SignatureInput: signatureInput}) + } + airPrivateInput.Ecdsa = builtinValues + } + } + } + } + + return airPrivateInput, nil +} + +type AirPrivateInput struct { + TracePath string `json:"trace_path"` + MemoryPath string `json:"memory_path"` + Pedersen []AirPrivateBuiltinPedersen `json:"pedersen"` + RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check"` + Ecdsa []AirPrivateBuiltinECDSA `json:"ecdsa"` + Bitwise []AirPrivateBuiltinBitwise `json:"bitwise"` + EcOp []AirPrivateBuiltinEcOp `json:"ec_op"` + Keccak []AirPrivateBuiltinKeccak `json:"keccak"` + Poseidon []AirPrivateBuiltinPoseidon `json:"poseidon"` +} + +type AirPrivateBuiltinRangeCheck struct { + Index int `json:"index"` + Value string `json:"value"` +} + +type AirPrivateBuiltinBitwise struct { + Index int `json:"index"` + X string `json:"x"` + Y string `json:"y"` +} + +type AirPrivateBuiltinPoseidon struct { + Index int `json:"index"` + InputS0 string `json:"input_s0"` + InputS1 string `json:"input_s1"` + InputS2 string `json:"input_s2"` +} + +type AirPrivateBuiltinPedersen struct { + Index int `json:"index"` + X string `json:"x"` + Y string `json:"y"` +} + +type AirPrivateBuiltinEcOp struct { + Index int `json:"index"` + PX string `json:"p_x"` + PY string `json:"p_y"` + M string `json:"m"` + QX string `json:"q_x"` + QY string `json:"q_y"` +} + +type AirPrivateBuiltinKeccak struct { + Index int `json:"index"` + InputS0 string `json:"input_s0"` + InputS1 string `json:"input_s1"` + InputS2 string `json:"input_s2"` + InputS3 string `json:"input_s3"` + InputS4 string `json:"input_s4"` + InputS5 string `json:"input_s5"` + InputS6 string `json:"input_s6"` + InputS7 string `json:"input_s7"` +} + +type AirPrivateBuiltinECDSA struct { + Index int `json:"index"` + PubKey string `json:"pubkey"` + Msg string `json:"msg"` + SignatureInput AirPrivateBuiltinECDSASignatureInput `json:"signature_input"` +} + +type AirPrivateBuiltinECDSASignatureInput struct { + R string `json:"r"` + W string `json:"w"` +} diff --git a/pkg/runners/zero/zero.go b/pkg/runners/zero/zero.go index 99117a16..9980524d 100644 --- a/pkg/runners/zero/zero.go +++ b/pkg/runners/zero/zero.go @@ -3,8 +3,6 @@ package zero import ( "errors" "fmt" - "math/big" - "sort" "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner" "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" @@ -420,409 +418,3 @@ func (runner *ZeroRunner) Output() []*fp.Element { } return output } - -func (runner *ZeroRunner) GetAirPublicInput() (AirPublicInput, error) { - rcMin, rcMax := runner.getPermRangeCheckLimits() - return AirPublicInput{ - Layout: runner.layout.Name, - RcMin: rcMin, - RcMax: rcMax, - // optimise this away - NSteps: len(runner.vm.RelocateTrace()), - DynamicParams: nil, - MemorySegments: make(map[string]AirMemorySegmentEntry), - PublicMemory: make([]AirPublicMemoryEntry, 0), - }, nil -} - -type AirPublicInput struct { - Layout string `json:"layout"` - RcMin uint16 `json:"rc_min"` - RcMax uint16 `json:"rc_max"` - NSteps int `json:"n_steps"` - DynamicParams interface{} `json:"dynamic_params"` - MemorySegments map[string]AirMemorySegmentEntry `json:"memory_segments"` - PublicMemory []AirPublicMemoryEntry `json:"public_memory"` -} - -type AirMemorySegmentEntry struct { - BeginAddr int `json:"begin_addr"` - StopPtr int `json:"stop_ptr"` -} - -type AirPublicMemoryEntry struct { - Address uint16 `json:"address"` - Value string `json:"value"` - Page uint16 `json:"page"` -} - -func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirPrivateInput, error) { - airPrivateInput := AirPrivateInput{ - TracePath: tracePath, - MemoryPath: memoryPath, - } - - for _, bRunner := range runner.layout.Builtins { - builtinName := bRunner.Runner.String() - builtinSegment, ok := runner.vm.Memory.FindSegmentWithBuiltin(builtinName) - if ok { - // some checks might be missing here - switch builtinName { - case "range_check": - { - builtinValues := make([]AirPrivateBuiltinRangeCheck, 0) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - builtinValues = append(builtinValues, AirPrivateBuiltinRangeCheck{Index: index, Value: valueHex}) - } - airPrivateInput.RangeCheck = builtinValues - } - case "bitwise": - { - valueMapping := make(map[int]AirPrivateBuiltinBitwise) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, typ := index/builtins.CellsPerBitwise, index%builtins.CellsPerBitwise - if typ >= 2 { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinBitwise{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if typ == 0 { - builtinValue.X = valueHex - } else { - builtinValue.Y = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinBitwise, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.Bitwise = builtinValues - } - case "poseidon": - { - valueMapping := make(map[int]AirPrivateBuiltinPoseidon) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, stateIndex := index/builtins.CellsPerPoseidon, index%builtins.CellsPerPoseidon - if stateIndex >= builtins.InputCellsPerPoseidon { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinPoseidon{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if stateIndex == 0 { - builtinValue.InputS0 = valueHex - } else if stateIndex == 1 { - builtinValue.InputS1 = valueHex - } else if stateIndex == 2 { - builtinValue.InputS2 = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinPoseidon, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.Poseidon = builtinValues - } - case "pedersen": - { - valueMapping := make(map[int]AirPrivateBuiltinPedersen) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, typ := index/builtins.CellsPerPedersen, index%builtins.CellsPerPedersen - if typ == 2 { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinPedersen{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if typ == 0 { - builtinValue.X = valueHex - } else { - builtinValue.Y = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinPedersen, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.Pedersen = builtinValues - } - case "ec_op": - { - valueMapping := make(map[int]AirPrivateBuiltinEcOp) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, typ := index/builtins.CellsPerEcOp, index%builtins.CellsPerEcOp - if typ >= builtins.InputCellsPerEcOp { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinEcOp{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if typ == 0 { - builtinValue.PX = valueHex - } else if typ == 1 { - builtinValue.PY = valueHex - } else if typ == 2 { - builtinValue.QX = valueHex - } else if typ == 3 { - builtinValue.QY = valueHex - } else if typ == 4 { - builtinValue.M = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinEcOp, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.EcOp = builtinValues - } - case "keccak": - { - valueMapping := make(map[int]AirPrivateBuiltinKeccak) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, stateIndex := index/builtins.CellsPerKeccak, index%builtins.CellsPerKeccak - if stateIndex >= builtins.InputCellsPerKeccak { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinKeccak{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if stateIndex == 0 { - builtinValue.InputS0 = valueHex - } else if stateIndex == 1 { - builtinValue.InputS1 = valueHex - } else if stateIndex == 2 { - builtinValue.InputS2 = valueHex - } else if stateIndex == 3 { - builtinValue.InputS3 = valueHex - } else if stateIndex == 4 { - builtinValue.InputS4 = valueHex - } else if stateIndex == 5 { - builtinValue.InputS5 = valueHex - } else if stateIndex == 6 { - builtinValue.InputS6 = valueHex - } else if stateIndex == 7 { - builtinValue.InputS7 = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinKeccak, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.Keccak = builtinValues - } - case "ecdsa": - { - ecdsaRunner, ok := bRunner.Runner.(*builtins.ECDSA) - if !ok { - return AirPrivateInput{}, fmt.Errorf("expected ECDSARunner") - } - - builtinValues := make([]AirPrivateBuiltinECDSA, 0) - for addrOffset, signature := range ecdsaRunner.Signatures { - idx := addrOffset / builtins.CellsPerECDSA - pubKey, err := builtinSegment.Read(addrOffset) - if err != nil { - return AirPrivateInput{}, err - } - msg, err := builtinSegment.Read(addrOffset + 1) - if err != nil { - return AirPrivateInput{}, err - } - - pubKeyBig := big.Int{} - msgBig := big.Int{} - pubKey.Felt.BigInt(&pubKeyBig) - msg.Felt.BigInt(&msgBig) - pubKeyHex := fmt.Sprintf("0x%x", &pubKeyBig) - msgHex := fmt.Sprintf("0x%x", &msgBig) - - rBig := new(big.Int).SetBytes(signature.R[:]) - sBig := new(big.Int).SetBytes(signature.S[:]) - frModulusBig, _ := new(big.Int).SetString("3618502788666131213697322783095070105526743751716087489154079457884512865583", 10) - wBig := new(big.Int).ModInverse(sBig, frModulusBig) - signatureInput := AirPrivateBuiltinECDSASignatureInput{ - R: fmt.Sprintf("0x%x", rBig), - W: fmt.Sprintf("0x%x", wBig), - } - - builtinValues = append(builtinValues, AirPrivateBuiltinECDSA{Index: int(idx), PubKey: pubKeyHex, Msg: msgHex, SignatureInput: signatureInput}) - } - airPrivateInput.Ecdsa = builtinValues - } - } - } - } - - return airPrivateInput, nil -} - -type AirPrivateInput struct { - TracePath string `json:"trace_path"` - MemoryPath string `json:"memory_path"` - Pedersen []AirPrivateBuiltinPedersen `json:"pedersen"` - RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check"` - Ecdsa []AirPrivateBuiltinECDSA `json:"ecdsa"` - Bitwise []AirPrivateBuiltinBitwise `json:"bitwise"` - EcOp []AirPrivateBuiltinEcOp `json:"ec_op"` - Keccak []AirPrivateBuiltinKeccak `json:"keccak"` - Poseidon []AirPrivateBuiltinPoseidon `json:"poseidon"` -} - -type AirPrivateBuiltinRangeCheck struct { - Index int `json:"index"` - Value string `json:"value"` -} - -type AirPrivateBuiltinBitwise struct { - Index int `json:"index"` - X string `json:"x"` - Y string `json:"y"` -} - -type AirPrivateBuiltinPoseidon struct { - Index int `json:"index"` - InputS0 string `json:"input_s0"` - InputS1 string `json:"input_s1"` - InputS2 string `json:"input_s2"` -} - -type AirPrivateBuiltinPedersen struct { - Index int `json:"index"` - X string `json:"x"` - Y string `json:"y"` -} - -type AirPrivateBuiltinEcOp struct { - Index int `json:"index"` - PX string `json:"p_x"` - PY string `json:"p_y"` - M string `json:"m"` - QX string `json:"q_x"` - QY string `json:"q_y"` -} - -type AirPrivateBuiltinKeccak struct { - Index int `json:"index"` - InputS0 string `json:"input_s0"` - InputS1 string `json:"input_s1"` - InputS2 string `json:"input_s2"` - InputS3 string `json:"input_s3"` - InputS4 string `json:"input_s4"` - InputS5 string `json:"input_s5"` - InputS6 string `json:"input_s6"` - InputS7 string `json:"input_s7"` -} - -type AirPrivateBuiltinECDSA struct { - Index int `json:"index"` - PubKey string `json:"pubkey"` - Msg string `json:"msg"` - SignatureInput AirPrivateBuiltinECDSASignatureInput `json:"signature_input"` -} - -type AirPrivateBuiltinECDSASignatureInput struct { - R string `json:"r"` - W string `json:"w"` -} From 28976f0dba69c3169ae7c5b9920b42e1f12c1381 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Thu, 29 Aug 2024 18:37:40 +0530 Subject: [PATCH 11/14] Add TODO --- pkg/runners/zero/air_input.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/runners/zero/air_input.go b/pkg/runners/zero/air_input.go index c727dbb3..adc5282c 100644 --- a/pkg/runners/zero/air_input.go +++ b/pkg/runners/zero/air_input.go @@ -11,13 +11,15 @@ import ( func (runner *ZeroRunner) GetAirPublicInput() (AirPublicInput, error) { rcMin, rcMax := runner.getPermRangeCheckLimits() return AirPublicInput{ - Layout: runner.layout.Name, - RcMin: rcMin, - RcMax: rcMax, - NSteps: len(runner.vm.Trace), - DynamicParams: nil, + Layout: runner.layout.Name, + RcMin: rcMin, + RcMax: rcMax, + NSteps: len(runner.vm.Trace), + DynamicParams: nil, + // TODO: yet to be implemented MemorySegments: make(map[string]AirMemorySegmentEntry), - PublicMemory: make([]AirPublicMemoryEntry, 0), + // TODO: yet to be implemented + PublicMemory: make([]AirPublicMemoryEntry, 0), }, nil } From a8248f0a00889491fe35c17b3f014ef8f4983d28 Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Fri, 30 Aug 2024 19:07:54 +0530 Subject: [PATCH 12/14] Fix unit test --- pkg/vm/builtins/ecop_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/vm/builtins/ecop_test.go b/pkg/vm/builtins/ecop_test.go index c7a2c8dc..6a3c6615 100644 --- a/pkg/vm/builtins/ecop_test.go +++ b/pkg/vm/builtins/ecop_test.go @@ -27,7 +27,7 @@ func TestEcOp(t *testing.T) { mult := ecmult(&point{*qx, *qy}, new(uint256.Int).SetUint64(3), &utils.FeltOne) r := ecadd(&point{*px, *py}, &mult) - segment := memory.EmptySegmentWithLength(cellsPerEcOp) + segment := memory.EmptySegmentWithLength(CellsPerEcOp) ecop := &EcOp{ratio: 1024, cache: make(map[uint64]fp.Element)} segment.WithBuiltinRunner(ecop) From df1c13f17459fe134977e35fd138500c8233a47f Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 11 Sep 2024 13:49:30 +0530 Subject: [PATCH 13/14] Refactor air private functionality to respective builtin files --- pkg/runners/zero/air_input.go | 350 ++------------------------------- pkg/vm/builtins/bitwise.go | 55 +++++- pkg/vm/builtins/ecdsa.go | 53 ++++- pkg/vm/builtins/ecop.go | 71 ++++++- pkg/vm/builtins/ecop_test.go | 2 +- pkg/vm/builtins/keccak.go | 83 +++++++- pkg/vm/builtins/pedersen.go | 56 +++++- pkg/vm/builtins/poseidon.go | 68 ++++++- pkg/vm/builtins/range_check.go | 20 ++ 9 files changed, 396 insertions(+), 362 deletions(-) diff --git a/pkg/runners/zero/air_input.go b/pkg/runners/zero/air_input.go index adc5282c..ac0a4ce3 100644 --- a/pkg/runners/zero/air_input.go +++ b/pkg/runners/zero/air_input.go @@ -1,10 +1,6 @@ package zero import ( - "fmt" - "math/big" - "sort" - "github.com/NethermindEth/cairo-vm-go/pkg/vm/builtins" ) @@ -58,286 +54,35 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP switch builtinName { case "range_check": { - builtinValues := make([]AirPrivateBuiltinRangeCheck, 0) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - builtinValues = append(builtinValues, AirPrivateBuiltinRangeCheck{Index: index, Value: valueHex}) - } - airPrivateInput.RangeCheck = builtinValues + airPrivateInput.RangeCheck = bRunner.Runner.(*builtins.RangeCheck).GetAirPrivateInput(builtinSegment) } case "bitwise": { - valueMapping := make(map[int]AirPrivateBuiltinBitwise) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, typ := index/builtins.CellsPerBitwise, index%builtins.CellsPerBitwise - if typ >= 2 { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinBitwise{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if typ == 0 { - builtinValue.X = valueHex - } else { - builtinValue.Y = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinBitwise, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.Bitwise = builtinValues + airPrivateInput.Bitwise = bRunner.Runner.(*builtins.Bitwise).GetAirPrivateInput(builtinSegment) } case "poseidon": { - valueMapping := make(map[int]AirPrivateBuiltinPoseidon) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, stateIndex := index/builtins.CellsPerPoseidon, index%builtins.CellsPerPoseidon - if stateIndex >= builtins.InputCellsPerPoseidon { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinPoseidon{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if stateIndex == 0 { - builtinValue.InputS0 = valueHex - } else if stateIndex == 1 { - builtinValue.InputS1 = valueHex - } else if stateIndex == 2 { - builtinValue.InputS2 = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinPoseidon, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.Poseidon = builtinValues + airPrivateInput.Poseidon = bRunner.Runner.(*builtins.Poseidon).GetAirPrivateInput(builtinSegment) } case "pedersen": { - valueMapping := make(map[int]AirPrivateBuiltinPedersen) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, typ := index/builtins.CellsPerPedersen, index%builtins.CellsPerPedersen - if typ == 2 { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinPedersen{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if typ == 0 { - builtinValue.X = valueHex - } else { - builtinValue.Y = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinPedersen, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.Pedersen = builtinValues + airPrivateInput.Pedersen = bRunner.Runner.(*builtins.Pedersen).GetAirPrivateInput(builtinSegment) } case "ec_op": { - valueMapping := make(map[int]AirPrivateBuiltinEcOp) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, typ := index/builtins.CellsPerEcOp, index%builtins.CellsPerEcOp - if typ >= builtins.InputCellsPerEcOp { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinEcOp{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if typ == 0 { - builtinValue.PX = valueHex - } else if typ == 1 { - builtinValue.PY = valueHex - } else if typ == 2 { - builtinValue.QX = valueHex - } else if typ == 3 { - builtinValue.QY = valueHex - } else if typ == 4 { - builtinValue.M = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinEcOp, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.EcOp = builtinValues + airPrivateInput.EcOp = bRunner.Runner.(*builtins.EcOp).GetAirPrivateInput(builtinSegment) } case "keccak": { - valueMapping := make(map[int]AirPrivateBuiltinKeccak) - for index, value := range builtinSegment.Data { - if !value.Known() { - continue - } - idx, stateIndex := index/builtins.CellsPerKeccak, index%builtins.CellsPerKeccak - if stateIndex >= builtins.InputCellsPerKeccak { - continue - } - - builtinValue, exists := valueMapping[idx] - if !exists { - builtinValue = AirPrivateBuiltinKeccak{Index: idx} - } - - valueBig := big.Int{} - value.Felt.BigInt(&valueBig) - valueHex := fmt.Sprintf("0x%x", &valueBig) - if stateIndex == 0 { - builtinValue.InputS0 = valueHex - } else if stateIndex == 1 { - builtinValue.InputS1 = valueHex - } else if stateIndex == 2 { - builtinValue.InputS2 = valueHex - } else if stateIndex == 3 { - builtinValue.InputS3 = valueHex - } else if stateIndex == 4 { - builtinValue.InputS4 = valueHex - } else if stateIndex == 5 { - builtinValue.InputS5 = valueHex - } else if stateIndex == 6 { - builtinValue.InputS6 = valueHex - } else if stateIndex == 7 { - builtinValue.InputS7 = valueHex - } - valueMapping[idx] = builtinValue - } - - builtinValues := make([]AirPrivateBuiltinKeccak, 0) - - sortedIndexes := make([]int, 0, len(valueMapping)) - for index := range valueMapping { - sortedIndexes = append(sortedIndexes, index) - } - sort.Ints(sortedIndexes) - for _, index := range sortedIndexes { - builtinValue := valueMapping[index] - builtinValues = append(builtinValues, builtinValue) - } - - airPrivateInput.Keccak = builtinValues + airPrivateInput.Keccak = bRunner.Runner.(*builtins.Keccak).GetAirPrivateInput(builtinSegment) } case "ecdsa": { - ecdsaRunner, ok := bRunner.Runner.(*builtins.ECDSA) - if !ok { - return AirPrivateInput{}, fmt.Errorf("expected ECDSARunner") - } - - builtinValues := make([]AirPrivateBuiltinECDSA, 0) - for addrOffset, signature := range ecdsaRunner.Signatures { - idx := addrOffset / builtins.CellsPerECDSA - pubKey, err := builtinSegment.Read(addrOffset) - if err != nil { - return AirPrivateInput{}, err - } - msg, err := builtinSegment.Read(addrOffset + 1) - if err != nil { - return AirPrivateInput{}, err - } - - pubKeyBig := big.Int{} - msgBig := big.Int{} - pubKey.Felt.BigInt(&pubKeyBig) - msg.Felt.BigInt(&msgBig) - pubKeyHex := fmt.Sprintf("0x%x", &pubKeyBig) - msgHex := fmt.Sprintf("0x%x", &msgBig) - - rBig := new(big.Int).SetBytes(signature.R[:]) - sBig := new(big.Int).SetBytes(signature.S[:]) - frModulusBig, _ := new(big.Int).SetString("3618502788666131213697322783095070105526743751716087489154079457884512865583", 10) - wBig := new(big.Int).ModInverse(sBig, frModulusBig) - signatureInput := AirPrivateBuiltinECDSASignatureInput{ - R: fmt.Sprintf("0x%x", rBig), - W: fmt.Sprintf("0x%x", wBig), - } - - builtinValues = append(builtinValues, AirPrivateBuiltinECDSA{Index: int(idx), PubKey: pubKeyHex, Msg: msgHex, SignatureInput: signatureInput}) + ecdsaAirPrivateInput, err := bRunner.Runner.(*builtins.ECDSA).GetAirPrivateInput(builtinSegment) + if err != nil { + return AirPrivateInput{}, err } - airPrivateInput.Ecdsa = builtinValues + airPrivateInput.Ecdsa = ecdsaAirPrivateInput } } } @@ -347,70 +92,13 @@ func (runner *ZeroRunner) GetAirPrivateInput(tracePath, memoryPath string) (AirP } type AirPrivateInput struct { - TracePath string `json:"trace_path"` - MemoryPath string `json:"memory_path"` - Pedersen []AirPrivateBuiltinPedersen `json:"pedersen"` - RangeCheck []AirPrivateBuiltinRangeCheck `json:"range_check"` - Ecdsa []AirPrivateBuiltinECDSA `json:"ecdsa"` - Bitwise []AirPrivateBuiltinBitwise `json:"bitwise"` - EcOp []AirPrivateBuiltinEcOp `json:"ec_op"` - Keccak []AirPrivateBuiltinKeccak `json:"keccak"` - Poseidon []AirPrivateBuiltinPoseidon `json:"poseidon"` -} - -type AirPrivateBuiltinRangeCheck struct { - Index int `json:"index"` - Value string `json:"value"` -} - -type AirPrivateBuiltinBitwise struct { - Index int `json:"index"` - X string `json:"x"` - Y string `json:"y"` -} - -type AirPrivateBuiltinPoseidon struct { - Index int `json:"index"` - InputS0 string `json:"input_s0"` - InputS1 string `json:"input_s1"` - InputS2 string `json:"input_s2"` -} - -type AirPrivateBuiltinPedersen struct { - Index int `json:"index"` - X string `json:"x"` - Y string `json:"y"` -} - -type AirPrivateBuiltinEcOp struct { - Index int `json:"index"` - PX string `json:"p_x"` - PY string `json:"p_y"` - M string `json:"m"` - QX string `json:"q_x"` - QY string `json:"q_y"` -} - -type AirPrivateBuiltinKeccak struct { - Index int `json:"index"` - InputS0 string `json:"input_s0"` - InputS1 string `json:"input_s1"` - InputS2 string `json:"input_s2"` - InputS3 string `json:"input_s3"` - InputS4 string `json:"input_s4"` - InputS5 string `json:"input_s5"` - InputS6 string `json:"input_s6"` - InputS7 string `json:"input_s7"` -} - -type AirPrivateBuiltinECDSA struct { - Index int `json:"index"` - PubKey string `json:"pubkey"` - Msg string `json:"msg"` - SignatureInput AirPrivateBuiltinECDSASignatureInput `json:"signature_input"` -} - -type AirPrivateBuiltinECDSASignatureInput struct { - R string `json:"r"` - W string `json:"w"` + TracePath string `json:"trace_path"` + MemoryPath string `json:"memory_path"` + Pedersen []builtins.AirPrivateBuiltinPedersen `json:"pedersen"` + RangeCheck []builtins.AirPrivateBuiltinRangeCheck `json:"range_check"` + Ecdsa []builtins.AirPrivateBuiltinECDSA `json:"ecdsa"` + Bitwise []builtins.AirPrivateBuiltinBitwise `json:"bitwise"` + EcOp []builtins.AirPrivateBuiltinEcOp `json:"ec_op"` + Keccak []builtins.AirPrivateBuiltinKeccak `json:"keccak"` + Poseidon []builtins.AirPrivateBuiltinPoseidon `json:"poseidon"` } diff --git a/pkg/vm/builtins/bitwise.go b/pkg/vm/builtins/bitwise.go index 6832d303..b42567ae 100644 --- a/pkg/vm/builtins/bitwise.go +++ b/pkg/vm/builtins/bitwise.go @@ -3,6 +3,8 @@ package builtins import ( "errors" "fmt" + "math/big" + "sort" "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" @@ -10,7 +12,7 @@ import ( const BitwiseName = "bitwise" -const CellsPerBitwise = 5 +const cellsPerBitwise = 5 const inputCellsPerBitwise = 2 const instancesPerComponentBitwise = 1 @@ -25,7 +27,7 @@ func (b *Bitwise) CheckWrite( } func (b *Bitwise) InferValue(segment *memory.Segment, offset uint64) error { - bitwiseIndex := offset % CellsPerBitwise + bitwiseIndex := offset % cellsPerBitwise // input cell if bitwiseIndex < inputCellsPerBitwise { return errors.New("cannot infer value from input cell") @@ -98,5 +100,52 @@ func (b *Bitwise) String() string { } func (b *Bitwise) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, b.ratio, inputCellsPerBitwise, instancesPerComponentBitwise, CellsPerBitwise) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, b.ratio, inputCellsPerBitwise, instancesPerComponentBitwise, cellsPerBitwise) +} + +type AirPrivateBuiltinBitwise struct { + Index int `json:"index"` + X string `json:"x"` + Y string `json:"y"` +} + +func (b *Bitwise) GetAirPrivateInput(bitwiseSegment *memory.Segment) []AirPrivateBuiltinBitwise { + valueMapping := make(map[int]AirPrivateBuiltinBitwise) + for index, value := range bitwiseSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/cellsPerBitwise, index%cellsPerBitwise + if typ >= 2 { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinBitwise{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if typ == 0 { + builtinValue.X = valueHex + } else { + builtinValue.Y = valueHex + } + valueMapping[idx] = builtinValue + } + + values := make([]AirPrivateBuiltinBitwise, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + value := valueMapping[index] + values = append(values, value) + } + return values } diff --git a/pkg/vm/builtins/ecdsa.go b/pkg/vm/builtins/ecdsa.go index 73161ead..8c65be11 100644 --- a/pkg/vm/builtins/ecdsa.go +++ b/pkg/vm/builtins/ecdsa.go @@ -2,6 +2,7 @@ package builtins import ( "fmt" + "math/big" "github.com/NethermindEth/cairo-vm-go/pkg/utils" "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" @@ -12,7 +13,7 @@ import ( const ECDSAName = "ecdsa" const inputCellsPerECDSA = 2 -const CellsPerECDSA = 2 +const cellsPerECDSA = 2 const instancesPerComponentECDSA = 1 @@ -23,7 +24,7 @@ type ECDSA struct { // verify_ecdsa_signature(message_hash, public_key, sig_r, sig_s) func (e *ECDSA) CheckWrite(segment *memory.Segment, offset uint64, value *memory.MemoryValue) error { - ecdsaIndex := offset % CellsPerECDSA + ecdsaIndex := offset % cellsPerECDSA pubOffset := offset - ecdsaIndex msgOffset := pubOffset + 1 @@ -141,7 +142,7 @@ func (e *ECDSA) String() string { } func (e *ECDSA) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, e.ratio, inputCellsPerECDSA, instancesPerComponentECDSA, CellsPerECDSA) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, e.ratio, inputCellsPerECDSA, instancesPerComponentECDSA, cellsPerECDSA) } // recoverY recovers the y and -y coordinate of x. True y can be either y or -y @@ -162,3 +163,49 @@ func recoverY(x *fp.Element) (fp.Element, fp.Element, error) { negY.Neg(y) return *y, negY, nil } + +type AirPrivateBuiltinECDSASignatureInput struct { + R string `json:"r"` + W string `json:"w"` +} + +type AirPrivateBuiltinECDSA struct { + Index int `json:"index"` + PubKey string `json:"pubkey"` + Msg string `json:"msg"` + SignatureInput AirPrivateBuiltinECDSASignatureInput `json:"signature_input"` +} + +func (e *ECDSA) GetAirPrivateInput(ecdsaSegment *memory.Segment) ([]AirPrivateBuiltinECDSA, error) { + values := make([]AirPrivateBuiltinECDSA, 0) + for addrOffset, signature := range e.Signatures { + idx := addrOffset / cellsPerECDSA + pubKey, err := ecdsaSegment.Read(addrOffset) + if err != nil { + return values, err + } + msg, err := ecdsaSegment.Read(addrOffset + 1) + if err != nil { + return values, err + } + + pubKeyBig := big.Int{} + msgBig := big.Int{} + pubKey.Felt.BigInt(&pubKeyBig) + msg.Felt.BigInt(&msgBig) + pubKeyHex := fmt.Sprintf("0x%x", &pubKeyBig) + msgHex := fmt.Sprintf("0x%x", &msgBig) + + rBig := new(big.Int).SetBytes(signature.R[:]) + sBig := new(big.Int).SetBytes(signature.S[:]) + frModulusBig, _ := new(big.Int).SetString("3618502788666131213697322783095070105526743751716087489154079457884512865583", 10) + wBig := new(big.Int).ModInverse(sBig, frModulusBig) + signatureInput := AirPrivateBuiltinECDSASignatureInput{ + R: fmt.Sprintf("0x%x", rBig), + W: fmt.Sprintf("0x%x", wBig), + } + + values = append(values, AirPrivateBuiltinECDSA{Index: int(idx), PubKey: pubKeyHex, Msg: msgHex, SignatureInput: signatureInput}) + } + return values, nil +} diff --git a/pkg/vm/builtins/ecop.go b/pkg/vm/builtins/ecop.go index 6ba690e3..3f4b0fd8 100644 --- a/pkg/vm/builtins/ecop.go +++ b/pkg/vm/builtins/ecop.go @@ -3,16 +3,19 @@ package builtins import ( "errors" "fmt" + "math/big" + "sort" "github.com/NethermindEth/cairo-vm-go/pkg/utils" + "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" mem "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" "github.com/holiman/uint256" ) const EcOpName = "ec_op" -const CellsPerEcOp = 7 -const InputCellsPerEcOp = 5 +const cellsPerEcOp = 7 +const inputCellsPerEcOp = 5 const instancesPerComponentEcOp = 1 var feltThree fp.Element = fp.Element( @@ -44,8 +47,8 @@ func (e *EcOp) InferValue(segment *mem.Segment, offset uint64) error { return segment.Write(offset, &mv) } // get the current slot index and verify it is an output cell - ecopIndex := offset % CellsPerEcOp - if ecopIndex < InputCellsPerEcOp { + ecopIndex := offset % cellsPerEcOp + if ecopIndex < inputCellsPerEcOp { return errors.New("cannot infer value from input cell") } @@ -99,7 +102,7 @@ func (e *EcOp) InferValue(segment *mem.Segment, offset uint64) error { } // store the resulting point `r` - outputOff := inputOff + InputCellsPerEcOp + outputOff := inputOff + inputCellsPerEcOp // store the x and y coordinates of the resulting point e.cache[outputOff] = r.X @@ -111,7 +114,7 @@ func (e *EcOp) InferValue(segment *mem.Segment, offset uint64) error { } func (e *EcOp) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, e.ratio, InputCellsPerEcOp, instancesPerComponentEcOp, CellsPerEcOp) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, e.ratio, inputCellsPerEcOp, instancesPerComponentEcOp, cellsPerEcOp) } // structure to represent a point in the elliptic curve @@ -234,3 +237,59 @@ func ecdouble(p *point, alpha *fp.Element) point { return point{x, y} } + +type AirPrivateBuiltinEcOp struct { + Index int `json:"index"` + PX string `json:"p_x"` + PY string `json:"p_y"` + M string `json:"m"` + QX string `json:"q_x"` + QY string `json:"q_y"` +} + +func (e *EcOp) GetAirPrivateInput(ecOpSegment *memory.Segment) []AirPrivateBuiltinEcOp { + valueMapping := make(map[int]AirPrivateBuiltinEcOp) + for index, value := range ecOpSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/cellsPerEcOp, index%cellsPerEcOp + if typ >= inputCellsPerEcOp { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinEcOp{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if typ == 0 { + builtinValue.PX = valueHex + } else if typ == 1 { + builtinValue.PY = valueHex + } else if typ == 2 { + builtinValue.QX = valueHex + } else if typ == 3 { + builtinValue.QY = valueHex + } else if typ == 4 { + builtinValue.M = valueHex + } + valueMapping[idx] = builtinValue + } + + values := make([]AirPrivateBuiltinEcOp, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + value := valueMapping[index] + values = append(values, value) + } + return values +} diff --git a/pkg/vm/builtins/ecop_test.go b/pkg/vm/builtins/ecop_test.go index 6a3c6615..c7a2c8dc 100644 --- a/pkg/vm/builtins/ecop_test.go +++ b/pkg/vm/builtins/ecop_test.go @@ -27,7 +27,7 @@ func TestEcOp(t *testing.T) { mult := ecmult(&point{*qx, *qy}, new(uint256.Int).SetUint64(3), &utils.FeltOne) r := ecadd(&point{*px, *py}, &mult) - segment := memory.EmptySegmentWithLength(CellsPerEcOp) + segment := memory.EmptySegmentWithLength(cellsPerEcOp) ecop := &EcOp{ratio: 1024, cache: make(map[uint64]fp.Element)} segment.WithBuiltinRunner(ecop) diff --git a/pkg/vm/builtins/keccak.go b/pkg/vm/builtins/keccak.go index ff03027c..c7109230 100644 --- a/pkg/vm/builtins/keccak.go +++ b/pkg/vm/builtins/keccak.go @@ -4,6 +4,8 @@ import ( "encoding/binary" "errors" "fmt" + "math/big" + "sort" "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" @@ -18,8 +20,8 @@ import ( // const KeccakName = "keccak" -const CellsPerKeccak = 16 -const InputCellsPerKeccak = 8 +const cellsPerKeccak = 16 +const inputCellsPerKeccak = 8 const instancesPerComponentKeccak = 16 type Keccak struct { @@ -37,14 +39,14 @@ func (k *Keccak) InferValue(segment *memory.Segment, offset uint64) error { mv := memory.MemoryValueFromFieldElement(&value) return segment.Write(offset, &mv) } - hashIndex := offset % CellsPerKeccak - if hashIndex < InputCellsPerKeccak { + hashIndex := offset % cellsPerKeccak + if hashIndex < inputCellsPerKeccak { return errors.New("cannot infer value") } startOffset := offset - hashIndex var data [200]byte - for i := uint64(0); i < InputCellsPerKeccak; i++ { + for i := uint64(0); i < inputCellsPerKeccak; i++ { value := segment.Peek(startOffset + i) if !value.Known() { return fmt.Errorf("cannot infer value: input value at offset %d is unknown", startOffset+i) @@ -70,12 +72,12 @@ func (k *Keccak) InferValue(segment *memory.Segment, offset uint64) error { binary.LittleEndian.PutUint64(output[i*8:i*8+8], dataU64[i]) } - for i := 0; i < InputCellsPerKeccak; i++ { + for i := 0; i < inputCellsPerKeccak; i++ { var bytes [32]byte copy(bytes[:], output[i*25:i*25+25]) //This is 25*8 bits which is smaller than max felt 252 bits so no need to check the error v, _ := fp.LittleEndian.Element(&bytes) - k.cache[startOffset+InputCellsPerKeccak+uint64(i)] = v + k.cache[startOffset+inputCellsPerKeccak+uint64(i)] = v } value = k.cache[offset] mv := memory.MemoryValueFromFieldElement(&value) @@ -87,5 +89,70 @@ func (k *Keccak) String() string { } func (k *Keccak) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, k.ratio, InputCellsPerKeccak, instancesPerComponentKeccak, CellsPerKeccak) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, k.ratio, inputCellsPerKeccak, instancesPerComponentKeccak, cellsPerKeccak) +} + +type AirPrivateBuiltinKeccak struct { + Index int `json:"index"` + InputS0 string `json:"input_s0"` + InputS1 string `json:"input_s1"` + InputS2 string `json:"input_s2"` + InputS3 string `json:"input_s3"` + InputS4 string `json:"input_s4"` + InputS5 string `json:"input_s5"` + InputS6 string `json:"input_s6"` + InputS7 string `json:"input_s7"` +} + +func (k *Keccak) GetAirPrivateInput(keccakSegment *memory.Segment) []AirPrivateBuiltinKeccak { + valueMapping := make(map[int]AirPrivateBuiltinKeccak) + for index, value := range keccakSegment.Data { + if !value.Known() { + continue + } + idx, stateIndex := index/cellsPerKeccak, index%cellsPerKeccak + if stateIndex >= inputCellsPerKeccak { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinKeccak{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if stateIndex == 0 { + builtinValue.InputS0 = valueHex + } else if stateIndex == 1 { + builtinValue.InputS1 = valueHex + } else if stateIndex == 2 { + builtinValue.InputS2 = valueHex + } else if stateIndex == 3 { + builtinValue.InputS3 = valueHex + } else if stateIndex == 4 { + builtinValue.InputS4 = valueHex + } else if stateIndex == 5 { + builtinValue.InputS5 = valueHex + } else if stateIndex == 6 { + builtinValue.InputS6 = valueHex + } else if stateIndex == 7 { + builtinValue.InputS7 = valueHex + } + valueMapping[idx] = builtinValue + } + + values := make([]AirPrivateBuiltinKeccak, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + value := valueMapping[index] + values = append(values, value) + } + return values } diff --git a/pkg/vm/builtins/pedersen.go b/pkg/vm/builtins/pedersen.go index 7fee2491..cc9f8d58 100644 --- a/pkg/vm/builtins/pedersen.go +++ b/pkg/vm/builtins/pedersen.go @@ -3,13 +3,16 @@ package builtins import ( "errors" "fmt" + "math/big" + "sort" + "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" mem "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" pedersenhash "github.com/consensys/gnark-crypto/ecc/stark-curve/pedersen-hash" ) const PedersenName = "pedersen" -const CellsPerPedersen = 3 +const cellsPerPedersen = 3 const inputCellsPerPedersen = 2 const instancesPerComponentPedersen = 1 @@ -22,7 +25,7 @@ func (p *Pedersen) CheckWrite(segment *mem.Segment, offset uint64, value *mem.Me } func (p *Pedersen) InferValue(segment *mem.Segment, offset uint64) error { - hashIndex := offset % CellsPerPedersen + hashIndex := offset % cellsPerPedersen // input cell if hashIndex < inputCellsPerPedersen { return errors.New("cannot infer value") @@ -61,5 +64,52 @@ func (p *Pedersen) String() string { } func (p *Pedersen) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, p.ratio, inputCellsPerPedersen, instancesPerComponentPedersen, CellsPerPedersen) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, p.ratio, inputCellsPerPedersen, instancesPerComponentPedersen, cellsPerPedersen) +} + +type AirPrivateBuiltinPedersen struct { + Index int `json:"index"` + X string `json:"x"` + Y string `json:"y"` +} + +func (p *Pedersen) GetAirPrivateInput(pedersenSegment *memory.Segment) []AirPrivateBuiltinPedersen { + valueMapping := make(map[int]AirPrivateBuiltinPedersen) + for index, value := range pedersenSegment.Data { + if !value.Known() { + continue + } + idx, typ := index/cellsPerPedersen, index%cellsPerPedersen + if typ == 2 { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinPedersen{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if typ == 0 { + builtinValue.X = valueHex + } else { + builtinValue.Y = valueHex + } + valueMapping[idx] = builtinValue + } + + values := make([]AirPrivateBuiltinPedersen, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + value := valueMapping[index] + values = append(values, value) + } + return values } diff --git a/pkg/vm/builtins/poseidon.go b/pkg/vm/builtins/poseidon.go index 3fd031db..2d6ed957 100644 --- a/pkg/vm/builtins/poseidon.go +++ b/pkg/vm/builtins/poseidon.go @@ -2,14 +2,18 @@ package builtins import ( "errors" + "fmt" + "math/big" + "sort" + "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" mem "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" ) const PoseidonName = "poseidon" -const CellsPerPoseidon = 6 -const InputCellsPerPoseidon = 3 +const cellsPerPoseidon = 6 +const inputCellsPerPoseidon = 3 const instancesPerComponentPoseidon = 1 type Poseidon struct { @@ -27,13 +31,13 @@ func (p *Poseidon) InferValue(segment *mem.Segment, offset uint64) error { mv := mem.MemoryValueFromFieldElement(&value) return segment.Write(offset, &mv) } - poseidonIndex := offset % CellsPerPoseidon - if poseidonIndex < InputCellsPerPoseidon { + poseidonIndex := offset % cellsPerPoseidon + if poseidonIndex < inputCellsPerPoseidon { return errors.New("cannot infer value") } baseOffset := offset - poseidonIndex - poseidonInputValues := make([]*fp.Element, InputCellsPerPoseidon) - for i := 0; i < InputCellsPerPoseidon; i++ { + poseidonInputValues := make([]*fp.Element, inputCellsPerPoseidon) + for i := 0; i < inputCellsPerPoseidon; i++ { mv := segment.Peek(baseOffset + uint64(i)) if !mv.Known() { return errors.New("cannot infer value") @@ -56,9 +60,59 @@ func (p *Poseidon) InferValue(segment *mem.Segment, offset uint64) error { } func (p *Poseidon) GetAllocatedSize(segmentUsedSize uint64, vmCurrentStep uint64) (uint64, error) { - return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, p.ratio, InputCellsPerPoseidon, instancesPerComponentPoseidon, CellsPerPoseidon) + return getBuiltinAllocatedSize(segmentUsedSize, vmCurrentStep, p.ratio, inputCellsPerPoseidon, instancesPerComponentPoseidon, cellsPerPoseidon) } func (p *Poseidon) String() string { return PoseidonName } + +type AirPrivateBuiltinPoseidon struct { + Index int `json:"index"` + InputS0 string `json:"input_s0"` + InputS1 string `json:"input_s1"` + InputS2 string `json:"input_s2"` +} + +func (p *Poseidon) GetAirPrivateInput(poseidonSegment *memory.Segment) []AirPrivateBuiltinPoseidon { + valueMapping := make(map[int]AirPrivateBuiltinPoseidon) + for index, value := range poseidonSegment.Data { + if !value.Known() { + continue + } + idx, stateIndex := index/cellsPerPoseidon, index%cellsPerPoseidon + if stateIndex >= inputCellsPerPoseidon { + continue + } + + builtinValue, exists := valueMapping[idx] + if !exists { + builtinValue = AirPrivateBuiltinPoseidon{Index: idx} + } + + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + if stateIndex == 0 { + builtinValue.InputS0 = valueHex + } else if stateIndex == 1 { + builtinValue.InputS1 = valueHex + } else if stateIndex == 2 { + builtinValue.InputS2 = valueHex + } + valueMapping[idx] = builtinValue + } + + values := make([]AirPrivateBuiltinPoseidon, 0) + + sortedIndexes := make([]int, 0, len(valueMapping)) + for index := range valueMapping { + sortedIndexes = append(sortedIndexes, index) + } + sort.Ints(sortedIndexes) + for _, index := range sortedIndexes { + value := valueMapping[index] + values = append(values, value) + } + return values +} diff --git a/pkg/vm/builtins/range_check.go b/pkg/vm/builtins/range_check.go index 7670bef4..89596845 100644 --- a/pkg/vm/builtins/range_check.go +++ b/pkg/vm/builtins/range_check.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math" + "math/big" "github.com/NethermindEth/cairo-vm-go/pkg/utils" "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory" @@ -89,3 +90,22 @@ func (r *RangeCheck) GetRangeCheckUsage(rangeCheckSegment *memory.Segment) (uint } return minVal, maxVal } + +type AirPrivateBuiltinRangeCheck struct { + Index int `json:"index"` + Value string `json:"value"` +} + +func (r *RangeCheck) GetAirPrivateInput(rangeCheckSegment *memory.Segment) []AirPrivateBuiltinRangeCheck { + values := make([]AirPrivateBuiltinRangeCheck, 0) + for index, value := range rangeCheckSegment.Data { + if !value.Known() { + continue + } + valueBig := big.Int{} + value.Felt.BigInt(&valueBig) + valueHex := fmt.Sprintf("0x%x", &valueBig) + values = append(values, AirPrivateBuiltinRangeCheck{Index: index, Value: valueHex}) + } + return values +} From 537d710fef7b6b0dc4b43ae5b937cef720ce7aac Mon Sep 17 00:00:00 2001 From: Harikrishnan Shaji Date: Wed, 11 Sep 2024 18:27:36 +0530 Subject: [PATCH 14/14] Minor updates --- pkg/runner/air_input.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pkg/runner/air_input.go b/pkg/runner/air_input.go index 52781101..17ae40a0 100644 --- a/pkg/runner/air_input.go +++ b/pkg/runner/air_input.go @@ -6,14 +6,24 @@ import ( func (runner *ZeroRunner) GetAirPublicInput() (AirPublicInput, error) { rcMin, rcMax := runner.getPermRangeCheckLimits() + + // TODO: refactor to reuse earlier computed relocated trace + relocatedTrace := runner.vm.RelocateTrace() + firstTrace := relocatedTrace[0] + lastTrace := relocatedTrace[len(relocatedTrace)-1] + memorySegments := make(map[string]AirMemorySegmentEntry) + // TODO: you need to calculate this for each builtin + memorySegments["program"] = AirMemorySegmentEntry{BeginAddr: firstTrace.Pc, StopPtr: lastTrace.Pc} + memorySegments["execution"] = AirMemorySegmentEntry{BeginAddr: firstTrace.Ap, StopPtr: lastTrace.Ap} + return AirPublicInput{ Layout: runner.layout.Name, RcMin: rcMin, RcMax: rcMax, NSteps: len(runner.vm.Trace), DynamicParams: nil, - // TODO: yet to be implemented - MemorySegments: make(map[string]AirMemorySegmentEntry), + // TODO: yet to be implemented fully + MemorySegments: memorySegments, // TODO: yet to be implemented PublicMemory: make([]AirPublicMemoryEntry, 0), }, nil @@ -30,8 +40,8 @@ type AirPublicInput struct { } type AirMemorySegmentEntry struct { - BeginAddr int `json:"begin_addr"` - StopPtr int `json:"stop_ptr"` + BeginAddr uint64 `json:"begin_addr"` + StopPtr uint64 `json:"stop_ptr"` } type AirPublicMemoryEntry struct {