Skip to content

Commit 7227f55

Browse files
committed
pop option, this is actually the most useful merkle list method
1 parent 90de4c1 commit 7227f55

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

src/lib/provable/merkle-list.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { provableFromClass } from './types/provable-derivers.js';
66
import { Poseidon, packToFields, ProvableHashable } from './crypto/poseidon.js';
77
import { Unconstrained } from './types/unconstrained.js';
88
import { ProvableType, WithProvable } from './types/provable-intf.js';
9+
import { Option } from './option.js';
910

1011
export {
1112
MerkleListBase,
@@ -166,6 +167,27 @@ class MerkleList<T> implements MerkleListBase<T> {
166167
return Provable.if(isEmpty, provable, provable.empty(), element);
167168
}
168169

170+
/**
171+
* Remove the last element from the list and return it as an option:
172+
* Some(element) if the list is non-empty, None if the list is empty.
173+
*
174+
* **Warning**: If the list is empty, the the option's .value is entirely unconstrained.
175+
*/
176+
popOption(): Option<T> {
177+
let { previousHash, element } = this.popWitness();
178+
let isEmpty = this.isEmpty();
179+
let emptyHash = this.Constructor.emptyHash;
180+
181+
let currentHash = this.nextHash(previousHash, element);
182+
currentHash = Provable.if(isEmpty, emptyHash, currentHash);
183+
this.hash.assertEquals(currentHash);
184+
185+
this.hash = Provable.if(isEmpty, emptyHash, previousHash);
186+
let provable = this.innerProvable;
187+
const OptionT = Option(provable);
188+
return new OptionT({ isSome: isEmpty.not(), value: element });
189+
}
190+
169191
/**
170192
* Return the last element, but only remove it if `condition` is true.
171193
*

0 commit comments

Comments
 (0)