Skip to content

Instantly share code, notes, and snippets.

@VitalJeevanjot
Last active June 20, 2022 07:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VitalJeevanjot/c1de8b049cf0eb608d275cb0d9bc386b to your computer and use it in GitHub Desktop.
Save VitalJeevanjot/c1de8b049cf0eb608d275cb0d9bc386b to your computer and use it in GitHub Desktop.
Merkle Tree Aeternity with MIMC hash as parameter
@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