The Leo prove command runs the package using the input values in the .in file, and it generates a proof of the computation. Leo uses the zkSNARK Marlin to produce a proof of the application’s correct execution.
Another zkSNARK, Groth16, will be used to prove that records were used and created in a valid manner (e.g. that there was no double spending). This proof, along with the Marlin proof, will then be verified in another Groth16 circuit (1-layer recursion), to produce another proof. It is this last proof, that everything was done correctly, that will go on chain.
Every Leo package should produce the same proving key (as long as all the code is the same, the inputs are allowed to vary). The proving key is needed to produce the proof. The proving key can be stored once generated to prevent repeated computation.
Similar to the proving key, verifying keys should be the same if the Leo package is the same (inputs can vary). The verifying key is needed to verify a proof of the relevant Leo programme. For common Leo programmes, it makes sense to store the key rather than constantly reproduce it.