# In-browser proving trick: Running proof generation in the background while user is interacting with the UI For Storyform, I want to run the membership proof generation in the background (using the Web worker API) while the user fills in their answer, reducing the perceived proving time. (even zero if the proof generation is done before the user completes the survey) One process required in generating membership proof is to “bind” the *signal* to the membership proof. (*signal* being the survey response in Storyform) An obvious way to do this is to include the signal in the construction of $m$. ($m$ is the message that is signed to generate the membership proof) - $m$ = Poseidon(userPrivateInput, signal) But for example in Storyform, if the membership proof requires the user’s answers as an input, we have to wait until the user fills in all their answers to start generating the membership proof. So an alternative membership proof generation process that doesn’t require the signal will be ideal. (i.e. a membership proof scheme that can utilize the trick: just do the proof generation in the background while the user is busy doing something) In conclusion, this alternative membership proof scheme will require 2 separate proofs. A membership proof and an attestation proof. Firstly, the membership proof includes the following equality check - $m$ = Poseidon(userPrivateInput, appId), where - userPrivateInput : private input - appId: public input And also outputs $mHashed$, that is: - mHashed = Poseidon($m$) $m$ is hashed because it shouldn’t be revealed appId is there to prevent replay attacks, but including more deterministic public inputs might be better for robust replay prevention. And the attestation proof will check - mHashed = Poseidon(Poseidon(userPrivateInput, appId)), where - userPrivateInput: private input - mHashed: public input - appId: public input And also takes the hash of the signal (the survey answers in the case of Storyform) as the public input to the circuit, and outputs $signalSquared$, that is: - signalSquared = signal * signal (the squaring is to prevent tampering, [as done in Semaphore](https://semaphore.appliedzkp.org/docs/technical-reference/circuits#signal)) Finally, the mHashes from both the membership and attestation proofs will be checked for their equality. This way, the only person who knows userPrivateInput can create an attestation proof of a particular signal. The idea is to bind two proofs by a secret value (userPrivateInput). The two proofs being, - one to prove knowledge of a signature and its public key’s membership, - and another proof to *attest* to a particular signal.