Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into add-divrem-hints
Browse files Browse the repository at this point in the history
  • Loading branch information
entropidelic committed Sep 19, 2023
2 parents e568e66 + 9c2a7f0 commit ae96b35
Show file tree
Hide file tree
Showing 26 changed files with 2,139 additions and 29 deletions.
31 changes: 31 additions & 0 deletions cairo_programs/assert_250_bit_element_array.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
%builtins range_check

from starkware.cairo.common.math import assert_250_bit
from starkware.cairo.common.alloc import alloc

func assert_250_bit_element_array{range_check_ptr: felt}(
array: felt*, array_length: felt, iterator: felt
) {
if (iterator == array_length) {
return ();
}
assert_250_bit(array[iterator]);
return assert_250_bit_element_array(array, array_length, iterator + 1);
}

func fill_array(array: felt*, base: felt, step: felt, array_length: felt, iterator: felt) {
if (iterator == array_length) {
return ();
}
assert array[iterator] = base + step * iterator;
return fill_array(array, base, step, array_length, iterator + 1);
}

func main{range_check_ptr: felt}() {
alloc_locals;
tempvar array_length = 10;
let (array: felt*) = alloc();
fill_array(array, 70000000000000000000, 300000000000000000, array_length, 0);
assert_250_bit_element_array(array, array_length, 0);
return ();
}
13 changes: 13 additions & 0 deletions cairo_programs/common_signature.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
%builtins ecdsa
from starkware.cairo.common.cairo_builtins import SignatureBuiltin
from starkware.cairo.common.signature import verify_ecdsa_signature

func main{ecdsa_ptr: SignatureBuiltin*}() {
verify_ecdsa_signature(
2718,
1735102664668487605176656616876767369909409133946409161569774794110049207117,
3086480810278599376317923499561306189851900463386393948998357832163236918254,
598673427589502599949712887611119751108407514580626464031881322743364689811,
);
return ();
}
29 changes: 29 additions & 0 deletions cairo_programs/dict_squash.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
%builtins range_check

from starkware.cairo.common.dict_access import DictAccess
from starkware.cairo.common.dict import dict_write, dict_update, dict_squash
from starkware.cairo.common.default_dict import default_dict_new

func main{range_check_ptr}() -> () {
let (dict_start) = default_dict_new(17);
let dict_end = dict_start;
dict_write{dict_ptr=dict_end}(0, 1);
dict_write{dict_ptr=dict_end}(1, 10);
dict_write{dict_ptr=dict_end}(2, -2);
dict_update{dict_ptr=dict_end}(0, 1, 2);
dict_update{dict_ptr=dict_end}(0, 2, 3);
dict_update{dict_ptr=dict_end}(0, 3, 4);
dict_update{dict_ptr=dict_end}(1, 10, 15);
dict_update{dict_ptr=dict_end}(1, 15, 20);
dict_update{dict_ptr=dict_end}(1, 20, 25);
dict_update{dict_ptr=dict_end}(2, -2, -4);
dict_update{dict_ptr=dict_end}(2, -4, -8);
dict_update{dict_ptr=dict_end}(2, -8, -16);
let (squashed_dict_start, squashed_dict_end) = dict_squash{range_check_ptr=range_check_ptr}(
dict_start, dict_end
);
assert squashed_dict_end[0] = DictAccess(key=0, prev_value=1, new_value=4);
assert squashed_dict_end[1] = DictAccess(key=1, prev_value=10, new_value=25);
assert squashed_dict_end[2] = DictAccess(key=2, prev_value=-2, new_value=-16);
return ();
}
42 changes: 42 additions & 0 deletions cairo_programs/split_felt.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
%builtins range_check

from starkware.cairo.common.math import assert_le
from starkware.cairo.common.math import split_felt

func split_felt_manual_implemetation{range_check_ptr}(value) -> (high: felt, low: felt) {
// Note: the following code works because PRIME - 1 is divisible by 2**128.
const MAX_HIGH = (-1) / 2 ** 128;
const MAX_LOW = 0;

// Guess the low and high parts of the integer.
let low = [range_check_ptr];
let high = [range_check_ptr + 1];
let range_check_ptr = range_check_ptr + 2;

%{
from starkware.cairo.common.math_utils import assert_integer
assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128
assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW
assert_integer(ids.value)
ids.low = ids.value & ((1 << 128) - 1)
ids.high = ids.value >> 128
%}

assert value = high * (2 ** 128) + low;
if (high == MAX_HIGH) {
assert_le(low, MAX_LOW);
} else {
assert_le(high, MAX_HIGH - 1);
}
return (high=high, low=low);
}

func main{range_check_ptr: felt}() {
let (m, n) = split_felt_manual_implemetation(5784800237655953878877368326340059594760);
assert m = 17;
assert n = 8;
let (x, y) = split_felt(5784800237655953878877368326340059594760);
assert x = 17;
assert y = 8;
return ();
}
33 changes: 33 additions & 0 deletions cairo_programs/squash_dict.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
%builtins range_check

from starkware.cairo.common.squash_dict import squash_dict
from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.dict_access import DictAccess

func main{range_check_ptr}() -> () {
alloc_locals;
let (dict_start: DictAccess*) = alloc();
assert dict_start[0] = DictAccess(key=0, prev_value=100, new_value=100);
assert dict_start[1] = DictAccess(key=1, prev_value=50, new_value=50);
assert dict_start[2] = DictAccess(key=0, prev_value=100, new_value=200);
assert dict_start[3] = DictAccess(key=1, prev_value=50, new_value=100);
assert dict_start[4] = DictAccess(key=0, prev_value=200, new_value=300);
assert dict_start[5] = DictAccess(key=1, prev_value=100, new_value=150);

let dict_end = dict_start + 6 * DictAccess.SIZE;
// (dict_start, dict_end) now represents the dictionary
// {0: 100, 1: 50, 0: 200, 1: 100, 0: 300, 1: 150}.

// Squash the dictionary from an array of 6 DictAccess structs
// to an array of 2, with a single DictAccess entry per key.
let (local squashed_dict_start: DictAccess*) = alloc();
let (squashed_dict_end) = squash_dict{range_check_ptr=range_check_ptr}(
dict_start, dict_end, squashed_dict_start
);

// Check the values of the squashed_dict
// should be: {0: (100, 300), 1: (50, 150)}
assert squashed_dict_start[0] = DictAccess(key=0, prev_value=100, new_value=300);
assert squashed_dict_start[1] = DictAccess(key=1, prev_value=50, new_value=150);
return ();
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.20
require (
github.com/pkg/errors v0.9.1
golang.org/x/crypto v0.12.0
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc
)

require (
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6S
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU=
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7 changes: 3 additions & 4 deletions pkg/builtins/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/pkg/errors"
)

const SIGNATURE_BUILTIN_NAME = "signature"
const SIGNATURE_BUILTIN_NAME = "ecdsa"

// Notice changing this to any other number breaks the code
const SIGNATURE_CELLS_PER_INSTANCE = 2
Expand Down Expand Up @@ -166,12 +166,11 @@ func (r *SignatureBuiltinRunner) AddValidationRule(mem *memory.Memory) {
}

// Helper function to AddSignature
func AddSignature(
signatureBuiltin *SignatureBuiltinRunner,
func (r *SignatureBuiltinRunner) AddSignature(
address memory.Relocatable,
signature Signature,
) {
signatureBuiltin.signatures[address] = signature
r.signatures[address] = signature
}

func (runner *SignatureBuiltinRunner) GetMemoryAccesses(manager *memory.MemorySegmentManager) ([]memory.Relocatable, error) {
Expand Down
67 changes: 67 additions & 0 deletions pkg/hints/dict_hints.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,70 @@ func dictUpdate(ids IdsManager, scopes *ExecutionScopes, vm *VirtualMachine) err
tracker.CurrentPtr.Offset += DICT_ACCESS_SIZE
return nil
}

func dictSquashCopyDict(ids IdsManager, scopes *ExecutionScopes, vm *VirtualMachine) error {
// Extract Variables
dictManager, ok := FetchDictManager(scopes)
if !ok {
return errors.New("Variable __dict_manager not present in current execution scope")
}
dictAccessEnd, err := ids.GetRelocatable("dict_accesses_end", vm)
if err != nil {
return err
}
// Hint logic
tracker, err := dictManager.GetTracker(dictAccessEnd)
if err != nil {
return err
}
initialDict := tracker.CopyDictionary()
scopes.EnterScope(map[string]interface{}{
"__dict_manager": dictManager,
"initial_dict": initialDict,
})
return nil
}

func dictSquashUpdatePtr(ids IdsManager, scopes *ExecutionScopes, vm *VirtualMachine) error {
// Extract Variables
dictManager, ok := FetchDictManager(scopes)
if !ok {
return errors.New("Variable __dict_manager not present in current execution scope")
}
squashedDictStart, err := ids.GetRelocatable("squashed_dict_start", vm)
if err != nil {
return err
}
squashedDictEnd, err := ids.GetRelocatable("squashed_dict_end", vm)
if err != nil {
return err
}
// Hint logic
tracker, err := dictManager.GetTracker(squashedDictStart)
if err != nil {
return err
}
tracker.CurrentPtr = squashedDictEnd
return nil
}

func dictNew(ids IdsManager, scopes *ExecutionScopes, vm *VirtualMachine) error {
// Fetch scope variables
initialDictAny, err := scopes.Get("initial_dict")
if err != nil {
return err
}
initialDict, ok := initialDictAny.(map[memory.MaybeRelocatable]memory.MaybeRelocatable)
if !ok {
return errors.New("initial_dict not in scope")
}
// Hint Logic
dictManager, ok := FetchDictManager(scopes)
if !ok {
newDictManager := NewDictManager()
dictManager = &newDictManager
scopes.AssignOrUpdateVariable("__dict_manager", dictManager)
}
dict_ptr := dictManager.NewDictionary(&initialDict, vm)
return vm.Segments.Memory.Insert(vm.RunContext.Ap, memory.NewMaybeRelocatableRelocatable(dict_ptr))
}
Loading

0 comments on commit ae96b35

Please sign in to comment.