diff --git a/src/router.ts b/src/router.ts index 153df62..4ef6479 100755 --- a/src/router.ts +++ b/src/router.ts @@ -568,16 +568,12 @@ export async function registerAllListeners() { try { // privateFields is only used if newData contains new fields // roles can be empty meaning that roles from the last commited state are kept - const { processId, lastStateId, newData, privateFields, roles, accessToken } = event.data; + const { processId, newData, privateFields, roles, accessToken } = event.data; if (!accessToken || await !tokenService.validateToken(accessToken, event.origin)) { throw new Error('Invalid or expired session token'); } - if (!isValid32ByteHex(lastStateId)) { - throw new Error('Invalid last state id'); - } - // Check if the new data is already in the process or if it's a new field const process = await services.getProcess(processId); if (!process) { @@ -587,36 +583,50 @@ export async function registerAllListeners() { if (!lastState) { throw new Error('Process doesn\'t have a commited state yet'); } - if (lastState.state_id !== lastStateId) { - throw new Error('Process has been updated'); - } - console.log('🚀 ~ handleUpdateProcess ~ lastState:', lastState); + const lastStateIndex = services.getLastCommitedStateIndex(process); + if (lastStateIndex === null) { + throw new Error('Process doesn\'t have a commited state yet'); + } // Shouldn't happen const privateData: Record = {}; const publicData: Record = {}; for (const field of Object.keys(newData)) { console.log('🚀 ~ handleUpdateProcess ~ newData[field]:', newData[field]); - if (lastState.pcd_commitment[field]) { - // is it a private field ? - if (lastState.public_data[field]) { - // Add it to public data - publicData[field] = newData[field]; - } else { - // Add it to private data - privateData[field] = newData[field]; - } - } else { - // is it supposed to be private ? - if (privateFields.includes(field)) { - // Add it to private data - privateData[field] = newData[field]; - } else { - // Add it to public data - publicData[field] = newData[field]; - } - // For new fields we should check that roles have been modified accordingly, otherwise the state would be impossible to commit + // Public data are carried along each new state + // So the first thing we can do is check if the new data is public data + if (lastState.public_data[field]) { + // Add it to public data + publicData[field] = newData[field]; + continue; } + + // If it's not a public data, it may be either a private data update, or a new field (public of private) + // Caller gave us a list of new private fields, if we see it here this is a new private field + if (privateFields.includes(field)) { + // Add it to private data + privateData[field] = newData[field]; + continue; + } + + // Now it can be an update of private data or a new public data + // We check that the field exists in previous states private data + for (let i = lastStateIndex; i >= 0; i--) { + const state = process.states[i]; + if (state.pcd_commitment[field]) { + // We don't even check if it's a public field, we would have seen it in the last state + privateData[field] = newData[field]; + break; + } else { + // This attribute was not modified in that state, we go back to the previous state + continue; + } + } + + if (privateData[field]) continue; + + // We've get back all the way to the first state without seeing it, it's a new public field + publicData[field] = newData[field]; } // We'll let the wasm check if roles are consistent