Try   HackMD

Private bridging

Plaintext bridge (relay) flow (Outdated)

Here, I am unwrapping more the logic without privacy as digested from IBC relayers for my own understanding of the workflow.

  1. Blockchain A with tokens a,b,c
  2. Blockchain B with tokens d,e,f
  3. User U from blockchain A with N tokens of type a wants to exhange n a's for m d's within a transaction object,
    td
    .
  4. A sends a message to B
  5. B opens the message and sends back an ack
  6. A burns n tokens and sends a proof(what is that proof?) that those tokens have been actually burnt. Certificate of transaction is sent.
  7. B validates the proof and creates a voucher which authorizes the creation of m d's to bc B and are equivalent to n d's of bc A.

Q:How those messages are sent actually since those are two different blockchains with different Consensus and state machines rules ? Who is transporting the packages/messages?

A: The relayers are responisble to act as the transporters of packages messages between A and B. Those relayers are light-clients who perform validations and orchestrate the networking between A and B. They are not full nodes in the sense that they do not need to download the entire state but they can still validate/verify

A has each own light-client LC-A and B has each own LC-B
All LCs constitute the relayer/bridge logic

Seems like those relayers are centralized components who hold logic for cross chain transactions.

IBC world: client, connections, channels, ports, and packets:

Chain A <> LC-A<->LC-B<>Chain B
Client

​​​​      create_client(type b on chain A and type a on chain B)
​​​​      update_client
​​​​      https://github.com/informalsystems/hermes-ibc-workshop/blob/main/docs/clients.md

Bridges (Functionality goal: Transfer tokens from bc A to bc B, with privacy)

  1. Blockchain A with tokens a,b,c
  2. Blockchain B with tokens d,e,f
  3. User U from blockchain A with N tokens of type a wants to exhange n a's for m d's within a transaction object,
    td
    . That is:
  4. Blockchain A keeps balance sheet for total amount (total outstanding balance) of transactions that happen from A to B for all tokens of A: a,b,c. Lets call those balance sheets BSa, BSb and BSc. Those BS's are encrypted with the public key of the blockchain(Q:since anyone can encrypt and send encrypted balances, how the system preserves malicious entities be it users, or the blockchain itself just sending incorrect balances from transactions that do not exist?)
  5. U encrypts transaction data: token type:tt ,token amount: ta with the public key of the blockchain A pkA:
    EpkA(td)=Ctd
    . The bridge module in blockchain A, updates the state of BSa with
    Ctd
    in a private way such that the BS keeps the correct encrypted amount.
  6. U publishes note commitment to blockchain A that includes (d, amount, recipientAddress) marked as to-be-sent (cross-chain transaction) to blockchain B, and U provides a proof that amount == ta from the encrypted amount in the previous step.
  7. Blockchain B is informed by the relayer (who copies the note commitment and light client proofs) that the transaction on Blockchain A happened (blockchain B can check the light client proofs) and now that user needs to mint in total m tokens of type c.(Q: where the information that user U owns those c tokens is recorded? in bridge A, bridge B or both?)

On the way back, if U sends token d back to blockchain A, where token d on blockchain B corresponds to token a on blockchain A, blockchain A, when it receives a new note commitment from blockchain B over the bridge which contains a tokens, will decrement the BSa encrypted counter and check that it is non-negative (thus preventing blockchain B from sending more token a back than it was originally sent by blockchain A).


Private Counters

MPC Approach:

  1. Each user additively secret shares the value
    tv
    inside a
    txcross
    transaction with validators responsible to act as watchdogs for the counter.
  2. For
    i=0..n2
    , where
    n=
    #validators, U picks random numbers
    ri
    and distributes one
    ri
    to each validator
    vi
    . Finally it computes
    rn1=tvi=0n2ri
    and distributes it to the last validator
    vn1

    Observe that the sum of all shares
    ri,0in1
    equals the total value
    tv
    . There is full threshold security here: All validators need to collude to reveal
    tv
    .
  3. Correctness of shares: We assume at the first version that secret shares are computed correctly (does that sound very powerful assumption? If user U secret shares gibberish data what can go wrong?Is that captured at a later stage? Can we force user to produce proofs that secret share equal the
    tv
    that has been part of the commitment? We need a protocol as follows: User(prover) secret shares
    ri,0in1
    sum to
    tv
    without revealing
    tv
    and
    tv
    is input to a note where a commitment has been put on the MT. )
  4. For additive properties (accumulating the total balance) additive secret sharing over a group is fine but for comparison we need to transform additive shares to boolean (edaBits/daBits: https://eprint.iacr.org/2021/119.pdf, https://mkskeller.github.io/files/programming.pdf). The general idea is: to check whether
    x<y
    we check whether
    xy<0
    . If subtraction result is negative it is equivalent to
    x<y
    otherwise when
    x>y
    the subtraction is a positive number. It suffices to check only the sign of the subtraction which can be done by extracting the MSB of
    xy
    and check in two complement's notation.
  5. Having additively secret shares of two numbers in
    ZN:[x]ZN
    and
    [y]ZN
    perform:
    • perform subtraction and publish
      [z]=[xy]
    • run
      bitDecompose
      to
      [z]
      such that
      z
      is been shared with boolean shares in
      Z2
    • run
      MSBExtract([z]Z2)
      )

Plaintext example:

Assume we are in a

4 digits register computer for simplicity and
a=0010(2)
and
b=0100(4)
.
b[i]
denotes the ith bit of
b
starting rightmost from position
0
, i.e:
b[0]=1,b[1]=0
, etc. We want to compute the function:

f<(a,b)={0if a>=b 1otherwise

In their bit decomposition thinking in big-endian machines(most significant bit is leftmost) we are looking to extract the the first leftmost bit where two numbers first differ. Obviously whichever's number bit is 0 at that position is less than the other one. So the task of comparing two numbers in their bit decomposition is reduced into:

  1. finding the first position
    p
    where the numbers start to differ starting from the most significant part (leftmost part)
  2. Extract from both numbers their bit at position
    p
  3. if
    b[p]==0
    then
    a<b

In bitwise arithmetics the above algorithm is translated as follows:

  1. Compute bitwise XOR of
    a
    and
    b
    and store it to
    c
    . That will result in a bit vector where at
    0
    positions
    a
    and
    b
    are equal and at
    1
    positions they differ.
  2. Compute the OR of each bit of
    c
    starting from the leftmost bit and store it to
    d
    .
    d[l1]=c[l1],d[l2]=d[l1]c[l2]
    ,
    That results in a bit vector of
    0
    's followed with
    1
    's starting at the position where
    a
    and
    b
    started to differ from leftmost.
  3. Perform component wise subtraction at vector
    d
    starting leftmost as in the previous step and store it in
    e
    . That will result in a bit vector with only a single
    1
    at the position where
    a
    and
    b
    started to differ from leftmost.
  4. Sum all individual bits of the value
    b
    with
    e
    .
    e
    is a one bit vector so that operation extracts the bit value of
    b
    in that positions where
    e[i]=1
  5. Finally
    be={0if a>=b 1if a<b

Running example

f<(a=2,b=4):

position 3 2 1 0
a
0 0 1 0
b
0 1 0 0

First step:

a
xor
b
3 2 1 0
c
0 1 1 0

Second step:

or
c
3 2 1 0
d
0 1 1 1

Third step:

subtruct d 3 2 1 0
e
0 1 0 0

Fourth step:

be
3 2 1 0
f
0 1 0 0

Fifth step:

r=f[i]=1 so output 1, meaning
a<b
, which is true:
2<4

Multiplicative shares

  • OR and AND gates require multiplication circuit which cannot be computed separately by the existing additive shares parties hold.

  • E.g: Two computing parties

    A and
    B
    and two users
    U1
    and
    U2
    with two values
    v1=5,v2=4
    , respectively.
    U1
    secret shares
    v1
    with
    A
    and
    B
    giving
    A
    [v1]A=3
    and to
    B
    [v1]B=2
    .
    U2
    respectively secret shares
    v2
    giving
    A
    [v2]A=1
    and to
    B
    :
    [v2]B=3
    Notice that without colluding
    A
    and
    B
    know nothing about the values
    v1
    and
    v2
    .
    A
    and
    B
    can do any computation requires addition/subtraction locally: meaning without the need of extra secret from additional parties or extra communication:
    v1+v2=[v1]A+[v1]B+[v2]A+[v2]B

  • A computes

    [v1]A+[v2]A and reveals it,
    B
    accordingly computes
    [v1]B+[v2]B
    and reveals it and now anyone can compute
    v1+v2
    .

  • multiplition only from additive shares does not work:

    ([v1]A+[v1]B)([v2]A+[v2]B)=[v1]A[v2]A+[v1]A[v2]B+[v1]B[v2]A+[v1]B[v2]B
    Setting :
    q1=[v1]A[v2]A

    q2=[v1]A[[v2]B

    q3=[v1]B[v2]A

    q4=[v1]B[v2]B

q1 and
q4
can be computed locally by
A
and
B
respectively but
q2
and
q3
not because parties hold additive shares and sharing any of the shares from A to B and vice versa is not allowed as it will reveal parties' values in cleartext.

Here is beaver trick:

  • Imagine an imaginary party choosing uniformly at random
    a,b
    and
    c
    such that
    ab=c
    and additively secret shares all values
    [a],[b]
    and
    [c]
    with
    A
    and
    B
    .
  • A and B compute locally:
    d=[v1][a]
    and
    e=[v2][b]
    and reveal
    e
    and
    d
    which are perfectly hiding
    v1
    and
    v2
    .
  • Both compute:

d[v2]+e[v1]+[c]ed=(v1a)[v2]+(v2b)[v1]+[c](v1a)(v2b)=[v1v2][a][v2]+[v1v2][b][v1]+[a][b][v1v2]+[b][v1]+[a][v2][a][b]=[v1v2]

Full protocol with passive security and honest users

Architecture

  • A lot of users:
    U
    's wishing to perform cross chain transactions from A to B blockchains.
  • Some validators being deployed by anoma, running anoma software:
    V
    .
  • A smart contract controlled by the target blockchain B:
    SC
  • A subset of validators called MPC computing parties (
    CP
    's) responsible for the bridging protocol act as MPC computing parties receiving the secret shared data inputs by the user.
  • A locking account on issue blockchain A acting as a vault:
    Vault

Phases

  • Issue():
  • Redeem():

Asssumptions

  • A trusted dealer distributing correlated randomness and not communicating with CPs during online phase (when data are secret shared among CPs which also hold the correlated randomness)
  • Fixed set of
    n
    CP's which are available at the beginning of a computation period. We assume parties are fixed within a computation period and

Description

Building Blocks

  • [x]SShare(
    x
    ,n): holding private data input
    x
    . Run my the user U hTakes as input the integer number
    x
    than needs to be protected and the number of CP's n and returns secret shares of
    x
    ,
    [x]
    , such that
    i=0n1[xi]M=x
    .
    For
    i=0..n2
    , where
    n=
    #CP, U picks random numbers
    ri
    and distributes one
    ri
    to each CP
    vi
    . Finally it computes
    rn1=xi=0n2ri
    and distributes it to the last CP
    vn1

  • [x+y]MSAdd(
    [x]M,[y]M
    ): Non interactive protocol where CP's locally add their share for
    [x]
    and
    [y]
    and every one publishes
    [x+y]
    . Finally an aggregator add all shares and reveals
    x+y
    .

  • [xy]MSMul(
    [x]M,[y]M
    ):Beaver

  • [x]2bitDecompose(
    [x]M
    ): Parties hold arithmetic secret shares of
    x
    which is an
    l
    -bit number, denoted as [x] in its secret shared form and they wish without revealing x to secret share each bit of
    x:al1,al2,...,a0
    with secret shares of the bit vector [a] in
    Z2
    such that
    x=ai2i
    . We denote with
    [a]ij
    the secret share of the
    i
    th bit of
    x
    held by party
    j
    ,
    0jn1
    ,
    0il1

Input: Each

CPi holds a share
[x]M
of
x

Output: Each
CPi
holds a share
[x]2
of bit
x


  1. Each CP secret shares a
    l
    random bit
    ri
    with all other parties such that no one knows
    r=ri2i
  2. Parties compute
    [x]i=0l1j=0n1rij2iZM
  3. CP's open
    c=xrZM
  4. CP's bitwise compute
    [xl1],...,[x0]=cl1+[rl1],...,c0+[r0]
  • MSBExtract([z]Z2)

Analysis

Security

Efficiency

Disadvantages: Threshold assumptions might be a bit wavy: If all validators collude they can reveal all the private information which is secret shared. Can we make assumptions on that as in research papers that all parties cannot collude? Validators might collude under the table. Can we enforce/incentivize correct behavior, otherwise slashed?

Challenges:

  1. How input is validated from users being potentially malicious? What stops a malicious user adding gibberish but welformed data to the counter? https://www.usenix.org/system/files/conference/nsdi17/nsdi17-corrigan-gibbs.pdf
  2. How validators prove correct MPC execution

To study:

  1. https://eprint.iacr.org/2019/017.pdf
  2. https://eprint.iacr.org/2019/188.pdf

Transaction Execution a la Zerocash

A transaction Tx:=snd,rcv,ic,oc, where ic equals the input coins and oc the output coins.

Zcast checks in private way:

  1. Check that ic is active
  2. Check that Tx sender is authorized
  3. Check that value at ocj is preserved: ocj.amount=ici.amount

With a ZKP:
Sender sends commitments cm1 corresponding to ic and cm2,cm3, corresponding to output coins and computes a zkp:

  1. Open commitment cm1
  2. Show that cm1
    CMTree
  3. sn1
    to non spent Tree
  4. cm2+cm3++cm3 underlying values correspond to cm1
  5. Check that signature of Tx is by sender.pk

Create_Address():

Each address comes with a public and secret key computed as follows:

  1. secret address key
    ask
    is chosen at random by user
    U
  2. public key of the adress is
    apk=PRFask(0)
  3. U
    also choses public secret keys for public key encryption scheme
    E
    , which is key private(looking ciphertexts cannot tell the the public key under which have been encrypted):
    pkenc,skenc

Now somebody knowing

ask can assign a coin
c
of value
v
to that address or can use
apk
as target for payments.

Create_Coin(v,

ask)->c,cm:

To mint a token

c of value
v
, U proceeds as follows:

  1. Choose
    ρ
    at random
  2. Compute
    sn=PRFask(ρ)
  3. Commit to (
    apk,v,ρ
    ) in two phases to hide public key:
    i.
    k=COMMr(apk,ρ)
    , for a hiding/binding commitment
    COMM
    with randomness
    r
    .
    ii.
    cm=COMMs(k,v)
  4. Coin is defined as
    c=(apk,r,ρ,v,s,cm)

    e. transaction for that minting is
    txmint=(cm,v,k,s)
    . Anyone can verify that
    cm
    contains a coin of value
    v
    as long as
    U
    deposited coins of value
    v
    . \mathsf{cm} is added to the merklee tree with root rt.

The nested commitment preserves anonymity of the the user since its public key is not explicitely part of the transaction but still anyone can verify that this was part of a valid pk unwrapping membership proofs. Transaction is also untrackable since serial number is hidden insiden

k - as such when
U
sends that coin it cannot track it.

Spend/Pour_Coin(c,

ask):

Owner of

ask who has minted coin
c=(apk,r,ρ,v,s,cm)
wishes to spend/send it to a new address:

  1. U proceeds with rerunning Create_Coin(v,
    ask
    ) twice for
    v1
    and
    v2
    such that
    v=v1+v2
    creating two new coins:

    • c1=(apk1,r1,ρ1,v1,s1,cm1)
    • c2=(apk2,r2,ρ2,v2,s2,cm2)

      and the corresponing commitments:
    • k1=COMMr1(apk1,ρ1)
    • k2=COMMr2(apk2,ρ2)
    • cm1=COMMs1(k1,v1)
    • cm2=COMMs2(k2,v2)
  2. U proves in ZK with
    πpour
    proof the followings:
    1.
    cm
    was part of the rt
    2.
    v=v1+v2

    3.
    sn
    was created correctly in
    sn=PRFask(ρ)

    4.
    apk
    was created correctly in
    apk=PRFask(0)

    5. commitments for c: k, cm were correct by opening them
    6.
    cm1
    and
    cm2
    are correct

Finally pour transaction is created as follows:

txpour=(rt,sn,cm1,cm2,πpour)

Send(

r,ρ,v,s,pkenc,apk):

Owner of

(r,ρ,v,s) coin who has pured it running the Spend/Pour_Coin wishes to send his coin to the address defined by
apk
in a private manner without exposing the values of the coin that identify its value or old owner.

  1. Compute ciphertext
    C=Epkenc(r,ρ,v,s)
  2. Put it on the ledger as part of the
    txpour
    transaction

The above works for one token type and is different from Zcash (need to digest the differences)