; This puzzle is intended to go inside of a taproot section of a standard inner puzzle. It does not, however,
; concern itself with re-creating the coin it is a part of. Since this is likely inside of a singleton, this will result
; in an error unless some higher puzzle takes care of recreation.
;
; Curried into this puzzle are 2 things:
; 1) Some info for constructing a bridge. A bridge from this puzzle's perspective is a singleton(state_layer(*)) puzzle
; stack, where the state_layer has a metadata of a single "height" integer and the updater accepts a solution of
; ((new_metadata new_metadata_updater_ph) conditions) - likely `11`.
;
; 2) A root of "validations". Each validation is (height . puzzle_hash) pair which signifies a vote on a payment to be
; made mapped to a height on another blockchain (for example). The validator will make an announcement such that the
; bridge's height is updated to the maximum height of the validations revealed + 1 (the next height to be validated)
; and the bridge creates a coin with amount 0 and the specified puzzle hash.
;
; The validations are stored in a binary tree and to spend this coin, one must provide a reveal of that binary tree
; all the way down to the validation pairs within. However, if the spender does not wish to announce all of the pairs
; in the tree, the can instead just reveal the necessary branch hashes to prove the other pairs' inclusion in the
; curried in root. For example, consider the following validation tree:
; 0xVALIDATION_ROOT
; / \
; / \
; 0xbranch1 0xbranch2
; / \ / \
; (0 . 0x...) (1 . 0x...) (2 . 0x...) (3 . 0x...)
;
; If the spender only wished to validate heights 0-1, they would provide the following reveal:
; 0xVALIDATION_ROOT
; / \
; / \
; 0xbranch1 0xbranch2
; / \
; (0 . 0x...) (1 . 0x...)
;
; And later, if they wished to validate height 2, they would provide the following tree:
; 0xVALIDATION_ROOT
; / \
; / \
; 0xbranch1 0xbranch2
; / \
; (2 . 0x...) 0xpair_hash3
(mod
(
BRIDGE_SINGLETON_STRUCT
NFT_STATE_LAYER_MOD_HASH ; The metadata should be a single integer and the updater is supplied in solution
VALIDATION_ROOT ; A binary tree of (height . secure_the_bag_ph) pairs
bridge_height
bridge_metadata_updater_hash
bridge_inner_puzhash
bridge_amount
validations_proof ; A reveal of the validation tree, with un-needed pairs already pre-hashed
)
(include *standard-cl-22*)
(include condition_codes.clib)
(include curry.clib)
(include sha256tree.clib)
(include utility_macros.clib)
(defconstant ONE 1)
(defun-inline calculate_singleton_puzzle_hash
(
(@ BRIDGE_SINGLETON_STRUCT
(SINGLETON_MOD_HASH . (LAUNCHER_ID . SINGLETON_LAUNCHER_HASH))
)
NFT_STATE_LAYER_MOD_HASH
bridge_height
bridge_metadata_updater_hash
bridge_inner_puzhash
)
(curry_mod_hash_with_hashes SINGLETON_MOD_HASH
(sha256tree BRIDGE_SINGLETON_STRUCT)
(curry_mod_hash_with_hashes NFT_STATE_LAYER_MOD_HASH
(sha256 ONE NFT_STATE_LAYER_MOD_HASH)
(sha256 ONE bridge_height)
(sha256 ONE bridge_metadata_updater_hash)
bridge_inner_puzhash
)
)
)
; utility function that turns the output of two calls to collapse_tree_and_note_leaf_info into a single return value
(defun branch_hash_and_merge_info ((TREE1 PAYMENTS1 TOTAL1 MIN1 MAX1) (TREE2 PAYMENTS2 TOTAL2 MIN2 MAX2))
(list
(sha256 TWO TREE1 TREE2)
(merge_list PAYMENTS1 PAYMENTS2)
(+ TOTAL1 TOTAL2)
(min MIN1 MIN2)
(max MAX1 MAX2)
)
)
(defun collapse_tree_and_note_leaf_info (TREE PAYMENTS TOTAL MIN_HEIGHT MAX_HEIGHT)
(if (l TREE)
(if (or (l (f TREE)) (l (r TREE))) ; If either side is a cons, we have not reached a leaf pair yet
(branch_hash_and_merge_info
(collapse_tree_and_note_leaf_info (f TREE) () 0 MIN_HEIGHT MAX_HEIGHT)
; we favor right because merge_list merges from left
(collapse_tree_and_note_leaf_info (r TREE) PAYMENTS TOTAL MIN_HEIGHT MAX_HEIGHT)
)
(branch_hash_and_merge_info
(list (sha256 ONE (f TREE)) () 0 MIN_HEIGHT MAX_HEIGHT)
(list (sha256 ONE (r TREE)) (c (r TREE) PAYMENTS) (+ TOTAL 1) (f TREE) (f TREE))
)
)
(list TREE PAYMENTS TOTAL MIN_HEIGHT MAX_HEIGHT) ; All atoms that we reach must be pre-hashed subtrees
)
)
(defun assert_root_and_calculate_delegated_puzzle_hash
(
VALIDATION_ROOT
bridge_height
bridge_metadata_updater_hash
bridge_inner_puzhash
bridge_amount
(ROOT PAYMENTS TOTAL MIN_HEIGHT MAX_HEIGHT)
)
(assert
(= VALIDATION_ROOT ROOT)
; Given the tree is honestly constructed, this ensures that a sequential set of integer heights was revealed
(= TOTAL (- MAX_HEIGHT MIN_HEIGHT))
; You must reveal the current height of the bridge (no skipping heights)
(= bridge_height MIN_HEIGHT)
; You cannot reveal heights less than the current height of the bridge (no double dipping)
(not (> bridge_height MAX_HEIGHT))
; then
; manual sha256tree expansion of:
; (q .
; (
; (-24 bridge_metadata_updater_hash ((max_height bridge_metadata_updater_hash) ()))
; .
; (calculate_output_conditions_hash ...)
; )
; )
(sha256 TWO
(sha256_one_one)
(sha256 TWO
(sha256 TWO
(sha256 ONE -24)
(sha256 TWO
bridge_metadata_updater_hash
(sha256 TWO
(sha256 TWO
(sha256 TWO
(sha256 ONE MAX_HEIGHT)
(sha256 TWO
(sha256 ONE bridge_metadata_updater_hash)
(sha256_one)
)
)
(sha256 TWO
(sha256_one) ; empty list of conditions
(sha256_one)
)
)
(sha256_one)
)
)
)
(calculate_output_conditions_hash
bridge_height
bridge_metadata_updater_hash
bridge_inner_puzhash
bridge_amount
PAYMENTS
)
)
)
)
)
(defun calculate_output_conditions_hash
(
bridge_height
bridge_metadata_updater_hash
bridge_inner_puzhash
bridge_amount
PAYMENTS
)
(if PAYMENTS
; manual sha256tree expansion of ((CREATE_COIN (f PAYMENTS) 0) . (calculate_output_conditions_hash ...))
(sha256 TWO
(sha256 TWO
(sha256 ONE CREATE_COIN)
(sha256 TWO
(sha256 ONE (f PAYMENTS))
(sha256 TWO
(sha256_one)
(sha256_one)
)
)
)
(calculate_output_conditions_hash
bridge_height
bridge_metadata_updater_hash
bridge_inner_puzhash
bridge_amount
(r PAYMENTS)
)
)
; else
; manual sha256tree expansion of:
; (
; (CREATE_PUZZLE_ANNOUNCEMENT bridge_height)
; (ASSERT_MY_AMOUNT bridge_amount)
; (CREATE_COIN bridge_inner_puzhash bridge_amount)
; )
(sha256 TWO
(sha256 TWO
(sha256 ONE CREATE_PUZZLE_ANNOUNCEMENT)
(sha256 TWO
(sha256 ONE bridge_height)
(sha256_one)
)
)
(sha256 TWO
(sha256 TWO
(sha256 ONE ASSERT_MY_AMOUNT)
(sha256 TWO
(sha256 ONE bridge_amount)
(sha256_one)
)
)
(sha256 TWO
(sha256 TWO
(sha256 ONE CREATE_COIN)
(sha256 TWO
(sha256 ONE bridge_inner_puzhash)
(sha256 TWO
(sha256 ONE bridge_amount)
(sha256_one)
)
)
)
(sha256_one)
)
)
)
)
)
; final conditions
(list
; An announcement to the bridge of the delegated puzzle it should run
(list CREATE_PUZZLE_ANNOUNCEMENT
(sha256
(f (r BRIDGE_SINGLETON_STRUCT))
(assert_root_and_calculate_delegated_puzzle_hash
VALIDATION_ROOT
bridge_height
bridge_metadata_updater_hash
bridge_inner_puzhash
bridge_amount
(collapse_tree_and_note_leaf_info validations_proof () 0 bridge_height bridge_height)
)
)
)
; Asserting an announcement from the delegated puzzle the bridge is running
(list ASSERT_PUZZLE_ANNOUNCEMENT
(sha256
(calculate_singleton_puzzle_hash
BRIDGE_SINGLETON_STRUCT
NFT_STATE_LAYER_MOD_HASH
bridge_height
bridge_metadata_updater_hash
bridge_inner_puzhash
)
bridge_height
)
)
)
)