-
-
Save VitalJeevanjot/c1de8b049cf0eb608d275cb0d9bc386b to your computer and use it in GitHub Desktop.
Merkle Tree Aeternity with MIMC hash as parameter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@compiler >= 6 | |
include "List.aes" | |
contract interface MIMCSponge = | |
entrypoint hasher: list(int) => list(int) | |
contract MerkleTreeWithHistory = | |
record state = { | |
field_size: int, | |
hashing: MIMCSponge, | |
levels: int, | |
filled_subtrees: list(int), | |
roots: list(int), | |
root_history_size: int, | |
current_root_index: int, | |
next_index: int | |
} | |
stateful entrypoint init(_levels: int, _hasher: MIMCSponge) = | |
require(_levels > 0 && _levels < 32, "Levels should be in range 0-32 ('Max-Min' is not included)") | |
{ | |
field_size = 52435875175126190479447740508185965837690552500527637822603658699938581184513, | |
levels = _levels, | |
hashing = _hasher, | |
filled_subtrees = zeros(), | |
roots = [14128481056524536957498216347562587505734220138697483515041882766627531681467], | |
root_history_size = 30, | |
current_root_index = 0, | |
next_index = 0 | |
} | |
entrypoint hashLeftRight(_left: int, _right: int) : int = | |
// Instead of using Field size in int, using in bytes reduced on conversion here. | |
require(_left < state.field_size, "_left should be inside the field") | |
require(_right < state.field_size, "_right should be inside the field") | |
let outs: list(int) = state.hashing.hasher([_left, 0]) | |
let out_1 : int = (List.get(0, outs) + _right) mod state.field_size | |
List.get(0, state.hashing.hasher([out_1, List.get(1, outs)])) | |
stateful entrypoint insert(leaf: int) : int= | |
let current_index : int = state.next_index | |
require(current_index != (2 ^ state.levels), "Merkle tree is full, No more leaves can be added") | |
let current_level_hash : int = _insert_loop(List.filter((x) => x < state.levels, zeros()), current_index, leaf) | |
let new_root_index = (state.current_root_index + 1) mod state.root_history_size | |
put(state{current_root_index = new_root_index}) | |
put(state{roots @ r = r ++ [current_level_hash]}) | |
put(state{next_index = current_index + 1}) | |
current_index | |
// levels considered 20 | |
stateful function _insert_loop(zeros: list(int), current_index: int, _current_level_hash: int) : int = | |
switch(zeros) | |
[] => | |
_current_level_hash | |
(zero :: zeros) => | |
let current_level_hash = | |
if(current_index mod 2 == 0) | |
let right = zero | |
let new_list = List.replace_at(zero, _current_level_hash, state.filled_subtrees) | |
put(state{filled_subtrees = new_list}) | |
hashLeftRight(_current_level_hash, right) | |
else | |
let left = List.get(zero, state.filled_subtrees) | |
hashLeftRight(left, _current_level_hash) | |
let current_index = current_index / 2 | |
_insert_loop(zeros, current_index, current_level_hash) | |
function zeros() : list(int) = | |
[ | |
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment