Hi gang, I'm trying to solve day 13 of the 17 days of the Cairo Challenge: Pedersen Hash This is my solution so far
// Computes the Pedersen hash chain on an array of size `length` starting from `data_ptr`.
func hash_chain{hash_ptr: HashBuiltin*}(data_ptr: felt*, length: felt) -> (result: felt) {
if (length == 2) {
let (result) = hash2(x=[data_ptr], y=[data_ptr + 1]);
return (result=result);
} else {
// Fix here:
let x_n: felt = data_ptr[length];
result = hash2(hash_chain(data_ptr, length - 1), x_n);
return (result=result);
}
}
And I got revoked and I have no idea what's going on. Can anyone please explain? TIA
Error: code:29:9: Reference 'result' was revoked.
result = hash2(tmp, x_n);
^****^
Feel like start in the middle of the ocean.
Cairo playground
- 05_variables
let
,tempvar
andlocal
:let
creates lot of temporary variables
Cairo playground
To be honest have little idea what happend
- this will not give error
func main{output_ptr: felt*}() {
let (x) = foo(10);
let (y) = foo(5);
return ();
}
- But adding
serialize_word(x + y);
will give error
func main{output_ptr: felt*}() {
let (x) = foo(10);
let (y) = foo(5);
serialize_word(x + y);
return ();
}
-
2 ways to fix error:
alloc_locals;
ap += SIZEOF_LOCALS; let (local x) = foo(10); let (local y) = foo(5);
-
Local variables are not revoked when functions are called
-
Read more about local variables here
- segments mechanism
- Thanks to this mechanism,
alloc
allocates an array of an arbitrary size, which does not need to be specified in the call.
func sqr_array(array: felt*, length: felt) -> (new_array: felt*) {
alloc_locals;
// allocate new memory slot for new_array
let (local new_array) = alloc();
// calculate the new_array by the helper function _inner_sqr_array
// this function does return anything
_inner_sqr_array(array=array, new_array=new_array, length=length);
return (new_array=new_array);
}
Cairo playground
Just totally random thought, play with output_ptr
by serialize_word
Cairo playground
let (__fp__, _) = get_fp_and_pc(); // need this to work
local x: felt;
local y: felt* = &x; // y is a pointer at position of felt x
assert [y] = 1234;
-
Implementation of a stack using a linked list.
- Remind of CS50 C lession, linked list element contains (next: pointer*, value, size)
-
To turn memory address into a pointer we have to use the & operator.
-
By default the compiler wouldn’t know what type of pointer this is so to inform it of the type we have to use the function
cast
and provide the type as the second argument -
new_node.next = cast(0, Node*);
: pointer to the 1st Node struct
-
implements a Pedersen hash chain.
-
tried this simple recursion but got
revoked
Error: code:28:9: Reference 'result' was revoked.
result = hash2(hash_chain(data_ptr, length - 1), x_n);
^****^
func hash_chain{hash_ptr: HashBuiltin*}(data_ptr: felt*, length: felt) -> (result: felt) {
if (length == 2) {
let (result) = hash2(x=[data_ptr], y=[data_ptr + 1]);
return (result=result);
} else {
// Fix here:
let x_n: felt = data_ptr[length];
result = hash2(hash_chain(data_ptr, length - 1), x_n);
return (result=result);
}
}
- The idea is that the verifier only needs to be convinced that res * res = n, it doesn't really care how res was computed.
- In such cases, we don't have to compute res in pure Cairo - we can write a piece of Python code inside the Cairo program, which is called a "hint".
- From the verifier's point of view, the hint is completely transparent.
wtf
prover, verifier, sharp, where it goes
The utils.py
is useful for type conversion
MAX_LEN_FELT = 31
def str_to_felt(text):
if len(text) > MAX_LEN_FELT:
raise Exception("Text length too long to convert to felt.")
return int.from_bytes(text.encode(), "big")
def felt_to_str(felt):
length = (felt.bit_length() + 7) // 8
return felt.to_bytes(length, byteorder="big").decode("utf-8")
def str_to_felt_array(text):
return [str_to_felt(text[i:i+MAX_LEN_FELT]) for i in range(0, len(text), MAX_LEN_FELT)]
def uint256_to_int(uint256):
return uint256[0] + uint256[1]*2**128
def uint256(val):
return (val & 2**128-1, (val & (2**256-2**128)) >> 128)
def hex_to_felt(val):
return int(val, 16)
>>> uint256(5)
(5, 0)
>>> uint256_to_int((5,1))
340282366920938463463374607431768211461
>>> uint256(340282366920938463463374607431768211461)
(5, 1)
>>> 2**128
340282366920938463463374607431768211456
>>> uint256(340282366920938463463374607431768211456)
(0, 1)
- Dictionary
- A dictionary is created using the
default_dict_new()
module from the Common Library - https://perama-v.github.io/cairo/examples/default_dict/
- A dictionary is created using the
- Something with a graph that might be well related, PAKHET Cairo game
default_dict.cairo
. . .
- skip, not really skip but tried different approach to solve a particular problem, ml-starknet
- but sometime, you dont know what you dont know so resuming
StarkNet messaging bridge
- call
ex_0_a
, with L1 address, amount = 1 - rank will be assigned
-
Unexpected implicit argument 'hash_ptr' in an external function.
- dont put
hash_ptr
as argument - use
pedersen_ptr: HashBuiltin*,
- in the function that need
hash_ptr
define it explicitly e.ghash2{hash_ptr=pedersen_ptr}
- dont put
-
facing issue on
starknet declare
❯ starknet declare --contract artifacts/contract.json
Error: KeyError: 'deployed'
- nile declare
- nile setup got weird
❯ echo $PKEY2
key exists
❯ nile setup PKEY2
❌ Cannot find PKEY2 in env.
Check spelling and that it exists.
Try moving the .env to the root of your project.
- work around
PKEY1=_key_ nile setup PKEY1
PKEY=_key_ nile declare contract
also worknile deploy contract 3 --network goerli
- worked
- no need
--class_hash
- takes care of declaration