-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] crypto examples #31
base: master
Are you sure you want to change the base?
Changes from all commits
b6a69ab
091ef49
8e744dc
fc1e10c
c5d326e
c6512f9
5b1a240
4e5e3da
5b6856a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
; crypto-tests.lurk | ||
; | ||
; tests for crypto.lurk | ||
; | ||
; run in repl as: | ||
; > :run "crypto-tests.lurk" | ||
|
||
!(:load "crypto.lurk") | ||
|
||
!(:assert-eq (odd 0) NIL) | ||
!(:assert-eq (odd 121) T) | ||
!(:assert-eq (odd (/ 2 3)) T) | ||
|
||
!(:assert-eq (even 0) T) | ||
!(:assert-eq (even 121) NIL) | ||
!(:assert-eq (even (/ 2 3)) NIL) | ||
|
||
!(:assert-eq (fastexp 129 13) 2739468013418114691600975489) | ||
!(:assert-eq (fastexp 129 921) 0x188bc6b313e74bcf3c8f8ddb1311c5e892b271c636866b64930d3357600c7f3f) | ||
|
||
!(:assert-eq (gcd 11856 25883) 13) | ||
|
||
!(:assert-eq (hash1 3) 0x12c26d76c2dff4b314388dc4ed60788206d921608575f77b1b9340e17a41b015) | ||
!(:assert-eq (hashn '(1 2 3 4 5)) 0x0c46596ba7b418cdea2764e0c8f48d48c418ab1b7e141981aaddfb70d439666c) | ||
|
||
!(:assert-eq (hashn '(1 2)) (hash2 1 2)) | ||
|
||
!(assert-eq (tree8 1 2 3 4 5 6 7 8) | ||
0x02fdb269fa0d532c68afb6120682cb0453255d71cdb09ac6323ef13a4dcada0e) | ||
|
||
|
||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
; crypto.lurk | ||
; | ||
; simple crypto-related functions | ||
; | ||
; load in repl as: | ||
; > :load "crypto.lurk" | ||
|
||
|
||
(letrec ( | ||
|
||
; parity tests | ||
(odd (lambda (a) (< (/ a 2) 0))) | ||
(even (lambda (a) (eq NIL (odd a)))) | ||
|
||
; square & multiply exponentiation | ||
(fastexp (lambda (b e) | ||
(if (= e 0) 1 | ||
(if (even e) (fastexp (* b b) (/ e 2)) | ||
(* b (fastexp (* b b) (/ (- e 1) 2))))))) | ||
|
||
(odd64 (lambda (a) (eq 1u64 (% (u64 a) 2u64)))) | ||
(even64 (lambda (a) (eq NIL (odd64 a)))) | ||
|
||
(fastexp64 (lambda (b e) | ||
(if (= e 0) 1 | ||
(if (even e) (fastexp64 (* (u64 b) (u64 b)) (/ e 2)) | ||
(* (u64 b) (fastexp64 (* (u64 b) (u64 b)) (/ (- e 1) 2))))))) | ||
|
||
; GCD | ||
(gcd (lambda (a b) | ||
(if (= a b) a | ||
(if (> a b) (gcd (- a b) b) | ||
(gcd (- b a) a))))) | ||
|
||
; hash function, poseidon-like | ||
; 2-element permutation used by the hash | ||
; NOT cryptographically safe | ||
(permute (lambda (a b) | ||
(letrec ( | ||
(rnd (lambda (i a b) (let ( | ||
(mat1 (lambda (a b) (+ (/ a 3) (* b 5)))) | ||
(mat2 (lambda (a b) (+ (/ a 7) (* b 9)))) | ||
(sbox (lambda (a) (fastexp a 5))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool. Obviously in this case, it would be cheaper just to expand by hand. I like the explanatory library function, just thought I would mention it as an aside. |
||
(add1 (lambda (a) (+ a (/ 2 3)))) | ||
(add2 (lambda (a) (+ a (/ 3 2)))) | ||
) | ||
(cons | ||
(+ i (add1 (sbox (mat1 a b)))) | ||
(add2 (sbox (mat2 a b))))))) | ||
(iter (lambda (i a b) | ||
(if (= i 4) ; 4 rounds | ||
(cons a b) | ||
(let ( | ||
(res (rnd i a b)) | ||
(a (car res)) | ||
(b (cdr res)) | ||
) | ||
(iter (+ i 1) a b)))))) | ||
(iter 0 a b)))) | ||
|
||
; initial state of the hash will be (0 iv) | ||
(iv (/ 5 2)) | ||
|
||
; hash 1 element | ||
(hash1 (lambda (a) (car (permute a iv)))) | ||
|
||
; hash 2 elements | ||
(hash2 (lambda (a b) | ||
(let ( | ||
(res1 (permute a iv)) | ||
(res2 (permute (+ b (car res1)) (cdr res1))) | ||
) | ||
(car res2)))) | ||
|
||
; hash a list of elements | ||
; such that (hashn '(a b)) = (hash2 a b) | ||
(hashn (lambda (alist) | ||
(if (eq alist nil) nil | ||
(let ( | ||
(res0 (permute (car alist) iv)) | ||
) | ||
(letrec ( | ||
(iter (lambda (blist a b) | ||
(if (eq blist nil) a | ||
(let ( | ||
(res (permute (+ (car blist) a) b)) | ||
) | ||
(iter (cdr blist) (car res) (cdr res)))))) | ||
) | ||
(iter (cdr alist) (car res0) (cdr res0))))))) | ||
|
||
; basic 8-leaf tree | ||
(tree8 (lambda (a b c d e f g h) | ||
(hash2 | ||
(hash2 (hash2 a b) (hash2 c d)) | ||
(hash2 (hash2 e f) (hash2 g h))))) | ||
|
||
; proof of membership check | ||
(treeproof8 (lambda (root x h1 h2 h3) | ||
(eq root (hash2 h1 (hash2 h2 (hash2 h3 x)))))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this a lot as an example. One nice thing about Lurk is that if you replace Put differently, Lurk makes obvious that merkle proofs are exactly membership tests. In this case, the 'container' is an 8-leaf binary tree. So if we were to hard-code the leaf in question like your example, we could just write:
Of course that requires that Since we have primitives for commitments and get some useful properties from them, you could also use Then you would have
I know these examples don't replace what you were trying to do here. I just wrote them out in case they help you get a better picture of why some Lurk features are as they are, and what they enable. |
||
|
||
) | ||
(current-env)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat. Note that GCD only makes sense if you view
a
andb
as natural numbers. (As field elements, you could kind of argue that every value is divided by <whichever value you consider 'greatest'>). If that's how you mean it, then it's important to specify (or check) thata
andb
are in range. I think if either one is negative, then your>
check won't give the right results. We spent some time thinking about this example (GCD — not your code) recently, but I still might have gotten a detail wrong in my quick summary. cc: @emmorais @differentialderek @weissjeffmThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a comment to clarify, so people studying this code don't get confused or misled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is sleek—the nice thing about it is that it doesn't require values greater than
a
andb
so from the "field-elements-as-integers" perspective this is simulates normal gcd for positives (as long as you start with positives, you don't run the risk of getting so positive that you go negative).I have a much more clunky version here: #32 lol, probably should throw that one away now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this recurses infinitely if
a
orb
is negative, which can be solved by adding something likeor failing if
(< a 0)
or(< b 0)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the field arithmetic there is some ambiguity on what
<
means too -- not sure if that's a problem here @emmorais? I think if you start from the position of(< 0 a)
and(< 0 b)
, this simulates gcd on natural numbers