-
![](/static/nostr-icon-purple-64x64.png)
@ john doe
2025-02-04 03:39:18
# NIP-XX: Proof of Watch
`draft` `optional`
This NIP defines a protocol for content creators to reward users for consuming content using Cashu tokens, utilizing existing Cashu P2PK capabilities.
## Abstract
Content creators can offer Cashu token rewards to users who prove they have spent time consuming their content. The protocol uses P2PK-locked tokens combined with proof-of-work verification to ensure genuine content consumption before releasing tokens to users.
## Motivation
Content creators want to incentivize users to engage with their content and potentially reward them for their attention. This NIP provides a standardized way to offer token rewards for content consumption while ensuring the user actually spent time with the content through a proof-of-work mechanism.
## Protocol Components
### Content Event
A content creator publishes a `kind:1` note containing their content and reward information:
```json
{
"kind": 1,
"content": "Watch my video!",
"tags": [
["reward", "<amount-in-sats>"],
["pow", "<difficulty>"],
["u", "<watcher-service-url>"],
["t", "proofofwatch"]
]
}
```
### Watcher Service
Content creators run (or use) a watcher service that:
1. Maintains a pool of Cashu tokens
2. Issues P2PK-locked tokens to viewers
3. Verifies proofs of watch
4. Releases signatures to unlock tokens
## Protocol Flow
### 1. Request Watch Session
Client makes a `POST /watch/start` request to watcher service:
```json
{
"note_id": "<event-id>"
}
```
Service responds with:
```json
{
"id": "<session-id>",
"challenge": "<random-challenge>",
"difficulty": <int>,
"token": {
"amount": <int>,
"id": "<keyset-id>",
"secret": "<p2pk-secret>",
"C": "<signature>"
},
"pubkey": "<service-ephemeral-pubkey>",
"expiry": <unix-timestamp>
}
```
The token is P2PK-locked to a one-time ephemeral pubkey generated by the service. Only the service holds the corresponding private key needed to generate the witness signature.
### 2. Computing Proof
While consuming content, client computes proof-of-work:
```
proof = find_nonce(
SHA256(
note_id +
session_id +
challenge +
latest_block_hash +
nonce
)
)
```
The proof must result in a hash with the required number of leading zeros.
### 3. Submitting Proof
Client submits proof to redeem token:
```http
POST /watch/prove
```
```json
{
"session_id": "<session-id>",
"proof": "<computed-proof>",
"block_hash": "<latest-block-hash>"
}
```
If valid, service responds with P2PK signature:
```json
{
"witness": {
"signatures": ["<signature-to-unlock-token>"]
}
}
```
The client can now unlock and spend their token using standard Cashu operations.
## Security Considerations
### Token Security
- Tokens are locked to service-generated ephemeral pubkeys
- Each watch session uses a unique keypair
- Only service can generate valid witness signatures
- Private keys never revealed to users
- Keys and unused tokens destroyed after session expiry
### Proof Construction
- Must include session ID to prevent replay
- Must include recent block hash to prevent precomputation
- Must achieve required difficulty (leading zeros)
- Must be completed within session expiry
### Service Requirements
1. Track used proofs
2. Enforce timeouts
3. Rate limit requests
4. Verify block hash recency
5. Maintain adequate token pool
6. Generate unique ephemeral keypairs per session
7. Securely store ephemeral private keys until proof verified
8. Clean up expired ephemeral keys
## Watcher Service Settings
Services should provide an info endpoint:
```http
GET /info
```
```json
{
"name": "Example Watcher",
"pubkey": "<service-pubkey>",
"difficulty_range": {
"min": <int>,
"max": <int>
},
"amount_range": {
"min": <int>,
"max": <int>
},
"supported_mints": [
"<mint-url-1>",
"<mint-url-2>"
]
}
```
## Client Implementation Guidelines
Clients SHOULD:
1. Verify service supports intended mint
2. Start proof computation only after beginning content consumption
3. Submit proof promptly after computation
4. Handle session expiry gracefully
5. Verify P2PK token validity
6. Submit proof before session timeout
## Content Creator Guidelines
Content creators SHOULD:
1. Set appropriate difficulty for content length
2. Maintain adequate token pool
3. Monitor service uptime
4. Consider token denomination strategies
5. Include clear reward terms
## Rate Limiting
Services SHOULD implement rate limiting:
- Per IP address
- Per pubkey
- Per note ID
- Per token amount
## Example Implementation
A basic proof computation in Python:
```python
def compute_proof(note_id, session_id, challenge, block_hash, difficulty):
nonce = 0
while True:
attempt = f"{note_id}{session_id}{challenge}{block_hash}{nonce}"
hash = sha256(attempt.encode()).hexdigest()
if hash.startswith('0' * difficulty):
return attempt
nonce += 1
```
## References
- [NUT-00](00.md): Protocol fundamentals
- [NUT-11](11.md): Pay-to-Pubkey (P2PK) tokens
- [NUT-12](12.md): DLEQ proofs