Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
每当大型中心化交易所崩溃时,一个常被提及的问题是:我们是否可以利用加密技术来解决这个问题。交易所可以通过创建密码学证明的方式证明其链上持有的资金足以偿付用户,而不仅仅依靠政府牌照、审计员、调查公司治理以及交易所法人背调等「法币」方案。
4 h! q7 o" @$ q7 ^! u- n
% z3 J6 {0 \( L$ h" D6 t更有野心的是,交易所可以建立一个未经储户同意无法提取储户资金的系统。我们可以尝试探索「不作恶」有职业素养的 CEX 与「无法作恶」却泄漏隐私的低效链上 DEX 之间的界限。这篇文章将深入探讨让 CEX 更加去信任的历史尝试,与其采用技术的局限性,以及一些依赖 ZK-SNARKs 等先进技术的有力手段。
% f5 ~+ r" ^, C% n* m* b- Z: @1 R  h8 a% u- l' ?7 W4 \* i
余额表和 Merkle 树:传统的可偿付证明交易所试图用密码学来证明自己没有欺骗用户的最早尝试可以追溯到很久以前。2011 年,当时最大的比特币交易所 MtGox 通过发送一笔移动 424,242 个 BTC 到预先公布地址的交易来证明他们拥有该笔资金。2013 年,大家开始讨论如何解决该问题的另一面:证明用户存款的总规模。如果你证明用户的存款等于 X (负债证明 proof of liabilities),并证明拥有 X 个代币的私钥(资产证明 proof of assets),那么就提供了可偿付证明(proof of solvency):你证明了交易所有足够的资金偿还给储户。
, p) q, I5 X! N- }. \3 D8 {8 u% o: ]  Y
提供存款证明的最简单方法是公布一个列表。每个用户都可以检查他们在列表中的余额,而且任何人都可以检查完整的列表:(i)每项余额都是非负的;(ii)总额是宣称的金额。; E6 b2 E+ S. C. i
1 d6 O0 }5 I" S, L
当然,这会破坏隐私,所以我们可以稍微改变一下该方案:发布一个  列表,并私下给用户发送 salt 值。但即使这样也会泄漏余额与其分布。为了保护隐私,我们采用了后续技术:Merkle 树技术。
4 K- j! g- U, m
8 j9 g' D$ d* n9 a! ?. d" R 1672307050728799.jpg
7 A' l9 g/ |. E( e3 K% E
: b1 E+ t  ^' h+ p+ P+ x: _2 |绿色:Charlie 的节点。蓝色:Charlie 收到用于证明的节点。黄色:根节点,向所有人公布
5 n9 `& ?) {6 T& L# U, g1 D
9 N, l# q, K3 _% R, c3 p7 X! {$ V" lMerkle 树技术会将用户余额表放进 Merkle 总和树。在 Merkle 总和树中,每个节点都是对。底层叶子节点表示各个用户的余额以及用户名的加盐哈希。在每个更高层的节点中,余额是下面两个节点余额的总和,而哈希是下面两个节点的哈希。Merkle 总和证明和 Merkle 证明一样,是一个由叶子节点到根节点路径上所有姐妹节点组成的「分支」。
* C0 k% E7 d, X" H1 T; _* i/ W- w) s( Z5 M# r& q
首先,交易所会向每个用户发送一份其余额的 Merkle 总和证明。然后,用户能够确定其余额作为总额的一部分而被正确地包含。可以在这里找到简单的示例代码。5 \% `3 h6 u- Y" L. Y
8 x  F  L8 V; V
  1. # The function for computing a parent node given two child nodes" F! H" G) H: n: {  j# L

  2. ! G! O! z' g3 ]! C3 w9 V
  3. def combine_tree_nodes(L, R):
    $ z6 ^2 _4 u" e# M) m% f. ^. K$ q
  4. 9 ~- r8 _5 H; _# O
  5. L_hash, L_balance = L/ e- X9 Y" w8 q4 G
  6. , }" \9 |: W9 K4 e
  7. R_hash, R_balance = R
    9 b3 Y: b9 L$ ~5 T

  8. ) m( L9 D( u7 L8 l2 @8 W
  9. assert L_balance >= 0 and R_balance >= 03 a) i  E6 T0 O2 h2 r
  10. ) i7 j: `& g! ]  X! S
  11. new_node_hash = hash(. ?- u6 y. b3 E5 x* p

  12. + D/ F0 r* }3 w; T) ?3 a
  13. L_hash + L_balance.to_bytes(32, 'big') +, K5 b$ i8 R3 E3 I, [! n: x1 k

  14. / c$ f. n- r5 @/ y1 o! e
  15. R_hash + R_balance.to_bytes(32, 'big')
    . z- D5 B: R2 P

  16. $ W* A0 I. d# H6 i+ q4 Y$ S& n
  17. ): s- t+ A( D3 C8 f# i1 Z
  18. ; M% {" E' W( H" i! t# h, J+ F+ ~! Z# p5 g# c
  19. return (new_node_hash, L_balance + R_balance)9 S2 F: z. W/ A% e( X+ a
  20. $ D- n! z4 m1 d# y/ E
  21. # Builds a full Merkle tree. Stored in flattened form where
    2 d9 p4 j) b1 e1 G# x9 N' N- B
  22. ; X! @2 A( D5 @2 H
  23. # node i is the parent of nodes 2i and 2i+1
    : y, D9 P  C: {& y0 O0 D. b, |
  24. / j4 |6 e; @4 ^
  25. def build_merkle_sum_tree(user_table: "List[(username, salt, balance)]"):
    ! i+ x: ~% x& H+ E
  26. 3 e; h5 `4 n# }& c" J& ^$ g
  27. tree_size = get_next_power_of_2(len(user_table))
    ) A/ y) K1 H9 e( {9 H  {

  28. + n+ T! t& s$ n  P; Z8 O
  29. tree = (1 Y4 D, O5 l% B; M$ |
  30. & v& Y$ G% l9 B; N8 i: I
  31. [None] * tree_size +" J# c) @  \" }- A: ^7 V
  32. 6 K! X8 {! y) f% {! H# [- P
  33. [userdata_to_leaf(*user) for user in user_table] +  Q, X& D! o# p  g! m8 `% x: r
  34. 2 D, a( g7 N; m7 J
  35. [EMPTY_LEAF for _ in range(tree_size - len(user_table))]  ~5 V9 E! G  `- T( a% L* a6 P7 P  p
  36. , u% f. |) r0 o% b7 o
  37. )
    ) {) \0 e+ A; n+ t
  38. 2 v3 v. [. \# A
  39. for i in range(tree_size - 1, 0, -1):
    ' Q9 i; Q2 L9 R6 {1 N
  40. . u4 N6 S+ @  N" ^# T
  41. tree = combine_tree_nodes(tree[i*2], tree[i*2+1])
    ! j" H( F: W- b% b4 _) @

  42. , i$ ~) w; F% g
  43. return tree9 ^2 S4 l2 S" n, s; \1 @& ~

  44. ; ?  X. k. w  x6 G% ^
  45. # Root of a tree is stored at index 1 in the flattened form
    * M# b9 @; z& ^' M1 V( W, B

  46. ; ^" ?- H8 e7 B  G6 s
  47. def get_root(tree):
    + v2 f& Z+ x! e2 q" ?8 ?5 L

  48. ) {4 U8 ]& E, t
  49. return tree[1]
    9 Z* a7 Z( M& D, _0 x+ R

  50. ; E5 _5 p. g# }+ @  F
  51. # Gets a proof for a node at a particular index
    ! \) ^- e5 I! }9 n1 L# s
  52. % v$ T; B6 I; l" n) _! U' t
  53. def get_proof(tree, index):
    . m3 `1 ~1 a! [& {3 A8 f- U
  54. . E* i( a3 k2 C+ ?& o0 Q& ]
  55. branch_length = log2(len(tree)) - 1
    ) c5 Z# U' q* E7 x7 R4 ]# X0 S

  56. . q2 x' E6 m4 \# s& D& @
  57. # ^ = bitwise xor, x ^ 1 = sister node of x! H3 b/ Q+ s/ o
  58. ; H1 K& d+ n/ a3 [
  59. index_in_tree = index + len(tree) // 2
    ( s5 X. [2 ~, b  Q7 p+ q
  60. , O* |( Y6 G% l! P, [% f
  61. return [tree[(index_in_tree // 2**i) ^ 1] for i in range(branch_length)]
    / \% J( g5 F9 `5 }6 m6 M3 V

  62. 3 o: a( j, n# h
  63. # Verifies a proof (duh)6 \; A7 w, d# z
  64. 7 K) \; h  v/ u* v2 G
  65. def verify_proof(username, salt, balance, index, user_table_size, root, proof):
    , N! n1 `7 `6 m  p  }/ Z

  66. ; V- p! ^  t# S3 |
  67. leaf = userdata_to_leaf(username, salt, balance)
    ) C. `* [: Y/ k. [8 G0 @# o

  68. 3 h7 c% j' Y' P2 E( b
  69. branch_length = log2(get_next_power_of_2(user_table_size)) - 1# G- M& k( t; I% a. z7 b8 I. l( M

  70. % E% R, I6 M0 J3 n
  71. for i in range(branch_length):8 f7 M. \* J/ K+ y+ x; W* S7 F

  72. . A8 [8 `# ~5 j% C0 r9 H
  73. if index & (2**i):1 w/ ^1 B) x& [; p; K3 P, v1 Z
  74. 8 ?' C% T, c. D& v4 P# g
  75. leaf = combine_tree_nodes(proof, leaf)
    + `: c" M4 O- R6 h: n/ D

  76. + D% J& M7 h2 c: N( q+ ]0 g
  77. else:+ O9 b0 e- \+ e' V& d) f

  78. 6 F7 G! v) f! b' m4 f5 P! B# s) i
  79. leaf = combine_tree_nodes(leaf, proof)# }) F  i2 Q8 F
  80. 2 X+ b1 L9 {4 n0 Z* E( D! W
  81. return leaf == root
复制代码
1 y# L" H; j) |1 F8 V! S
标签: 交易所
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

楼琴观雪让 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    5