Skip to content

Commit-Reveal

The Commit-Reveal pattern is a fundamental blockchain pattern that enables to:

  1. Commit to a value without revealing it (commit phase)
  2. Reveal the value later to prove they knew it in advance (reveal phase)

Some use cases:

  • Blind Auctions: Bidders commit to their bids first, then reveal them after the bidding period
  • Voting Systems: Voters commit their votes early, revealing them only after voting ends
  • Knowledge Proofs/Attestations: Proving you knew information at a specific time without revealing it immediately
  • Fair Random Number Generation: Players commit to random numbers that get combined later, making it harder to manipulate the outcome

How It Works

  1. Commit Phase:

    • User generates a value (secret)
    • User creates a hash of this value
    • User submits only the hash on-chain (commit)
  2. Reveal Phase:

    • User submits the original value (reveal)
    • Contract verifies that the hash of the submitted value matches the previously committed hash
    • If it matches then it proves that the user knew the value at the commitment time

Minimal commit-reveal contract:

#[starknet::contract]
pub mod CommitmentRevealTraits {
    use starknet::storage::{StoragePointerWriteAccess, StoragePointerReadAccess};
    use core::hash::HashStateTrait;
    use core::pedersen::PedersenTrait;
 
    #[storage]
    struct Storage {
        commitment: felt252,
    }
 
    #[abi(embed_v0)]
    impl CommitmentRevealTrait of super::ICommitmentRevealTrait<ContractState> {
        fn commit(ref self: ContractState, commitment: felt252) {
            self.commitment.write(commitment);
        }
 
        fn reveal(self: @ContractState, secret: felt252) -> bool {
            let hash = PedersenTrait::new(secret).finalize();
            self.commitment.read() == hash
        }
    }
}

Usage example:

        // Off-chain, compute the commitment hash for secret
        let secret = 'My secret';
        let offchain_commitment = PedersenTrait::new(secret).finalize();
 
        // Commit on-chain
        contract.commit(offchain_commitment);
 
        // Reveal on-chain and assert the result
        let reveal_result = contract.reveal(secret);

Some considerations:

  • The commit phase must complete before any reveals can start
  • Users might choose not to reveal if the outcome is unfavorable (consider adding stake/slashing mechanics to ensure reveals)
Powered By Nethermind