> For the complete documentation index, see [llms.txt](https://noiho.gitbook.io/noiho/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://noiho.gitbook.io/noiho/architecture/order-lifecycle/commit-reveal.md).

# Fulfillment commit-reveal

Why fulfillment takes two transactions instead of one.

A Monero txid and transaction secret key are public once revealed, and anyone who sees them in the mempool could submit them first. Commit-reveal binds the proof to a fulfiller and an order in an earlier block, so a copied reveal cannot succeed.

```solidity
commitment = keccak256(abi.encode(
  keccak256("NOIHO_FULFILLMENT_V1"),
  chainId,
  diamondAddress,
  orderId,
  fulfiller,
  orderType,
  takerIntentTime,
  xmrTxid,
  xmrTxSecretKey,
  salt
));
```

1. Generate a nonzero random bytes32 salt and keep it private alongside the txid and transaction secret key.
2. Read the current order immediately before hashing — orderType and takerIntentTime are commitment inputs.
3. Call commitFulfillment(orderId, commitment) from the fulfiller address.
4. Wait until that transaction is mined and block.number is greater than fulfillmentCommitmentBlock.
5. Call fulfillWrap or fulfillUnwrap with the exact txid, canonical secret key, and salt, before the deadline.
6. To abandon before the deadline, the same fulfiller calls removeFulfillment and can then commit again.

Keep the proof inputs private until reveal. Backup formats depend on the client. See [Commitment backups](/noiho/developers/frontend-builders/commitment-backups.md).
