@@ -22,6 +22,114 @@ const keyDb =
2222 process . env . KEY_DB_PATH || '/app/orchestration/common/db/key.json' ;
2323
2424const PRINTABLE_ASCII_REGEX = / ^ [ \x20 - \x7E ] * $ / ;
25+ const NULLIFIER_EVENTS_COLLECTION = `${ COMMITMENTS_COLLECTION } _nullifiers` ;
26+
27+ async function getCommitmentsDb ( ) {
28+ const connection = await mongo . connection ( MONGO_URL ) ;
29+ return connection . db ( COMMITMENTS_DB ) ;
30+ }
31+
32+ async function getCommitmentsCollection ( ) {
33+ const db = await getCommitmentsDb ( ) ;
34+ return db . collection ( COMMITMENTS_COLLECTION ) ;
35+ }
36+
37+ async function getNullifierEventsCollection ( ) {
38+ const db = await getCommitmentsDb ( ) ;
39+ return db . collection ( NULLIFIER_EVENTS_COLLECTION ) ;
40+ }
41+
42+ function normaliseNullifier ( nullifier ) {
43+ const normalised = generalise ( nullifier ) ;
44+ return {
45+ hex : normalised . hex ( 32 ) ,
46+ integer : normalised . bigInt . toString ( ) ,
47+ } ;
48+ }
49+
50+ function normaliseNullifiers ( nullifiers ) {
51+ const uniqueNullifiers = new Map ( ) ;
52+ for ( const nullifier of nullifiers ) {
53+ if ( nullifier === null || nullifier === undefined || nullifier === '' )
54+ continue ; // eslint-disable-line no-continue
55+ const normalised = normaliseNullifier ( nullifier ) ;
56+ if ( BigInt ( normalised . integer ) === 0n ) continue ; // eslint-disable-line no-continue
57+ uniqueNullifiers . set ( normalised . hex , normalised ) ;
58+ }
59+ return Array . from ( uniqueNullifiers . values ( ) ) ;
60+ }
61+
62+ async function hasSeenNullifier ( nullifier ) {
63+ if ( ! nullifier ) return false ;
64+ const nullifierEventsCollection = await getNullifierEventsCollection ( ) ;
65+ const normalised = normaliseNullifier ( nullifier ) ;
66+ const knownNullifier = await nullifierEventsCollection . findOne ( {
67+ _id : normalised . hex ,
68+ } ) ;
69+ return ! ! knownNullifier ;
70+ }
71+
72+ export async function recordNullifiers ( nullifiers , metadata = { } ) {
73+ const normalisedNullifiers = normaliseNullifiers ( nullifiers ) ;
74+ if ( normalisedNullifiers . length === 0 ) {
75+ return {
76+ nullifierCount : 0 ,
77+ modifiedCount : 0 ,
78+ } ;
79+ }
80+
81+ const nullifierEventsCollection = await getNullifierEventsCollection ( ) ;
82+ const commitmentsCollection = await getCommitmentsCollection ( ) ;
83+ const now = new Date ( ) ;
84+ const blockNumber =
85+ metadata . blockNumber === undefined || metadata . blockNumber === null
86+ ? null
87+ : Number ( metadata . blockNumber ) ;
88+ const transactionHash = metadata . transactionHash ?? null ;
89+
90+ await nullifierEventsCollection . bulkWrite (
91+ normalisedNullifiers . map ( nullifier => ( {
92+ updateOne : {
93+ filter : { _id : nullifier . hex } ,
94+ update : {
95+ $set : {
96+ nullifier : nullifier . hex ,
97+ integer : nullifier . integer ,
98+ blockNumber,
99+ transactionHash,
100+ updatedAt : now ,
101+ } ,
102+ $setOnInsert : {
103+ createdAt : now ,
104+ } ,
105+ } ,
106+ upsert : true ,
107+ } ,
108+ } ) ) ,
109+ { ordered : false } ,
110+ ) ;
111+
112+ const nullifierValues = normalisedNullifiers . flatMap ( nullifier => [
113+ nullifier . hex ,
114+ nullifier . integer ,
115+ ] ) ;
116+ const updateResult = await commitmentsCollection . updateMany (
117+ {
118+ isNullified : false ,
119+ nullifier : { $in : nullifierValues } ,
120+ } ,
121+ {
122+ $set : {
123+ isNullified : true ,
124+ } ,
125+ } ,
126+ ) ;
127+
128+ return {
129+ nullifierCount : normalisedNullifiers . length ,
130+ modifiedCount : updateResult . modifiedCount || 0 ,
131+ } ;
132+ }
25133
26134const formatPreimageValue = ( rawValue , typeName = null ) => {
27135 const generalisedValue = generalise ( rawValue ) ;
@@ -102,9 +210,15 @@ export function formatCommitment(commitment) {
102210}
103211
104212export async function persistCommitment ( data ) {
105- const connection = await mongo . connection ( MONGO_URL )
106- const db = connection . db ( COMMITMENTS_DB )
107- return db . collection ( COMMITMENTS_COLLECTION ) . insertOne ( data )
213+ const connection = await mongo . connection ( MONGO_URL ) ;
214+ const db = connection . db ( COMMITMENTS_DB ) ;
215+ const commitmentData = { ...data } ;
216+ if ( commitmentData ?. nullifier && ! commitmentData . isNullified ) {
217+ commitmentData . isNullified = await hasSeenNullifier (
218+ commitmentData . nullifier ,
219+ ) ;
220+ }
221+ return db . collection ( COMMITMENTS_COLLECTION ) . insertOne ( commitmentData ) ;
108222}
109223// function to format a commitment for a mongo db and store it
110224export async function storeCommitment ( commitment ) {
@@ -114,20 +228,17 @@ export async function storeCommitment (commitment) {
114228
115229// function to retrieve commitment with a specified stateVarId
116230export async function getCommitmentsById ( id ) {
117- const connection = await mongo . connection ( MONGO_URL ) ;
118- const db = connection . db ( COMMITMENTS_DB ) ;
119- const commitments = await db
120- . collection ( COMMITMENTS_COLLECTION )
231+ const commitmentsCollection = await getCommitmentsCollection ( ) ;
232+ const commitments = await commitmentsCollection
121233 . find ( { 'preimage.stateVarId' : generalise ( id ) . hex ( 32 ) } )
122234 . toArray ( ) ;
123235 return commitments ;
124236}
125237
126238// function to retrieve commitment with a specified stateVarId
127239export async function getCurrentWholeCommitment ( id ) {
128- const connection = await mongo . connection ( MONGO_URL ) ;
129- const db = connection . db ( COMMITMENTS_DB ) ;
130- const commitment = await db . collection ( COMMITMENTS_COLLECTION ) . findOne ( {
240+ const commitmentsCollection = await getCommitmentsCollection ( ) ;
241+ const commitment = await commitmentsCollection . findOne ( {
131242 'preimage.stateVarId' : generalise ( id ) . hex ( 32 ) ,
132243 isNullified : false ,
133244 } ) ;
@@ -136,12 +247,10 @@ export async function getCurrentWholeCommitment(id) {
136247
137248// function to retrieve commitment with a specified stateName
138249export async function getCommitmentsByState ( name , mappingKey = null ) {
139- const connection = await mongo . connection ( MONGO_URL ) ;
140- const db = connection . db ( COMMITMENTS_DB ) ;
250+ const commitmentsCollection = await getCommitmentsCollection ( ) ;
141251 const query = { name : name } ;
142252 if ( mappingKey ) query [ 'mappingKey' ] = generalise ( mappingKey ) . integer ;
143- const commitments = await db
144- . collection ( COMMITMENTS_COLLECTION )
253+ const commitments = await commitmentsCollection
145254 . find ( query )
146255 . toArray ( ) ;
147256 return commitments ;
@@ -161,10 +270,8 @@ export async function deleteCommitmentsByState(name, mappingKey = null) {
161270
162271// function to retrieve all known nullified commitments
163272export async function getNullifiedCommitments ( ) {
164- const connection = await mongo . connection ( MONGO_URL ) ;
165- const db = connection . db ( COMMITMENTS_DB ) ;
166- const commitments = await db
167- . collection ( COMMITMENTS_COLLECTION )
273+ const commitmentsCollection = await getCommitmentsCollection ( ) ;
274+ const commitments = await commitmentsCollection
168275 . find ( { isNullified : true } )
169276 . toArray ( ) ;
170277 return commitments ;
@@ -174,10 +281,8 @@ export async function getNullifiedCommitments() {
174281 * @returns {Promise<number> } The sum of the values of all non-nullified commitments
175282 */
176283export async function getBalance ( ) {
177- const connection = await mongo . connection ( MONGO_URL ) ;
178- const db = connection . db ( COMMITMENTS_DB ) ;
179- const commitments = await db
180- . collection ( COMMITMENTS_COLLECTION )
284+ const commitmentsCollection = await getCommitmentsCollection ( ) ;
285+ const commitments = await commitmentsCollection
181286 . find ( { isNullified : false } ) // no nullified
182287 . toArray ( ) ;
183288
@@ -189,12 +294,10 @@ export async function getBalance() {
189294}
190295
191296export async function getBalanceByState ( name , mappingKey = null ) {
192- const connection = await mongo . connection ( MONGO_URL ) ;
193- const db = connection . db ( COMMITMENTS_DB ) ;
297+ const commitmentsCollection = await getCommitmentsCollection ( ) ;
194298 const query = { name : name } ;
195299 if ( mappingKey ) query [ 'mappingKey' ] = generalise ( mappingKey ) . integer ;
196- const commitments = await db
197- . collection ( COMMITMENTS_COLLECTION )
300+ const commitments = await commitmentsCollection
198301 . find ( query )
199302 . toArray ( ) ;
200303 let sumOfValues = 0 ;
@@ -210,10 +313,8 @@ export async function getBalanceByState(name, mappingKey = null) {
210313 * @returns all the commitments existent in this database.
211314 */
212315export async function getAllCommitments ( ) {
213- const connection = await mongo . connection ( MONGO_URL ) ;
214- const db = connection . db ( COMMITMENTS_DB ) ;
215- const allCommitments = await db
216- . collection ( COMMITMENTS_COLLECTION )
316+ const commitmentsCollection = await getCommitmentsCollection ( ) ;
317+ const allCommitments = await commitmentsCollection
217318 . find ( )
218319 . toArray ( ) ;
219320 return allCommitments ;
0 commit comments