SOME CATS is a scheme to send 16-byte transaction memos in 2-out transactions using Carrot. SOME CATS memos are:
- Encrypted - Memos are encrypted to the receiver, optionally visible to the sender as well
- Indistinguishable - Transactions containing a SOME CATS memo are indistinguishable from normal Carrot transactions
- Available on-chain - The memo will always be available on-chain as long as its associated transaction is
- Receiver agnostic - The receiver doesn't need to support SOME CATS to spend funds sent in a SOME CATS transaction, so long as they support the Carrot addressing protocol
See the Carrot notation section.
We also introduce two functions: cipher(k, p) and decipher(k, c) which perform symmetric block cipher operations on 16-byte (128-bit) blocks. One implementation we could use in practice is Twofish. They have the relationship:
decipher(k, cipher(k, p)) = p
cipher(k, decipher(k, c)) = c
Given 16-byte message m and receiver address (Ksj, Kvj):
- If the sender wants to remember the memo, she sets
anchorrecv = SecretDerive("somecats sender-view memo anchor" || svb || input_context), otherwise she setsanchorrecv = RandBytes(16) - Sender derives the memo cipher secret
smemo = SecretDerive("somecats cipher secret" || anchorrecv || input_context || Ksj || Kvj || pid) - Sender sets
mc = cipher(smemo, m) - Sender constructs external enote to the receiver
E1withanchor = anchorrecv, instead of the regularanchor = RandBytes(16) - Sender constructs internal selfsend enote
E2withanchorenc = mc, skipping regular anchor encryption - Sender constructs transaction containing enotes
E1andE2
- During the enote scan process, while checking against Janus attacks, the receiver will decrypt
anchor - Receiver derives the memo cipher secret
smemo = SecretDerive("somecats cipher secret" || anchor || input_context || Ksj || Kvj || pid) - Receiver deciphers the memo
m = decipher(smemo, anchorencother), whereanchorencotheris the encrypted anchor on the other enote
If the sender chose to derive anchor deterministically, then they can obtain anchor = SecretDerive("somecats sender-view memo anchor" || svb || input_context), replacing step 1.