Chameleon Mining
How it hidesStart mining

The work

A job is a CREATE2 deployment: a deployer and the hash of the contract's init code. The miner tries salts:

salt    = miner address (20 bytes) | day (uint32, big-endian) | counter (uint64, big-endian)
address = keccak256(0xff | deployer | salt | initCodeHash)[12:]

A share is a counter whose address starts with at least d zero bits. It weighs 2^(d - 28). Each hash has the same expected weight whatever d you pick (a share at d takes about 2^d hashes), so a fast GPU and a phone are paid for the hashes they do, and the difficulty only sets how often they report.

Checking a share

One keccak: rebuild the salt from the miner, the day and the counter, hash the CREATE2 preimage, count the zero bits. The server does this when a batch arrives and again for every share when the epoch closes. Because the miner's address is the first 20 bytes of the salt, a share found by one address is worth nothing to another, and the day inside the salt keeps it from counting twice.

The GPU kernel

keccak-f[1600] in WGSL, 64-bit lanes as pairs of 32-bit words, one hash per invocation, 256 invocations per workgroup. The page writes the 136-byte block once per batch; each invocation only ORs its counter into lanes 5 and 6. The same rounds are generated in JavaScript for the CPU fallback, and both are checked against viem's keccak256.

Public ledger

curl -s https://www.chameleonmining.app/api/mine/job
curl -s https://www.chameleonmining.app/api/epoch/today
curl -s https://www.chameleonmining.app/api/epoch/<day>        # closed: weights, amounts, proofs, root

Every accepted batch is stored as an open JSON file, so anyone can recount an epoch.