@@ -6,6 +6,7 @@ import { provableFromClass } from './types/provable-derivers.js';
66import { Poseidon , packToFields , ProvableHashable } from './crypto/poseidon.js' ;
77import { Unconstrained } from './types/unconstrained.js' ;
88import { ProvableType , WithProvable } from './types/provable-intf.js' ;
9+ import { Option } from './option.js' ;
910
1011export {
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