mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-19 23:21:46 +03:00
eab43eb800
* Add chialispp port to pre-commit * Lint files
136 lines
5.1 KiB
Plaintext
136 lines
5.1 KiB
Plaintext
(
|
|
;; The code below is used to calculate of the tree hash of a curried function
|
|
;; without actually doing the curry, and using other optimization tricks
|
|
;; like unrolling `sha256tree`.
|
|
|
|
(defconstant TWO 2)
|
|
(defconstant constant_tree (
|
|
(0x4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a . ; = `(sha256 1)`
|
|
0x9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2) . ; = `(sha256 1 1)` = `(sha256 1 #q)`
|
|
(0x02a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222 . ; = `(concat 2 (sha256 1 #a))`
|
|
0x02a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5) ; = `(concat 2 (sha256 1 #c))`
|
|
)
|
|
)
|
|
|
|
; I looked into calculating the values of `constant_tree` because it's pretty easy to code-golf
|
|
; out an implementation that produces the values cheaper than just inlining them. The problem is,
|
|
; when do we calculate them? If there were a way to calculate it "before main" and include it in
|
|
; the globally-accessible constant table, we could do that. But we can't which means to be optimal,
|
|
; client code should call the "build table" code once, then pass it around to anyone that wants to
|
|
; call `curry` or `curry2`. This is pretty intrusive, so for now we'll just use the existing
|
|
; global constant infrastructure, and include it as a fixed table so the tree of four values will
|
|
; appear in all code that includes this file, and it will compress better in generators.
|
|
|
|
(defun-inline sha256_one _noargs (f (f constant_tree)))
|
|
(defun-inline sha256_one_one _noargs (r (f constant_tree)))
|
|
(defun-inline two_sha256_one_a_kw _noargs (f (r constant_tree)))
|
|
(defun-inline two_sha256_one_c_kw _noargs (r (r constant_tree)))
|
|
|
|
;; this returns the sha256 tree hash of expression F = `((q . a1) a2)`
|
|
(defun hash_expression_F (a1 a2)
|
|
(sha256 TWO (sha256 TWO (sha256_one_one) a1)
|
|
(sha256 TWO a2 (sha256_one)))
|
|
)
|
|
|
|
;; Given the tree hash `environment_hash` of an environment tree E
|
|
;; and the tree hash `parameter_hash` of a constant parameter P
|
|
;; return the tree hash of the tree corresponding to
|
|
;; `(c (q . P) E)`
|
|
;; This is the new environment tree with the addition parameter P curried in.
|
|
;;
|
|
;; Note that `(c (q . P) E)` = `(c . ((q . P) . (E . 0)))`
|
|
|
|
(defun-inline update_hash_for_parameter_hash (parameter_hash environment_hash)
|
|
(sha256 (two_sha256_one_c_kw) (hash_expression_F parameter_hash environment_hash))
|
|
)
|
|
|
|
;; Given the tree hash `environment_hash` of an environment tree E
|
|
;; and the tree hash `mod_hash` of a mod M
|
|
;; return the tree hash of the tree corresponding to
|
|
;; `(a (q . M) E)`
|
|
;; This is the hash of a new function that adopts the new environment E.
|
|
;; This is used to build of the tree hash of a curried function.
|
|
;;
|
|
;; Note that `(a (q . M) E)` = `(a . ((q . M) . (E . 0)))`
|
|
|
|
(defun-inline tree_hash_of_apply (mod_hash environment_hash)
|
|
(sha256 (two_sha256_one_a_kw) (hash_expression_F mod_hash environment_hash))
|
|
)
|
|
|
|
;; This function recursively calls `update_hash_for_parameter_hash`
|
|
|
|
(defun calculate_hash_of_curried_parameters (curry_parameter_hashes)
|
|
(if curry_parameter_hashes
|
|
(update_hash_for_parameter_hash (f curry_parameter_hashes) (calculate_hash_of_curried_parameters (r curry_parameter_hashes)))
|
|
(sha256_one_one)
|
|
)
|
|
)
|
|
|
|
;; mod_hash:
|
|
;; the hash of a puzzle function, ie. a `mod`
|
|
;;
|
|
;; curry_parameter_hashes:
|
|
;; a list of pre_hashed trees representing parameters to be curried into the puzzle.
|
|
;;
|
|
;; we return the hash of the curried expression
|
|
;; (a (q . mod_hash) (c (cp1 (c cp2 (c ... 1)...))))
|
|
;;
|
|
;; Note that from a user's perspective the hashes passed in here aren't simply
|
|
;; the hashes of the desired parameters, but their treehash representation since
|
|
;; that's the form we're assuming they take in the acutal curried program.
|
|
|
|
;; inline functions that take varargs don't seem to work, so we can't inline `curry`
|
|
|
|
(defun curry_hashes (mod_hash . curry_parameter_hashes)
|
|
(tree_hash_of_apply mod_hash
|
|
(calculate_hash_of_curried_parameters curry_parameter_hashes))
|
|
)
|
|
|
|
|
|
;; This is the macro version that inlines everything and expects varargs parameters.
|
|
;; It may be more efficient in some cases.
|
|
|
|
(defmacro curry_hashes_inline (mod_hash . curry_parameter_hashes)
|
|
(qq
|
|
(sha256
|
|
; apply
|
|
(two_sha256_one_a_kw)
|
|
(sha256 TWO
|
|
; func
|
|
(sha256 TWO
|
|
(sha256_one_one)
|
|
(unquote mod_hash)
|
|
)
|
|
(sha256 TWO
|
|
; args
|
|
(unquote (c build_pre_hashed_environment curry_parameter_hashes))
|
|
(sha256_one)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
;; helper macro
|
|
|
|
(defmacro build_pre_hashed_environment curry_parameter_hashes
|
|
(qq
|
|
(sha256
|
|
(two_sha256_one_c_kw)
|
|
(sha256 TWO
|
|
(sha256 TWO
|
|
(sha256_one_one)
|
|
(unquote (f curry_parameter_hashes))
|
|
)
|
|
(sha256 TWO
|
|
(unquote (if (r curry_parameter_hashes) (c build_pre_hashed_environment (r curry_parameter_hashes)) (q . (sha256_one_one))))
|
|
(sha256_one)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
)
|