1
0

fusion.proto 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Electron Cash - a lightweight Bitcoin Cash client
  3. * CashFusion - an advanced coin anonymizer
  4. *
  5. * Copyright (C) 2020 Mark B. Lundeberg
  6. *
  7. * Permission is hereby granted, free of charge, to any person
  8. * obtaining a copy of this software and associated documentation files
  9. * (the "Software"), to deal in the Software without restriction,
  10. * including without limitation the rights to use, copy, modify, merge,
  11. * publish, distribute, sublicense, and/or sell copies of the Software,
  12. * and to permit persons to whom the Software is furnished to do so,
  13. * subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be
  16. * included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  22. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  23. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  25. * SOFTWARE.
  26. */
  27. syntax = "proto2";
  28. package fusion;
  29. // Some primitives
  30. message InputComponent {
  31. required bytes prev_txid = 1; // in 'reverse' order, just like in tx
  32. required uint32 prev_index = 2;
  33. required bytes pubkey = 3;
  34. required uint64 amount = 4;
  35. }
  36. message OutputComponent {
  37. required bytes scriptpubkey = 1;
  38. required uint64 amount = 2;
  39. }
  40. message BlankComponent {
  41. }
  42. message Component {
  43. required bytes salt_commitment = 1; // 32 bytes
  44. oneof component {
  45. InputComponent input = 2;
  46. OutputComponent output = 3;
  47. BlankComponent blank = 4;
  48. }
  49. }
  50. message InitialCommitment {
  51. required bytes salted_component_hash = 1; // 32 byte hash
  52. required bytes amount_commitment = 2; // uncompressed point
  53. required bytes communication_key = 3; // compressed point
  54. }
  55. message Proof {
  56. // During blame phase, messages of this form are encrypted and sent
  57. // to a different player. It is already known which commitment this
  58. // should apply to, so we only need to point at the component.
  59. required fixed32 component_idx = 1;
  60. required bytes salt = 2; // 32 bytes
  61. required bytes pedersen_nonce = 3; // 32 bytes
  62. }
  63. // Primary communication message types (and flow)
  64. // Setup phase
  65. message ClientHello { // from client
  66. required bytes version = 1;
  67. optional bytes genesis_hash = 2; // 32 byte hash (bitcoind little-endian memory order)
  68. }
  69. message ServerHello { // from server
  70. repeated uint64 tiers = 1;
  71. required uint32 num_components = 2;
  72. required uint64 component_feerate = 4; // sats/kB
  73. required uint64 min_excess_fee = 5; // sats
  74. required uint64 max_excess_fee = 6; // sats
  75. optional string donation_address = 15; // BCH Address "bitcoincash:qpx..."
  76. }
  77. message JoinPools { // from client
  78. message PoolTag {
  79. // These tags can be used to client to stop the server from including
  80. // the client too many times in the same fusion. Thus, the client can
  81. // connect many times without fear of fusing with themselves.
  82. required bytes id = 1; // allowed up to 20 bytes
  83. required uint32 limit = 2; // between 1 and 5 inclusive
  84. optional bool no_ip = 3; // whether to do an IP-less tag -- this will collide with all other users, make sure it's random so you can't get DoSed.
  85. }
  86. repeated uint64 tiers = 1;
  87. repeated PoolTag tags = 2; // at most five tags.
  88. }
  89. message TierStatusUpdate { // from server
  90. message TierStatus {
  91. // in future, we will want server to indicate 'remaining time' and mask number of players.
  92. // note: if player is in queue then a status will be ommitted.
  93. optional uint32 players = 1;
  94. optional uint32 min_players = 2; // minimum required to start (may have delay to allow extra)
  95. optional uint32 max_players = 3; // maximum allowed (immediate start)
  96. optional uint32 time_remaining = 4;
  97. }
  98. map<uint64, TierStatus> statuses = 1;
  99. }
  100. message FusionBegin { // from server
  101. required uint64 tier = 1;
  102. required bytes covert_domain = 2;
  103. required uint32 covert_port = 3;
  104. optional bool covert_ssl = 4;
  105. required fixed64 server_time = 5; // server unix time when sending this message; can't be too far off from recipient's clock.
  106. }
  107. // Fusion round (repeatable multiple times per connection)
  108. message StartRound { // from server
  109. required bytes round_pubkey = 1;
  110. repeated bytes blind_nonce_points = 2;
  111. required fixed64 server_time = 5; // server unix time when sending this message; can't be too far off from recipient's clock.
  112. }
  113. // Phase 3
  114. message PlayerCommit { // from client
  115. repeated bytes initial_commitments = 1; // serialized InitialCommitment messages; server will repeat them later, verbatim.
  116. required uint64 excess_fee = 2;
  117. required bytes pedersen_total_nonce = 3; // 32 bytes
  118. required bytes random_number_commitment = 4; // 32 bytes
  119. repeated bytes blind_sig_requests = 5; // 32 byte scalars
  120. }
  121. // Phase 4
  122. message BlindSigResponses { // from server
  123. repeated bytes scalars = 1; // 32 byte scalars
  124. }
  125. message AllCommitments {
  126. // All the commitments from all players. At ~140 bytes per commitment and hundreds of commitments, this can be quite large, so it gets sent in its own message during the covert phase.
  127. repeated bytes initial_commitments = 1;
  128. }
  129. //Phase 5
  130. message CovertComponent { // from covert client
  131. // The round key is used to identify the pool if needed
  132. optional bytes round_pubkey = 1;
  133. required bytes signature = 2;
  134. required bytes component = 3; // bytes so that it can be signed and hashed verbatim
  135. }
  136. //Phase 6
  137. message ShareCovertComponents { // from server
  138. // This is a large message! 168 bytes per initial commitment, ~112 bytes per input component.
  139. // Can easily reach 100 kB or more.
  140. repeated bytes components = 4;
  141. optional bool skip_signatures = 5; // if the server already sees a problem in submitted components
  142. optional bytes session_hash = 6; // the server's calculation of session hash, so clients can crosscheck.
  143. }
  144. // Phase 7A
  145. message CovertTransactionSignature { // from covert client
  146. // The round key is used to identify the pool if needed
  147. optional bytes round_pubkey = 1;
  148. required uint32 which_input = 2;
  149. required bytes txsignature = 3;
  150. }
  151. // Phase 8
  152. message FusionResult { // from server
  153. required bool ok = 1;
  154. repeated bytes txsignatures = 2; // if ok
  155. repeated uint32 bad_components = 3; // if not ok
  156. }
  157. // Phase 9
  158. message MyProofsList { // from client
  159. repeated bytes encrypted_proofs = 1;
  160. required bytes random_number = 2; // the number we committed to, back in phase 3
  161. }
  162. message TheirProofsList { // from server
  163. message RelayedProof {
  164. required bytes encrypted_proof = 1;
  165. required uint32 src_commitment_idx = 2; // which of the commitments is being proven (index in full list)
  166. required uint32 dst_key_idx = 3; // which of the recipient's keys will unlock the encryption (index in player list)
  167. }
  168. repeated RelayedProof proofs = 1;
  169. }
  170. // Phase 10
  171. message Blames { // from client
  172. message BlameProof {
  173. required uint32 which_proof = 1;
  174. oneof decrypter {
  175. bytes session_key = 2; // 32 byte, preferred if the proof decryption works at all
  176. bytes privkey = 3; // 32 byte scalar
  177. }
  178. // Some errors can only be discovered by checking the blockchain,
  179. // Namely, if an input UTXO is missing/spent/unconfirmed/different
  180. // scriptpubkey/different amount, than indicated.
  181. optional bool need_lookup_blockchain = 4;
  182. // The client can indicate why it thinks the blame is deserved. In
  183. // case the server finds no issue, this string might help for debugging.
  184. optional string blame_reason = 5;
  185. }
  186. repeated BlameProof blames = 1;
  187. }
  188. // Final message of the round
  189. message RestartRound {
  190. }
  191. // Fatal error from server, likely we did something wrong (it will disconnect us, but the message may help debugging).
  192. message Error {
  193. optional string message = 1;
  194. }
  195. // Simple ping, as a keepalive.
  196. message Ping {
  197. }
  198. // Simple acknowledgement, nothing more to say.
  199. message OK {
  200. }
  201. // Primary communication channel types
  202. message ClientMessage {
  203. oneof msg {
  204. ClientHello clienthello = 1;
  205. JoinPools joinpools = 2;
  206. PlayerCommit playercommit = 3;
  207. MyProofsList myproofslist = 5;
  208. Blames blames = 6;
  209. }
  210. }
  211. message ServerMessage {
  212. oneof msg {
  213. ServerHello serverhello = 1;
  214. TierStatusUpdate tierstatusupdate = 2;
  215. FusionBegin fusionbegin = 3;
  216. StartRound startround = 4;
  217. BlindSigResponses blindsigresponses = 5;
  218. AllCommitments allcommitments = 6;
  219. ShareCovertComponents sharecovertcomponents = 7;
  220. FusionResult fusionresult = 8;
  221. TheirProofsList theirproofslist = 9;
  222. RestartRound restartround = 14;
  223. Error error = 15;
  224. }
  225. }
  226. message CovertMessage { // client -> server, covertly
  227. oneof msg {
  228. CovertComponent component = 1;
  229. CovertTransactionSignature signature = 2;
  230. Ping ping = 3;
  231. }
  232. }
  233. message CovertResponse { // server -> a covert client
  234. oneof msg {
  235. OK ok = 1;
  236. Error error = 15;
  237. }
  238. }