Skip to content

Instantly share code, notes, and snippets.

@AdamISZ
Last active April 3, 2023 20:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AdamISZ/baf93ce2589854a7992383b3c69fae13 to your computer and use it in GitHub Desktop.
Save AdamISZ/baf93ce2589854a7992383b3c69fae13 to your computer and use it in GitHub Desktop.

Username (herafter "nick") construction for message channel:

nick = one "type" byte (currently "J") + one version byte (current jm_version protocol value) + Base58 (not Base58Check) of: first joinmarket.message_channel.NICK_HASH_LEN bytes of sha256 of : ephemeral per-bot-process public key.

If length(X) < joinmarket.message_channel.NICK_MAX_ENCODED, right pad with 'O' char to that length.

Definitions:

T: taker

M: maker

* : indicates message not including NS is encrypted

[t,m]encpubkey : taker and maker encryption pubkeys, per transaction, for ECDH setup

C: single data field for commitment to a utxo by taker, by default for PoDLE (C=H(P2)). First byte is commitment type, default "P" for PoDLE.

B(p): bitcoin signature of an encryption pubkey p (signed message format standardised as for Bitcoin Core etc.)

Commitment data for default PoDLE construct:

O: commitment opening serialization, consists of the following fields separated by a field separator (default '|'):

U: utxo used for PoDLE (not necessarily from wallet)

P: pubkey used for PoDLE (not necessarily from wallet)

P2: shifted base point pubkey for PoDLE

s, e: schnorr sig values for PoDLE

maker_auth_pub: pubkey of keypair used to authorize and setup encryption by maker (must correspond to one of maker's input addresses)

coinjoinA: coinjoin address used by maker

changeA: change address used by maker

ulist: list of utxos that maker proposes to be used in transaction

(NS): nick signature (either of form pub, sig or from pubkey recovery, bitcoin type) : message to be signed is the whole message to be sent + message channel identifier str(serverport) (the latter to prevent cross-channel replay).

Private conversation sequence:

1: M: !ordertype [order details]!ordertype [orderdetails]... (NS)
2: T: !fill order-id amount tencpubkey C (NS)
3: M: !pubkey mencpubkey (NS)
4: T*: !auth O (NS)
5: M*: !ioauth ulist maker_auth_pub coinjoinA changeA B(mencpubkey) (NS)
6: T*: !tx txhex (NS)
7: M*: !sig txsig (NS)

Notes:

After step 2, if provided commitment is blacklisted according to maker's policy, maker quits. Current implementation stores utxo commitments (note that there are taker_utxo_retries possible commitments per utxo, and that the commitments do not reveal the utxo, thus effectively the same utxo can be tried that many times) in a file named blacklist.

After step 4, if PoDLE verification fails, the maker quits before sending !ioauth, thereby disallowing receipt of owned utxos.

For PODLE calculation see here

In 5, !ioauth ulist maker_auth_pub coinjoinA changeA B(mencpubkey) (NS), returned by maker, it's to be noted here that maker_auth_pub is needed to use an input , rather than an output, pubkey, as the anti-MITM key for the reason that a maker might not always own the coinjoin output key (see e.g. patientsendpayment mixing of maker/taker role).

Nick signature: currently re-calculates expected nick from given pubkey then validates signature against the entire message before NS. In future could cut out ~ 66 bytes by making use of secp256k1 pubkey recovery. The purpose of this feature is to prevent impersonation of a running bot by using its nick on a different message channel (see issue 568).

Taker side auth of utxo has been REMOVED, see overview of argument here and see also earlier background.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment