Skip to content

Commit

Permalink
Merge branch 'develop' into feature/integrate-ocaml-heap-rust-bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
lk86 authored Nov 5, 2020
2 parents cfee1d8 + 66635c4 commit 11b6c87
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Lucky for us, we can leverage two properties about SNARKs:
1. proofs can be merged - two proofs can be combined to form a _merge proof_
2. merges are associative - merge proofs are identical, regardless of the order merged

![Diagram of snark merge proofs](/static/img/snark-diagram.png)
![Diagram of snark merge proofs](/static/img/SnarkDiagram.jpg)
_Each σ ⇒ σ' represents a state transition (aka a transaction) — you can see from this image that the two trees are identical, regardless of the order in which transactions were proved._

What these two properties essentially allow us to do is take advantage of parallelism. If proofs can be merged, and it doesn't matter how they're combined, then SNARK proofs can be generated in parallel. Whichever proof is finished first can be combined later with the proofs in progress. This can be envisioned as a binary tree, where the bottom row (the leaves) consists of the individual transaction proofs, and each parent row, the set of respective merge proofs. We can combine these all the way to the root, which represents a state update performed by applying all the transactions.
Expand Down
30 changes: 12 additions & 18 deletions frontend/website-redesign/pages/docs/snarks/constructions.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Page from '@reason/pages/Docs';
export default Page({title: "SNARK Constructions"});
import Page from "@reason/pages/Docs";
export default Page({ title: "SNARK Constructions" });

# Which SNARK construction should I use?

Expand All @@ -8,16 +8,17 @@ This page gives an overview of some of the important criteria to have in mind wh

## Non-malleability

For many applications, it is important for SNARKs to be *non-malleable*.
Intuitively, a SNARK is *non-malleable* if seeing proofs doesn't help you produce proofs on new statements.
For many applications, it is important for SNARKs to be _non-malleable_.
Intuitively, a SNARK is _non-malleable_ if seeing proofs doesn't help you produce proofs on new statements.

A bit more in detail, a SNARK construction is *non-malleable* if
A bit more in detail, a SNARK construction is _non-malleable_ if
it is impossible to modify a proof **p** which verifies against input **x** into a proof **p'** which verifies
against an input **x'**, unless you could have done so without seeing **(p, x)**.
against an input **x'**, unless you could have done so without seeing **(p, x)**.

The technical phrase for this kind of non-malleability is *simulation extractable*.
The technical phrase for this kind of non-malleability is _simulation extractable_.

### When do I need non-malleability?

In applications where the witness or part of the witness should remain secret, you probably need
non-malleability. There are techniques for achieving the same security while still using a
malleable SNARK, but they are best left to the experts.
Expand Down Expand Up @@ -53,23 +54,16 @@ The following efficiency characteristics are important to keep in mind when sele
There are other performance criteria that are of interest if one intends to use recursive SNARKs, but
that is outside the scope of this document.

# Overview of the landscape
## Overview of the landscape

Let's evaluate some of the existing SNARK constructions according to our criteria.
Performance descriptions for some of the parameters will remain subjective until someone gets
around to running a proper, fair benchmark. There are many holes in the below table, so please
around to running a proper, fair benchmark. There are many holes in the below table, so please
make a PR if you are so moved :)

| Construction | Setup | Non-malleable | Prover time | Proof size | Verifier time |
| --- | --- | --- | --- | --- | --- |
| Groth16 | Per-program | No | Excellent | 100-300 bytes | 1-10ms |
| Bowe--Gabizon18 | Per-program | Yes | Excellent | 100-300 bytes | 1-10ms |
| Marlin | Universal | ? | Good | 1-2kB | 8-20ms |
| PLONK | Universal | ? | ? | ? | ? |
| Sonic | Universal | ? | Fair | 1-2kB | ? |
| Fractal | None | ? | Good | 80-250kB | ? |
![Snarks Overview](/static/img/SnarksOverview.jpg)

# Footnotes
## Footnotes

In this document, by "no setup", I mean a transparent setup, which in practice amounts to a choice of a hash function
like SHA256, blake2s, etc.
3 changes: 3 additions & 0 deletions frontend/website-redesign/public/static/img/SnarkDiagram.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/website-redesign/src/components/Constants.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ let codeOfConductUrl = "https://github.com/MinaProtocol/mina/blob/develop/CODE_O
let genesisGrantApplication = "https://share.hsforms.com/1y-QXRVSgQJ6nFnzbbYv_Pg4xuul";
let projectGrantApplication = "https://forms.gle/ekPwDKE1BArTqVCu9";
let githubUrl = "https://github.com/MinaProtocol/mina";

/* 1440 is the breakpoint width for desktop. Please refer to Theme.re for the specified breakpoints. */
let desktopBreakpoint = 1440;
23 changes: 22 additions & 1 deletion frontend/website-redesign/src/components/Nav.re
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,26 @@ module NavGroupLink = {
};
};

[@bs.val] [@bs.scope "window"] external innerWidth: int = "innerWidth";
[@bs.val] [@bs.scope "window"]
external addEventListener: (string, unit => unit) => unit = "addEventListener";

[@react.component]
let make = (~dark=false) => {
let (width, setWidth) = React.useState(() => 0);

React.useEffect0(() => {
let handleSize = () => {
switch ([%external innerWidth]) {
| Some(_) => setWidth(_ => innerWidth)
| None => ()
};
};
addEventListener("resize", handleSize);
handleSize();
None;
});

<header className=Styles.container>
<Next.Link href="/">
{dark
Expand Down Expand Up @@ -258,7 +276,10 @@ let make = (~dark=false) => {
<Spacer width=1.5 />
<div className=Styles.ctaContainer>
<Button
href={`Internal("/genesis")} width={`rem(13.)} paddingX=1. dark>
href={`Internal("/genesis")}
width={`rem(13.)}
paddingX=1.
dark={width < Constants.desktopBreakpoint ? true : false}>
<img src="/static/img/promo-logo.svg" height="40" />
<Spacer width=0.5 />
<span> {React.string("Join Genesis Token Program")} </span>
Expand Down
116 changes: 116 additions & 0 deletions scripts/telemetry-crawl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/env python3

# script to gather and store all telemetry from peers reachable from the local daemon

import subprocess
import sys
import os
import argparse
import json

default_port=8301
default_prog='coda'

parser = argparse.ArgumentParser(description='Get telemetry data from all Mina nodes reachable from localhost daemon')
parser.add_argument('--daemon-port',
help='daemon port on localhost (default: ' + str(default_port) + ')')
parser.add_argument('--executable',
help='Mina program on localhost (default: ' + str(default_prog) + ')')

args = parser.parse_args()

if args.daemon_port is None :
daemon_port = str(default_port)
else :
daemon_port = args.daemon_port

if args.executable is None :
prog = default_prog
else :
prog = args.executable

# map from peer IDs to telemetry data
telemetries = dict ()

# the peer ids we've already queried
seen_peer_ids = set ()

def add_telemetries (output) :

lines = output.decode ('utf-8').split ('\n')

# set of peers to query on next round
peer_ids_to_query = set ()

# populate map from responses
for line in lines :
if line == '' :
continue

telem = json.loads (line)

try :

telemetries[telem['node_peer_id']] = telem

for peer in telem['peers'] :
peer_id = peer['peer_id']
peer_ids_to_query.add (peer_id)
# don't consider this peer_id again
# the query to this peer may not succeed, though
seen_peer_ids.add (peer_id)

except :

print ('Error in telemetry response: ' + line)

return peer_ids_to_query

# get telemetry data from peers known to daemon
output = subprocess.check_output([prog, 'advanced', 'telemetry', '-daemon-peers', '-daemon-port', daemon_port])

peer_ids_to_query = add_telemetries (output)

done = False

# calculate fixpoint: add telemetries from peer ids until we see no new peer ids
while not done :

done = True

formatted_peer_ids = ''

for peer_id in peer_ids_to_query :

if peer_id in seen_peer_ids :
continue
else :
done = False
if peer_id_count == 0 :
formatted_peer_ids = peer_id
else :
formatted_peer_ids = peer_id + ',' + formatted_peer_ids

if done :
break

output = subprocess.check_output([prog, 'advanced', 'telemetry', '-peer-ids', formatted_peer_ids, '-daemon-port', daemon_port])
peer_ids_to_query = add_telemetries (output)



print ('{ "peer_ids_queried": ' + str(len(seen_peer_ids)) + ',')
print (' "telemetries": [')

num_telemetries=len(telemetries)
count = 0

for telem in telemetries.values () :
s = str(telem).replace("'",'"')
if count < num_telemetries - 1:
print (' ' + s + ',')
else :
print (' ' + s)
count += 1

print (' ]}')
15 changes: 9 additions & 6 deletions src/lib/consensus/proof_of_stake.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ let name = "proof_of_stake"
let genesis_ledger_total_currency ~ledger =
Coda_base.Ledger.to_list (Lazy.force ledger)
|> List.fold_left ~init:Balance.zero ~f:(fun sum account ->
Balance.add_amount sum
(Balance.to_amount @@ account.Coda_base.Account.Poly.balance)
|> Option.value_exn ?here:None ?error:None
~message:"failed to calculate total currency in genesis ledger"
)
let open Coda_base in
let open Account.Poly in
(* only default token matters for total currency used to determine stake *)
if Token_id.equal account.token_id Token_id.default then
Balance.add_amount sum (Balance.to_amount @@ account.balance)
|> Option.value_exn ?here:None ?error:None
~message:"Failed to calculate total currency in genesis ledger"
else sum )
|> Balance.to_amount

let genesis_ledger_hash ~ledger =
Expand Down Expand Up @@ -1910,7 +1913,7 @@ module Data = struct
Amount.add previous_consensus_state.total_currency supply_increase
|> Option.map ~f:Or_error.return
|> Option.value
~default:(Or_error.error_string "failed to add total_currency")
~default:(Or_error.error_string "Failed to add total_currency")
and () =
if
Consensus_transition.(
Expand Down
5 changes: 4 additions & 1 deletion src/lib/merkle_mask/maskable_merkle_tree.ml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ module Make (Inputs : Inputs_intf) = struct
let num_accounts = Mask.Attached.num_accounts mask in
let total_currency =
Mask.Attached.foldi mask ~init:0 ~f:(fun _ total_currency account ->
total_currency + (Balance.to_int @@ Account.balance account) )
(* only default token matters for total currency *)
if Token_id.equal (Account.token account) Token_id.default then
total_currency + (Balance.to_int @@ Account.balance account)
else total_currency )
in
let uuid = format_uuid mask in
{ hash= Visualization.display_prefix_of_string @@ Hash.to_string root_hash
Expand Down

0 comments on commit 11b6c87

Please sign in to comment.