Ethereum is how the Internet was supposed to work.
Ethereum was crowdfunded during August 2014 by fans all around the world. It is developed by ETHDEV with contributions from great minds across the globe.
https://www.cryptocompare.com/mining/guides/howto…
https://github.com/ethereum/goethereum/wiki/Minin…
https://ethereum.gitbooks.io/frontierguide/conten…
https://github.com/ethereum/wiki/wiki
https://www.reddit.com/r/ethereum
https://github.com/ethereum/mist/releases/download…
Online wallet:
The following fullnode implementations of Ethereum are available:
https://azure.microsoft.com/enin/blog/ethereumbl…
https://explorer.etherapps.info/
https://tradeblock.com/ethereum/
https://github.com/etherparty/explorer (Git Source)
https://poloniex.com/exchange/btc_eth
https://www.gatecoin.com/public/markets
https://www.cryptsy.com/markets/view/ETH_BTC
https://bittrex.com/Market/Index?MarketName=BTCET…
https://bleutrade.com/exchange/ETH/BTC
https://metaexchange.info/markets/ETH/BTC
https://alcurex.org/index.php/crypto/index
https://yunbi.com/markets/ethcny
https://www.cryptocompare.com/coins/eth/markets/BT…
http://ether.fund/tool/contract
http://ether.fund/tool/etherface
http://ether.fund/tool/terminal
http://ether.fund/tool/converter
http://ether.fund/tool/calculator
http://ether.fund/tool/gasfees
http://ether.fund/tool/gasprice
http://ether.fund/tool/blockcast
https://www2.coinmine.pl/eth/index.php?page=statistics&action=blocks
https://twitter.com/ethereumproject
https://plus.google.com/+EthereumOrgOfficial
https://www.facebook.com/ethereumproject/
Ethereum is how the Internet was supposed to work.
Ethereum was crowdfunded during August 2014 by fans all around the world. It is developed by ETHDEV with contributions from great minds across the globe.
https://www.cryptocompare.com/mining/guides/howto…
https://github.com/ethereum/goethereum/wiki/Minin…
https://ethereum.gitbooks.io/frontierguide/conten…
https://github.com/ethereum/wiki/wiki
https://www.reddit.com/r/ethereum
https://github.com/ethereum/mist/releases/download…
Online wallet:
The following fullnode implementations of Ethereum are available:
https://azure.microsoft.com/enin/blog/ethereumbl…
https://explorer.etherapps.info/
https://tradeblock.com/ethereum/
https://github.com/etherparty/explorer (Git Source)
https://poloniex.com/exchange/btc_eth
https://www.gatecoin.com/public/markets
https://www.cryptsy.com/markets/view/ETH_BTC
https://bittrex.com/Market/Index?MarketName=BTCET…
https://bleutrade.com/exchange/ETH/BTC
https://metaexchange.info/markets/ETH/BTC
https://alcurex.org/index.php/crypto/index
https://yunbi.com/markets/ethcny
https://www.cryptocompare.com/coins/eth/markets/BT…
http://ether.fund/tool/contract
http://ether.fund/tool/etherface
http://ether.fund/tool/terminal
http://ether.fund/tool/converter
http://ether.fund/tool/calculator
http://ether.fund/tool/gasfees
http://ether.fund/tool/gasprice
http://ether.fund/tool/blockcast
https://www2.coinmine.pl/eth/index.php?page=statistics&action=blocks
https://twitter.com/ethereumproject
https://plus.google.com/+EthereumOrgOfficial
https://www.facebook.com/ethereumproject/
This blog post provides an update on our findings following the discovery of the storage corruption bug last week. In summary, the bug was much less severe than we initially thought. The small number of affected contracts we found is either only exploitable by the owner, or the exploit can only cause a disruption in the user interface and not in the actual contract logic. All exploitable contracts/dapps we reviewed can be fixed without having to upgrade the contract itself. Of course, please still check your contracts to be safe.
Following the discovery of the storage corruption bug in the Solidity compiler and the realization that it may have serious effects on alreadydeployed contracts that cannot be updated, we started analyzing how common the bug is and how exploitable contracts can be addressed.
We focused on contracts with source code published on etherscan because important or popular smart contracts usually have their source code published there in order to gain trust from their users, who can then verify the compilation. Furthermore, if the source code is not available, it is also much harder for an attacker to find a suitable exploit. Finally, contracts that are privately used (and thus do not require publishing their source code) usually check that they are called from a certain address, and thus an attacker has no means to write to their storage.
In order to automate the process of checking all contracts on etherscan, we created a modified version of the Solidity compiler that can automatically detect the conditions for triggering the bug. This technique has already reduced the number of potentially vulnerable contracts to 167. We then manually checked those contracts for potential corruption of storage that would make them vulnerable to attacks.
It turns out that only ten contracts were vulnerable, so we were able to contact most of the contract owners/developers. Seven out of ten of those contracts are only exploitable by the owner in that they are allowed to change certain parameters outside their permitted range, or allowed to unlock a previously locked contract. One contract is exploitable by unprivileged users but have other major flaws in its design. The other two contracts found to be exploitable by unprivileged users either provided no advantages if exploited or only affected the user interface.
First, let us define what we mean by “exploitable”:
The storage corruption bug is exploitable if it can be used to modify a variable in storage in a way that would not be possible without the bug, and this modification has consequences for the behaviour and use of the smart contract. For example, we do not consider a contract exploitable in the following situations:
Why is this critical bug only exploitable in so few cases?
It is a combination of the following factors that together multiply and dramatically reduce the probability of exploitability.
msg.sender
and thus not exploitable.
Even if the owner can be changed, the flag is often a flag that can be
still be set by the owner through other means.A large majority of the exploitable contracts are only exploitable by the contract owner, administrator or developer, particularly though a single function that allows the owner to be changed. The exploit allows a further escalation of privileges for the owner. In order to prevent the owner from taking advantage of this exploit, a proxy contract can be installed between the owner and the affected contract. This proxy contract forwards calls from the owner, but disallows calling the exploitable functions. If calling the exploitable functions is still necessary, the proxy contract can prevent malicious data from being forwarded to the contract.
If you have specific questions or concerns regarding your contracts, please contact us on gitter.
]]>The Go Ethereum team is very proud to finally release Geth 1.5, which
can almost be called a complete internal rewrite of the
Go Ethereum (goethereum
) codebase.
We’ve packed a huge number of changes into this release, and simply listing them wouldn’t do them justice. Instead, we’ve decided to write them up in a more informal way, explaining not only what’s new, but also why it’s needed, and why it’s awesome!
The goethereum
project never really had a website. There was something
autogenerated a long time ago by GitHub, but it couldn’t really be
called a decent website as it didn’t contain valuable information,
didn’t look particularly good, and there was nobody to properly maintain
it. But at the time it was ok as the hardcore developers were cared
more about the source repository and wiki pages, than a web site.
However, as Ethereum gains popularity and traction, we are now making efforts to make Geth, its code, and associated resources more accessible and streamlined for everyone involved, not just a handful of core developers. As a first step in this direction we’ve begun to put together a new website for goethereum. You can see it at: https://geth.ethereum.org.
The web site still has a long way to go, but we’ve done our best to include information that is not available elsewhere else, yet we feel is essential for anyone starting out with goethereum: a detailed installation guide for all platforms, and a downloads section gathering all our binaries from every build service we maintain. You can expect a detailed developer guide in the next few weeks, and a detailed user guide afterwards.
Go Ethereum, one of three original clients along with C++ Ethereum and Py Ethereum, evolved alongside the Ethereum networking and consensus protocol specification. This process entailed fast prototyping, frequent rewrites and binned features. The net effect was a codebase that worked well, but was difficult to embed into other projects due to its messy internals.
In the Geth 1.4.x series we started untangling <strong>goethereum</strong>
,
but it took longer than anticipated to clean up most of the public API
pathways. With Geth 1.5, we’ve finally arrived at the point where we can
stand behind our programmatic APIs both as usable and as something we
would like to support long term. The final pieces are still being
polished, but we’re confident you’ll like the result a lot!
Our main areas of focus were: a) simplified client side account management, b) remote clients via HTTP, IPC and WebSockets; c) contract interactions and binding generation, and d) inprocess embedded nodes. With these four main usecases covered, we’re confident most server side or mobile applications can go a long way.
Check out the teaser slide presentation about our new APIs presented by @karalabe at Devcon2, our Ethereum developers conference in Shanghai, a few weeks ago.
With Geth 1.5 focusing on library reusability, it is only natural to see how far we can push the envelope. There has been ample exploration of running (or at least interfacing with) Ethereum from browsers; our current release focused on doing so from desktop/server processes. The only missing piece of the puzzle was mobile devices… until now.
The 1.5 release of goethereum
introduces our first
experimental attempt at providing true Android and iOS library
reusability of our codebase. This comes in the form of a native Java and
ObjC wrapper around our code, bundled up officially as an Android
archive and iOS XCode framework. The former is more mature, while the
latter requires some API polishes due to the difficulty in automatically
wrapping Go to ObjC/Swift code.
We’re also providing native dependencies for both platforms in the form of Maven Central packages (or Sonatype for develop snapshots) for Android, and CocoaPod packages for iOS. Since this is the very first time we’re making the pushes to these package managers, there are a few hurdles that may arise, so we’ll make a separate announcement when both are reliable to use. Until then, we recommend sticking to the downloadable library bundles.
The 1.5 release of Geth is an attempted foundation for the future direction and features we’d like to work on and stabilize in upcoming releases. In our opinion, the best way to push the desired new features forward is to ship them as experimental (solely optin) protocols so that anyone can play with them and provide feedback. In the light of this, we’ve merged in quite a few things we (and hopefully the community) had been looking forward to for quite some time.
If you’ve played with joining the official testnet (Morden) or running a publicly reachable private testnet, you know it can sometimes take quite a long time to synchronize, as the node often seemingly just sits there doing nothing.
One of the root causes for testnet sync issues is that the peer discovery protocol cannot differentiate between machines running different blockchains, or even different network protocols altogether. The only way to find suitable peers is to connect to as many peers as possible and keep the ones that make sense. This approach works for the mainnet, but for smaller protocols (testnet, light clients, swarm, whisper) it’s like looking for a needle in a haystack of advertised peers.
Geth 1.5 contains a new version of the peer discovery protocol that extends the “shooting in the dark” approach with topic based peerquerying. In short, peers can actively search for other peers that have specifically advertised feature sets, protocols or configurations. This new discovery protocol should enable nodes to instantly find others of interest, even when there are only a handful among thousands of “boring” ones.
Please note: the v5 discovery protocol is experimental, hence it is currently only enabled for light clients and light servers. This will allow us to gather valuable information and analyze its behavior/anomalies without influencing the main Ethereum P2P network in the slightest.
Blockchains are large beasts, there’s no denying it. Irrelevant of optimizations, there will always be devices that are too resourceconstrained to play an active role in blockchain networks (e.g. mobile phones, IoT devices). Although unexpected, we’ve seen this effect happen during the DoS attack, which caused HDDs to have troubles syncing.
The only meaningful solution for running a blockchain on tiny embedded devices is for them to become light clients, where they do not bare the full burden of sustaining the network, but rather only bear the burden of their own operation. Not only is this beneficial for the small devices, but it also benefits the network as a whole as it removes slow links and thus makes the core network smaller, tighter and more performant.
We’re proud to finally include an alpha version of a light client inside Geth 1.5. It can sync in minutes (or less) and consume only megabytes of disk space, but nonetheless fully interacts with the Ethereum blockchain and is even usable through the Mist browser (although there have been hiccups there).
You can run Geth as a light client via the light
flag.
If you are maintaining a full node, feeling a bit generous, and
aren’t running a sensitive production system, consider enabling the
light server protocol to help out small devices in the network via
<strong>lightserv 25 lightpeers 50</strong>
flags (first sets the percentage of system resources allowed to be used
by light clients, and the second sets the number of light clients to
allow connecting).
Along with the consensus protocol, the Ethereum vision also consists of two other pillars: real time dark messaging (Whisper) and decentralized file storage (Swarm). All three are needed to create truly decentralized, high availability applications. Whisper is more or less available as an experimental protocol, but Swarm always looked like a far away dream.
With the arrival of 1.5, we’re very excited to include an initial proofofconcept implementation of the Swarm protocol for developers to play with. It is included as a separate daemon process (and inherently executable binary), not embedded inside Geth. This allows users to run Swarm against any Ethereum client while also preventing any issues from interfering with the main node’s functionality.
If you’ve written a more complex DApp against a Geth node (or any other Ethereum node for that matter), you may have noticed that polling the node for data on RPC can have adverse effects on performance. Not polling it, on the other hand, has adverse effects on user experience since the DApp is less sensitive to new events.
The issue is that polling for changes is a bad idea since most of the time there’s no change, only the possibility of one. A better solution, instead of querying the node for changes every now and then, is to subscribe to certain events and let the node provide notification when there’s a change. Geth 1.5 enables this via a new RPC subscription mechanism. Any DApp (or external process) can subscribe to a variety of events and leave it to the node to notify when needed. Since this mechanism is not possible over plain HTTP (like it is over IPC), the 1.5 release also includes support for running the RPC API via WebSockets.
During the DoS attacks in recent months, we spent an inordinate amount of time analyzing different transactions to better understand how they work. These efforts entailed trying to create various traces, looking at exactly what the EVM executes, and how that influences the underlying implementation.
Although Geth featured an EVM tracing API endpoint for quite some time now, it didn’t provide much granularity in regards to configurability. It ran the EVM bytecode, returned the executed opcodes, any occurred errors and optionally a diff of stack, and memory and storage modifications made by the transaction. This is useful, but expensive resourcewise to both create and to pass through the RPC layer.
With the 1.5 release, we’re introducing a new mechanism for tracing transactions, a JavaScript mapreduce construct. Instead of the usual trace options available until now, you will be able to specify two JavaScript methods: a mapper invoked for every opcode with access to all trace data, and a reducer invoked at the end of the trace to specify the final data to return to the caller.
The advantage of the JavaScript trace approach it that it’s executed inside the Go Ethereum node itself, so the tracer can access all information available for free without performance impact, and can collect only what it needs while discarding everything else. It is also a lot simpler to write custom trace code instead of having to parse some predefined output format.
Until the 1.4.x release cycles of Geth, the goethereum codebase used the godep
tool
as its dependency manager because Go itself did not provide a viable
alternative other than manually copying dependencies or relying on
upstream repositories to not break over time.
This situation was unfortunate due to a number of drawbacks: a)
building goethereum required both a custom tool as well as knowing the
quirks of said tool, b) dependency updates via
godep
were
very painful due to them dirtying the local workspaces and not being
able to work in temporary folders, and c) using goethereum as a library
was extremely hard as dependencies weren’t an integral part of the Go
workflow.
With the Geth 1.5 release, we’ve switched over to the officially
recommended way of vendoring dependencies (fully supported starting with
Go 1.6), namely by placing all external dependencies into locations
native to the Go compiler and toolchain (
vendor
), and switching to a different dependency management tool to more cleanly handle our requirements (called trash
).
From an outside perspective, the main benefit is no longer having to muck around with some random dependency management tool that we happen to use when building goethereum, or to using it as a library in other projects. Now you can stick to the plain old Go tools and everything will work out of the box!
From the beginning of the Ethereum project, all official clients
depended on a build infrastructure that was built and maintained by
@caktux based on Amazon EC2 instances, Ansible and a sizeable suite of
Python scripts (called the
Ethereum Buildbot
).
Initially, this infrastructure worked well when the original implementations all shipped a handful of major platform, architecture and deliverable bundles. However as time passed and projects started to focus on smaller unique builds, the maintenance burden started to ramp up as the buildbot began to crumble down. When the maintainer left the Ethereum project, it became clear that we needed to transition to new build flows, but creating them was a nontrivial effort.
One of the major milestones of the Geth 1.5 release is the complete transition from the old build infrastructure to one that is fully selfcontained within our repositories. We moved all builds on top of the various continuous integration services we rely on (Travis, AppVeyor, CircleCI), and implemented all the build code ourselves as an organic part of the goethereum sources.
The end result is that we can now build everything the goethereum project needs without depending on particular service providers or particular code outside of the team’s control. This will ensure that goethereum won’t have strange missing packages or outofdate package managers.
Starting with Geth 1.5, we are distributing significantly more build
artifacts than before. Our two major deliverables are archives
containing Geth only, and bundles containing Geth and any other tools
deemed useful for developers and/or users of the Ethereum platform.
These artifacts are precompiled for every stable release as well as
every single develop commit to a very wide variety of targets: Linux (
386
, amd64
, arm5
, arm6
, arm7
and arm64
), macOS (amd64
) and Windows (386
, amd64
).
One of our feature updates are library bundles for using goethereum
in mobile projects. On Android we’re providing official builds for
.aar
archives containing binaries for 386
, amd64
, arm7
and arm64
,
covering all popular mobiles as well as local simulator builds. On iOS
we’re providing official XCode Framework bundles containing binaries for
amd64
, arm7
and arm64
, covering all iPhone architectures as well as local simulator builds.
Besides the standalone binary archives we’re also distributing all of the above in the form of Homebrew bundles for macOS, launchpad PPA packages for Ubuntu, NSIS installers for Windows (Chocolatey distribution will need further administrative hurdles to overcome), Maven Central dependencies for Android and CocoaPods dependencies for iOS!
All of the artifacts mentioned above are available from the goethereum downloads page.
For a long time our binary distributions were a bit chaotic, sometimes providing checksums, sometimes not, which depended on who made the release packages and how much time we had to tie up loose ends. The lack of checksums often lead to users asking how to verify bundles floating around the internet, and more seriously it resulted in a number of fake developer and project clones popping up that distributed malware.
To sort this out once and for all, from Geth 1.5 an on, all our officially built archives will be digitally signed via a handful of OpenPGP keys. We will not rely on checksums any more to prove authenticity of our distributed bundles, but will ask securityconscious users to verify any downloads via their attached PGP signatures. You can find the list of signing keys we use at our OpenPGP Signatures section.
A bit before the Frontier release last July, we switched to a source repository model where the master
branch contained the latest stable code and develop
contained the bleeding edge source code we were working on.
This repository model however had a few drawbacks: a) people new to the project wanting to contribute always started hacking on master
, only to realize later that their work was based on something old; b) every time a major release was made, master
needed to be forcepushed, which looked pretty bad from a repository history perspective; c) developers trying to use the goethereum
codebase in their own projects rarely realized there was a more advanced branch available.
Beginning with Geth 1.5, we will no longer maintain a separate master
branch for lateststable and develop
branch for latestedge, rather we will switch to master
as the default and development branch of the project, and each stable release generation will have its own indefinitely living branch (e.g. release/1.4
, release/1.5
).
The release branches will allow people to depend on older generations
(e.g. 1.4.x) without finding surprising git issues with history
rewrites. And having
master
as the default development branch would allow developers to use the latest code.
The Ethereum network will be undergoing a hard fork at block number 2,675,000, which will likely occur between 15:00 and 16:00 UTC on Tuesday, November 22, 2016. A countdown timer can be seen at https://fork.codetract.io/. The Morden test network will be undergoing a hard fork at block number 1,885,000.
Download the latest version of your Ethereum client:
If you are using an Ethereum client that is not updated for the upcoming hard fork, your client will sync to the prefork blockchain once the fork occurs. You will be stuck on an incompatible chain following the old rules and you will be unable to send ether or operate on the postfork Ethereum network.
Importantly, if your client is not updated, it also means that any transactions you make will still be susceptible to replay attacks.
Ethereum websites and mobile applications that allow you to store ether and/or make transactions are running their own Ethereum client infrastructure to facilitate their services. Generally, you do not need to do anything if you use a third party web based or mobile Ethereum wallet. However, you should still check with your web or mobile Ethereum wallet provider to see what actions they are taking to update for the hard fork and if they are asking their users to take other steps.
In particular, you should ensure that transactions are generated with the new replayprotected EIP 155 scheme.
Make sure you have downloaded the latest version of your Ethereum client.
“Spurious Dragon” is the second hard fork of the tworound hard fork response to the DoS attacks on the Ethereum network in September and October. The previous hard fork (a.k.a “Tangerine Whistle”) addressed immediate network health issues due to the attacks. The upcoming hard fork addresses important but less pressing matters such as further tuning opcode pricing to prevent future attacks on the network, enabling “debloat” of the blockchain state, and adding replay attack protection.
The following Ethereum Improvement Proposals (EIPs) describe the protocol changes implemented in this hard fork.
DISCLAIMER
This is an emergent and evolving highly technical space. If you choose
to implement the recommendations in this post and continue to
participate, you should make sure you understand how it impacts you. You
should understand that there are risks involved including but not
limited to risks like unexpected bugs. By choosing to implement these
recommendations, you alone assume the risks of the consequences.
The Spurious Dragon hardfork is scheduled for the coming week; block 2675000 is likely to occur Tuesday evening (CET). The block number for the testnet “Morden” was scheduled at block 1885000. Performing the fork in the test network prior to performing it in the main network was an important measure taken in the testing process to ensure a smooth rollover into the postfork state.
The Morden fork occurred on Nov202016, 06:12:20 +UTC, at block 1885000 as planned. A bit later, at block 1885074, there was a consensus issue between Geth and Parity.
The Morden testnet has been running since the launch of the Ethereum
blockchain (July 2015). At that time, concerns about replayattacks
between Morden and Mainnet were addressed by using a nonceoffset. All
accounts on Morden used a starting nonce of 2^20
instead of 0
, ensuring that any transaction valid on one chain would not be valid on the other.
EIP 161 specifies new EVM rules regarding nonces. The implementation of those rules, in combination with Mordenspecific noncerules, resulted in Geth and Parity creating incompatible blocks at block 1885074.
All issues found during the rollout of Spurious Dragon on the test network were Mordenspecific. There are currently no known issues affecting the Mainnet.
Before the current hard forks, there were already discussions about restarting the test network from a new genesis block in order to make full syncing simpler and less resource intensive. And due to the low difficulty of the testnet, the difficulty bomb was already causing noticeable increases in block times, which would continue to grow if unaddressed. So the time is now right to leave Morden behind and start a new test network.
New clients will be released that use Ropsten instead of Morden as the default testnet.
Developers who want to get started with Ropsten right away can download the genesis file here, and start a client with the Ropsten network id:3
geth datadir /path/to/testnet/data init genesis.json; geth datadir /path/to/testnet/data networkid 3 console
parity chain path/to/ropsten.json
Security Alert
—————————–
As a very short summary, zkSNARKs as currently implemented, have 4
main ingredients (don’t worry, we will explain all the terms in later
sections):
A) Encoding as a polynomial problem
The program that is to be checked is compiled into a quadratic
equation of polynomials: t(x) h(x) = w(x) v(x), where the equality holds
if and only if the program is computed correctly. The prover wants to
convince the verifier that this equality holds.
B) Succinctness by random sampling
The verifier chooses a secret evaluation point s to reduce the
problem from multiplying polynomials and verifying polynomial function
equality to simple multiplication and equality check on numbers:
t(s)h(s) = w(s)v(s)
This reduces both the proof size and the verification time tremendously.
C) Homomorphic encoding / encryption
An encoding/encryption function E is used that has some homomorphic
properties (but is not fully homomorphic, something that is not yet
practical). This allows the prover to compute E(t(s)), E(h(s)), E(w(s)),
E(v(s)) without knowing s, she only knows E(s) and some other helpful
encrypted values.
D) Zero Knowledge
The prover permutes the values E(t(s)), E(h(s)), E(w(s)), E(v(s)) by
multiplying with a number so that the verifier can still check their
correct structure without knowing the actual encoded values.
The very rough idea is that checking t(s)h(s) = w(s)v(s) is identical
to checking t(s)h(s) k = w(s)v(s) k for a random secret number k (which
is not zero), with the difference that if you are sent only the numbers
(t(s)h(s) k) and (w(s)v(s) k), it is impossible to derive t(s)h(s) or
w(s)v(s).
This was the handwaving part so that you can understand the essence of zkSNARKs, and now we get into the details.
RSA and ZeroKnowledge Proofs
Let us start with a quick reminder of how RSA works, leaving out some
nitpicky details. Remember that we often work with numbers modulo some
other number instead of full integers. The notation here is “a + b ≡ c
(mod n)”, which means “(a + b) % n = c % n”. Note that the “(mod n)”
part does not apply to the right hand side “c” but actually to the “≡”
and all other “≡” in the same equation. This makes it quite hard to
read, but I promise to use it sparingly. Now back to RSA:
The prover comes up with the following numbers:
p, q: two random secret primes
n := p q
d: random number such that 1 < d < n – 1
e: a number such that d e ≡ 1 (mod (p1)(q1)).
The public key is (e, n) and the private key is d. The primes p and q can be discarded but should not be revealed.
The message m is encrypted via
E(m) := me % n
and c = E(m) is decrypted via
D(c) := cd % n.
Because of the fact that cd ≡ (me % n)d ≡ med (mod n) and multiplication in the exponent of m behaves like multiplication in the group modulo (p1)(q1), we get med ≡
m (mod n). Furthermore, the security of RSA relies on the assumption
that n cannot be factored efficiently and thus d cannot be computed from
e (if we knew p and q, this would be easy).
One of the remarkable feature of RSA is that it is multiplicatively homomorphic.
In general, two operations are homomorphic if you can exchange their
order without affecting the result. In the case of homomorphic
encryption, this is the property that you can perform computations on
encrypted data. Fully homomorphic encryption, something that
exists, but is not practical yet, would allow to evaluate arbitrary
programs on encrypted data. Here, for RSA, we are only talking about
group multiplication. More formally: E(x) E(y) ≡ xeye ≡ (xy)e
≡ E(x y) (mod n), or in words: The product of the encryption of two
messages is equal to the encryption of the product of the messages.
This homomorphicity already allows some kind of zeroknowledge proof
of multiplication: The prover knows some secret numbers x and y and
computes their product, but sends only the encrypted versions a = E(x), b
= E(y) and c = E(x y) to the verifier. The verifier now checks that (a
b) % n ≡ c % n and the only thing the verifier learns is the encrypted
version of the product and that the product was correctly computed, but
she neither knows the two factors nor the actual product. If you replace
the product by addition, this already goes into the direction of a
blockchain where the main operation is to add balances.
Interactive Verification
Having touched a bit on the zeroknowledge aspect, let us now focus
on the other main feature of zkSNARKs, the succinctness. As you will see
later, the succinctness is the much more remarkable part of zkSNARKs,
because the zeroknowledge part will be given “for free” due to a
certain encoding that allows for a limited form of homomorphic encoding.
SNARKs are short for succinct noninteractive arguments of knowledge. In this general setting of socalled interactive protocols, there is a prover and a verifier
and the prover wants to convince the verifier about a statement (e.g.
that f(x) = y) by exchanging messages. The generally desired properties
are that no prover can convince the verifier about a wrong statement (soundness) and there is a certain strategy for the prover to convince the verifier about any true statement (completeness). The individual parts of the acronym have the following meaning:
Succinct: the sizes of the messages are tiny in comparison to the length of the actual computation
Noninteractive: there is no or only little interaction. For
zkSNARKs, there is usually a setup phase and after that a single message
from the prover to the verifier. Furthermore, SNARKs often have the
socalled “public verifier” property meaning that anyone can verify
without interacting anew, which is important for blockchains.
ARguments: the verifier is only protected against computationally
limited provers. Provers with enough computational power can create
proofs/arguments about wrong statements (Note that with enough
computational power, any publickey encryption can be broken). This is
also called “computational soundness”, as opposed to “perfect
soundness”.
of Knowledge: it is not possible for the prover to construct a proof/argument without knowing a certain socalled witness (for example the address she wants to spend from, the preimage of a hash function or the path to a certain Merkletree node).
If you add the zeroknowledge prefix, you also
require the property (roughly speaking) that during the interaction, the
verifier learns nothing apart from the validity of the statement. The
verifier especially does not learn the witness string – we will see later what that is exactly.
As an example, let us consider the following transaction validation computation: f(σ1, σ2, s, r, v, ps, pr, v) = 1 if and only if σ1 and σ2 are the root hashes of account Merkletrees (the pre and the poststate), s and r are sender and receiver accounts and ps, pr are Merkletree proofs that testify that the balance of s is at least v in σ1 and they hash to σ2 instead of σ1 if v is moved from the balance of s to the balance of r.
It is relatively easy to verify the computation of f if all inputs
are known. Because of that, we can turn f into a zkSNARK where only σ1 and σ2 are publicly known and (s, r, v, ps, pr,
v) is the witness string. The zeroknowledge property now causes the
verifier to be able to check that the prover knows some witness that
turns the root hash from σ1 to σ2 in a way that does not violate any requirement on correct transactions, but she has no idea who sent how much money to whom.
The formal definition (still leaving out some details) of zeroknowledge is that there is a simulator
that, having also produced the setup string, but does not know the
secret witness, can interact with the verifier — but an outside observer
is not able to distinguish this interaction from the interaction with
the real prover.
NP and ComplexityTheoretic Reductions
In order to see which problems and computations zkSNARKs can be used
for, we have to define some notions from complexity theory. If you do
not care about what a “witness” is, what you will not know
after “reading” a zeroknowledge proof or why it is fine to have
zkSNARKs only for a specific problem about polynomials, you can skip
this section.
P and NP
First, let us restrict ourselves to functions that only output 0 or 1 and call such functions problems.
Because you can query each bit of a longer result individually, this is
not a real restriction, but it makes the theory a lot easier. Now we
want to measure how “complicated” it is to solve a given problem
(compute the function). For a specific machine implementation M of a
mathematical function f, we can always count the number of steps it
takes to compute f on a specific input x – this is called the runtime
of M on x. What exactly a “step” is, is not too important in this
context. Since the program usually takes longer for larger inputs, this
runtime is always measured in the size or length (in number of bits) of
the input. This is where the notion of e.g. an “n2 algorithm” comes from – it is an algorithm that takes at most n2 steps on inputs of size n. The notions “algorithm” and “program” are largely equivalent here.
Programs whose runtime is at most nk for some k are also called “polynomialtime programs”.
Two of the main classes of problems in complexity theory are P and NP:
P is the class of problems L that have polynomialtime programs.
Even though the exponent k can be quite large for some problems, P is
considered the class of “feasible” problems and indeed, for
nonartificial problems, k is usually not larger than 4. Verifying a
bitcoin transaction is a problem in P, as is evaluating a polynomial
(and restricting the value to 0 or 1). Roughly speaking, if you only
have to compute some value and not “search” for something, the problem
is almost always in P. If you have to search for something, you mostly
end up in a class called NP.
The Class NP
There are zkSNARKs for all problems in the class NP and actually, the
practical zkSNARKs that exist today can be applied to all problems in
NP in a generic fashion. It is unknown whether there are zkSNARKs for
any problem outside of NP.
All problems in NP always have a certain structure, stemming from the definition of NP:
NP is the class of problems L that have a polynomialtime program V
that can be used to verify a fact given a polynomiallysized socalled
witness for that fact. More formally:
L(x) = 1 if and only if there is some polynomiallysized string w (called the witness) such that V(x, w) = 1
As an example for a problem in NP, let us consider the problem of
boolean formula satisfiability (SAT). For that, we define a boolean
formula using an inductive definition:
any variable x1, x2, x3,… is a boolean formula (we also use any other character to denote a variable
if f is a boolean formula, then ¬f is a boolean formula (negation)
if f and g are boolean formulas, then (f ∧ g) and (f ∨ g) are boolean formulas (conjunction / and, disjunction / or).
The string “((x1∧ x2) ∧ ¬x2)” would be a boolean formula.
A boolean formula is satisfiable if there is a way to assign
truth values to the variables so that the formula evaluates to true
(where ¬true is false, ¬false is true, true ∧ false is false and so on,
the regular rules). The satisfiability problem SAT is the set of all
satisfiable boolean formulas.
SAT(f) := 1 if f is a satisfiable boolean formula and 0 otherwise
The example above, “((x1∧ x2) ∧ ¬x2)”,
is not satisfiable and thus does not lie in SAT. The witness for a
given formula is its satisfying assignment and verifying that a variable
assignment is satisfying is a task that can be solved in polynomial
time.
P = NP?
If you restrict the definition of NP to witness strings of length
zero, you capture the same problems as those in P. Because of that,
every problem in P also lies in NP. One of the main tasks in complexity
theory research is showing that those two classes are actually different
– that there is a problem in NP that does not lie in P. It might seem
obvious that this is the case, but if you can prove it formally, you can
win US$ 1 million.
Oh and just as a side note, if you can prove the converse, that P and
NP are equal, apart from also winning that amount, there is a big chance
that cryptocurrencies will cease to exist from one day to the next. The
reason is that it will be much easier to find a solution to a proof of
work puzzle, a collision in a hash function or the private key
corresponding to an address. Those are all problems in NP and since you
just proved that P = NP, there must be a polynomialtime program for
them. But this article is not to scare you, most researchers believe
that P and NP are not equal.
NPCompleteness
Let us get back to SAT. The interesting property of this seemingly
simple problem is that it does not only lie in NP, it is also
NPcomplete. The word “complete” here is the same complete as in
“Turingcomplete”. It means that it is one of the hardest problems in
NP, but more importantly — and that is the definition of NPcomplete —
an input to any problem in NP can be transformed to an equivalent input
for SAT in the following sense:
For any NPproblem L there is a socalled reduction function f, which is computable in polynomial time such that:
L(x) = SAT(f(x))
Such a reduction function can be seen as a compiler: It takes source
code written in some programming language and transforms in into an
equivalent program in another programming language, which typically is a
machine language, which has the some semantic behaviour. Since SAT is
NPcomplete, such a reduction exists for any possible problem in NP,
including the problem of checking whether e.g. a bitcoin transaction is
valid given an appropriate block hash. There is a reduction function
that translates a transaction into a boolean formula, such that the
formula is satisfiable if and only if the transaction is valid.
Reduction Example
In order to see such a reduction, let us consider the problem of
evaluating polynomials. First, let us define a polynomial (similar to a
boolean formula) as an expression consisting of integer constants,
variables, addition, subtraction, multiplication and (correctly
balanced) parentheses. Now the problem we want to consider is
PolyZero(f) := 1 if f is a polynomial which has a zero where its variables are taken from the set {0, 1}
We will now construct a reduction from SAT to PolyZero and thus show
that PolyZero is also NPcomplete (checking that it lies in NP is left
as an exercise).
It suffices to define the reduction function r on the structural
elements of a boolean formula. The idea is that for any boolean formula
f, the value r(f) is a polynomial with the same number of variables and
f(a1,..,ak) is true if and only if r(f)(a1,..,ak)
is zero, where true corresponds to 1 and false corresponds to 0, and
r(f) only assumes the value 0 or 1 on variables from {0, 1}:
r(xi) := (1 – xi)
r(¬f) := (1 – r(f))
r((f ∧ g)) := (1 – (1 – r(f))(1 – r(g)))
r((f ∨ g)) := r(f)r(g)
One might have assumed that r((f ∧ g)) would be defined as r(f) +
r(g), but that will take the value of the polynomial out of the {0, 1}
set.
Using r, the formula ((x ∧ y) ∨¬x) is translated to (1 – (1 – (1 – x))(1 – (1 – y))(1 – (1 – x)),
Note that each of the replacement rules for r satisfies the goal stated above and thus r correctly performs the reduction:
SAT(f) = PolyZero(r(f)) or f is satisfiable if and only if r(f) has a zero in {0, 1}
Witness Preservation
From this example, you can see that the reduction function only
defines how to translate the input, but when you look at it more closely
(or read the proof that it performs a valid reduction), you also see a
way to transform a valid witness together with the input. In our
example, we only defined how to translate the formula to a polynomial,
but with the proof we explained how to transform the witness, the
satisfying assignment. This simultaneous transformation of the witness
is not required for a transaction, but it is usually also done. This is
quite important for zkSNARKs, because the the only task for the prover
is to convince the verifier that such a witness exists, without
revealing information about the witness.
Quadratic Span Programs
In the previous section, we saw how computational problems inside NP
can be reduced to each other and especially that there are NPcomplete
problems that are basically only reformulations of all other problems in
NP – including transaction validation problems. This makes it easy for
us to find a generic zkSNARK for all problems in NP: We just choose a
suitable NPcomplete problem. So if we want to show how to validate
transactions with zkSNARKs, it is sufficient to show how to do it for a
certain problem that is NPcomplete and perhaps much easier to work with
theoretically.
This and the following section is based on the paper GGPR12
(the linked technical report has much more information than the journal
paper), where the authors found that the problem called Quadratic Span
Programs (QSP) is particularly well suited for zkSNARKs. A Quadratic
Span Program consists of a set of polynomials and the task is to find a
linear combination of those that is a multiple of another given
polynomial. Furthermore, the individual bits of the input string
restrict the polynomials you are allowed to use. In detail (the general
QSPs are a bit more relaxed, but we already define the strong version because that will be used later):
A QSP over a field F for inputs of length n consists of
a set of polynomials v0,…,vm, w0,…,wm over this field F,
a polynomial t over F (the target polynomial),
an injective function f: {(i, j)  1 ≤ i ≤ n, j ∈ {0, 1}} → {1, …, m}
The task here is roughly, to multiply the polynomials by factors and add them so that the sum (which is called a linear combination)
is a multiple of t. For each binary input string u, the function f
restricts the polynomials that can be used, or more specific, their
factors in the linear combinations. For formally:
An input u is accepted (verified) by the QSP if and only if there are tuples a = (a1,…,am), b = (b1,…,bm) from the field F such that
ak,bk = 1 if k = f(i, u[i]) for some i, (u[i] is the ith bit of u)
ak,bk = 0 if k = f(i, 1 – u[i]) for some i and
the target polynomial t divides va wb where va = v0 + a1 v0 + … + amvm, wb = w0 + b1 w0 + … + bmwm.
Note that there is still some freedom in choosing the tuples a and b
if 2n is smaller than m. This means QSP only makes sense for inputs up
to a certain size – this problem is removed by using nonuniform
complexity, a topic we will not dive into now, let us just note that it
works well for cryptography where inputs are generally small.
As an analogy to satisfiability of boolean formulas, you can see the factors a1,…,am, b1,…,bm
as the assignments to the variables, or in general, the NP witness. To
see that QSP lies in NP, note that all the verifier has to do (once she
knows the factors) is checking that the polynomial t divides va wb, which is a polynomialtime problem.
We will not talk about the reduction from generic computations or
circuits to QSP here, as it does not contribute to the understanding of
the general concept, so you have to believe me that QSP is NPcomplete
(or rather complete for some nonuniform analogue like NP/poly). In
practice, the reduction is the actual “engineering” part – it has to be
done in a clever way such that the resulting QSP will be as small as
possible and also has some other nice features.
One thing about QSPs that we can already see is how to verify them
much more efficiently: The verification task consists of checking
whether one polynomial divides another polynomial. This can be
facilitated by the prover in providing another polynomial h such that t h
= va wb which turns the task into checking a polynomial identity or put differently, into checking that t h – va wb
= 0, i.e. checking that a certain polynomial is the zero polynomial.
This looks rather easy, but the polynomials we will use later are quite
large (the degree is roughly 100 times the number of gates in the
original circuit) so that multiplying two polynomials is not an easy
task.
So instead of actually computing va, wb and
their product, the verifier chooses a secret random point s (this point
is part of the “toxic waste” of zCash), computes the numbers t(s), vk(s) and wk(s) for all k and from them, va(s) and wb(s) and only checks that t(s) h(s) = va(s) wb
(s). So a bunch of polynomial additions, multiplications with a scalar
and a polynomial product is simplified to field multiplications and
additions.
Checking a polynomial identity only at a single point instead of at
all points of course reduces the security, but the only way the prover
can cheat in case t h – va wb is not the zero
polynomial is if she manages to hit a zero of that polynomial, but since
she does not know s and the number of zeros is tiny (the degree of the
polynomials) when compared to the possibilities for s (the number of
field elements), this is very safe in practice.
The zkSNARK in Detail
We now describe the zkSNARK for QSP in detail. It starts with a setup
phase that has to be performed for every single QSP. In zCash, the
circuit (the transaction verifier) is fixed, and thus the polynomials
for the QSP are fixed which allows the setup to be performed only once
and reused for all transactions, which only vary the input u. For the
setup, which generates the common reference string (CRS), the
verifier chooses a random and secret field element s and encrypts the
values of the polynomials at that point. The verifier uses some specific
encryption E and publishes E(vk(s)) and E(wk(s))
in the CRS. The CRS also contains several other values which makes the
verification more efficient and also adds the zeroknowledge property.
The encryption E used there has a certain homomorphic property, which
allows the prover to compute E(v(s)) without actually knowing vk(s).
How to Evaluate a Polynomial Succinctly and with ZeroKnowledge
Let us first look at a simpler case, namely just the encrypted
evaluation of a polynomial at a secret point, and not the full QSP
problem.
For this, we fix a group (an elliptic curve is usually chosen here) and a generator g. Remember that a group element is called generator if there is a number n (the group order) such that the list g0, g1, g2, …, gn1 contains all elements in the group. The encryption is simply E(x) := gx. Now the verifier chooses a secret field element s and publishes (as part of the CRS)
E(s0), E(s1), …, E(sd) – d is the maximum degree of all polynomials
After that, s can be (and has to be) forgotten. This is exactly what
zCash calls toxic waste, because if someone can recover this and the
other secret values chosen later, they can arbitrarily spoof proofs by
finding zeros in the polynomials.
Using these values, the prover can compute E(f(s)) for arbitrary
polynomials f without knowing s: Assume our polynomial is f(x) = 4x2 + 2x + 4 and we want to compute E(f(s)), then we get E(f(s)) = E(4s2 + 2s + 4) = g4s^2 + 2s + 4 = E(s2)4 E(s1)2 E(s0)4, which can be computed from the published CRS without knowing s.
The only problem here is that, because s was destroyed, the verifier
cannot check that the prover evaluated the polynomial correctly. For
that, we also choose another secret field element, α, and publish the
following “shifted” values:
E(αs0), E(αs1), …, E(αsd)
As with s, the value α is also destroyed after the setup phase and
neither known to the prover nor the verifier. Using these encrypted
values, the prover can similarly compute E(α f(s)), in our example this
is E(4αs2 + 2αs + 4α) = E(αs2)4 E(αs1)2 E(αs0)4.
So the prover publishes A := E(f(s)) and B := E(α f(s))) and the
verifier has to check that these values match. She does this by using
another main ingredient: A socalled pairing function e. The elliptic curve and the pairing function have to be chosen together, so that the following property holds for all x, y:
e(gx, gy) = e(g, g)xy
Using this pairing function, the verifier checks that e(A, gα) = e(B, g) — note that gα is known to the verifier because it is part of the CRS as E(αs0). In order to see that this check is valid if the prover does not cheat, let us look at the following equalities:
e(A, gα) = e(gf(s), gα) = e(g, g)α f(s)
e(B, g) = e(gα f(s), g) = e(g, g)α f(s)
The more important part, though, is the question whether the prover
can somehow come up with values A, B that fulfill the check e(A, gα)
= e(B, g) but are not E(f(s)) and E(α f(s))), respectively. The answer
to this question is “we hope not”. Seriously, this is called the
“dpower knowledge of exponent assumption” and it is unknown whether a
cheating prover can do such a thing or not. This assumption is an
extension of similar assumptions that are made for proving the security
of other publickey encryption schemes and which are similarly unknown
to be true or not.
Actually, the above protocol does not really allow the verifier to check that the prover evaluated the polynomial f(x) = 4x2 + 2x + 4, the verifier can only check that the prover evaluated some
polynomial at the point s. The zkSNARK for QSP will contain another
value that allows the verifier to check that the prover did indeed
evaluate the correct polynomial.
What this example does show is that the verifier does not need to
evaluate the full polynomial to confirm this, it suffices to evaluate
the pairing function. In the next step, we will add the zeroknowledge
part so that the verifier cannot reconstruct anything about f(s), not
even E(f(s)) – the encrypted value.
For that, the prover picks a random δ and instead of A := E(f(s)) and
B := E(α f(s))), she sends over A’ := E(δ + f(s)) and B := E(α (δ +
f(s)))). If we assume that the encryption cannot be broken, the
zeroknowledge property is quite obvious. We now have to check two
things: 1. the prover can actually compute these values and 2. the check
by the verifier is still true.
For 1., note that A’ = E(δ + f(s)) = gδ + f(s) = gδgf(s) = E(δ) E(f(s)) = E(δ) A and similarly, B’ = E(α (δ + f(s)))) = E(α δ + α f(s))) = gα δ + α f(s) = gα δ gα f(s)
= E(α)δE(α f(s)) = E(α)δ B.
For 2., note that the only thing the verifier checks is that the
values A and B she receives satisfy the equation A = E(a) und B = E(α a)
for some value a, which is obviously the case for a = δ + f(s) as it is
the case for a = f(s).
Ok, so we now know a bit about how the prover can compute the
encrypted value of a polynomial at an encrypted secret point without the
verifier learning anything about that value. Let us now apply that to
the QSP problem.
A SNARK for the QSP Problem
Remember that in the QSP we are given polynomials v0,…,vm, w0,…,wm, a target polynomial t (of degree at most d) and a binary input string u. The prover finds a1,…,am, b1,…,bm (that are somewhat restricted depending on u) and a polynomial h such that
t h = (v0 + a1v1 + … + amvm) (w0 + b1w1 + … + bmwm).
In the previous section, we already explained how the common
reference string (CRS) is set up. We choose secret numbers s and α and
publish
E(s0), E(s1), …, E(sd) and E(αs0), E(αs1), …, E(αsd)
Because we do not have a single polynomial, but sets of polynomials
that are fixed for the problem, we also publish the evaluated
polynomials right away:
E(t(s)), E(α t(s)),
E(v0(s)), …, E(vm(s)), E(α v0(s)), …, E(α vm(s)),
E(w0(s)), …, E(wm(s)), E(α w0(s)), …, E(α wm(s)),
and we need further secret numbers βv, βw, γ (they will be used to verify that those polynomials were evaluated and not some arbitrary polynomials) and publish
E(γ), E(βv γ), E(βw γ),
E(βv v1(s)), …, E(βv vm(s))
E(βw w1(s)), …, E(βw wm(s))
E(βv t(s)), E(βw t(s))
This is the full common reference string. In practical
implementations, some elements of the CRS are not needed, but that would
complicated the presentation.
Now what does the prover do? She uses the reduction explained above to find the polynomial h and the values a1,…,am, b1,…,bm. Here it is important to use a witnesspreserving reduction (see above) because only then, the values a1,…,am, b1,…,bm
can be computed together with the reduction and would be very hard to
find otherwise. In order to describe what the prover sends to the
verifier as proof, we have to go back to the definition of the QSP.
There was an injective function f: {(i, j)  1 ≤ i ≤ n, j ∈ {0, 1}} → {1, …, m} which restricts the values of a1,…,am, b1,…,bm.
Since m is relatively large, there are numbers which do not appear in
the output of f for any input. These indices are not restricted, so let
us call them Ifree and define vfree(x) = Σk akvk(x) where the k ranges over all indices in Ifree. For w(x) = b1w1(x) + … + bmwm(x), the proof now consists of
Vfree := E(vfree(s)), W := E(w(s)), H := E(h(s)),
V’free := E(α vfree(s)), W’ := E(α w(s)), H’ := E(α h(s)),
Y := E(βv vfree(s) + βw w(s)))
where the last part is used to check that the correct polynomials
were used (this is the part we did not cover yet in the other example).
Note that all these encrypted values can be generated by the prover
knowing only the CRS.
The task of the verifier is now the following:
Since the values of ak, where k is not a “free” index can
be computed directly from the input u (which is also known to the
verifier, this is what is to be verified), the verifier can compute the
missing part of the full sum for v:
E(vin(s)) = E(Σk akvk(s)) where the k ranges over all indices not in Ifree.
With that, the verifier now confirms the following equalities using the pairing function e (don’t be scared):
e(V’free, g) = e(Vfree, gα), e(W’, E(1)) = e(W, E(α)), e(H’, E(1)) = e(H, E(α))
e(E(γ), Y) = e(E(βv γ), Vfree) e(E(βw γ), W)
e(E(v0(s)) E(vin(s)) Vfree, E(w0(s)) W) = e(H, E(t(s)))
To grasp the general concept here, you have to understand that the
pairing function allows us to do some limited computation on encrypted
values: We can do arbitrary additions but just a single multiplication.
The addition comes from the fact that the encryption itself is already
additively homomorphic and the single multiplication is realized by the
two arguments the pairing function has. So e(W’, E(1)) = e(W, E(α))
basically multiplies W’ by 1 in the encrypted space and compares that to
W multiplied by α in the encrypted space. If you look up the value W
and W’ are supposed to have – E(w(s)) and E(α w(s)) – this checks out if
the prover supplied a correct proof.
If you remember from the section about evaluating polynomials at
secret points, these three first checks basically verify that the prover
did evaluate some polynomial built up from the parts in the CRS. The
second item is used to verify that the prover used the correct
polynomials v and w and not just some arbitrary ones. The idea behind is
that the prover has no way to compute the encrypted combination E(βv vfree(s) + βw w(s))) by some other way than from the exact values of E(vfree(s)) and E(w(s)). The reason is that the values βv are not part of the CRS in isolation, but only in combination with the values vk(s) and βw is only known in combination with the polynomials wk(s). The only way to “mix” them is via the equally encrypted γ.
Assuming the prover provided a correct proof, let us check that the
equality works out. The left and right hand sides are, respectively
e(E(γ), Y) = e(E(γ), E(βv vfree(s) + βw w(s))) = e(g, g)γ(βv vfree(s) + βw w(s))
e(E(βv γ), Vfree) e(E(βw γ), W) = e(E(βv γ), E(vfree(s))) e(E(βw γ), E(w(s))) = e(g, g)(βv γ) vfree(s) e(g, g)(βw γ) w(s) = e(g, g)γ(βv vfree(s) + βw w(s))
The third item essentially checks that (v0(s) + a1v1(s) + … + amvm(s)) (w0(s) + b1w1(s) + … + bmwm(s))
= h(s) t(s), the main condition for the QSP problem. Note that
multiplication on the encrypted values translates to addition on the
unencrypted values because E(x) E(y) = gx gy = gx+y = E(x + y).
Adding ZeroKnowledge
As I said in the beginning, the remarkable feature about zkSNARKS is
rather the succinctness than the zeroknowledge part. We will see now
how to add zeroknowledge and the next section will be touch a bit more
on the succinctness.
The idea is that the prover “shifts” some values by a random secret
amount and balances the shift on the other side of the equation. The
prover chooses random δfree, δw and performs the following replacements in the proof
vfree(s) is replaced by vfree(s) + δfree t(s)
w(s) is replaced by w(s) + δw t(s).
By these replacements, the values Vfree and W, which
contain an encoding of the witness factors, basically become
indistinguishable form randomness and thus it is impossible to extract
the witness. Most of the equality checks are “immune” to the
modifications, the only value we still have to correct is H or h(s). We
have to ensure that
(v0(s) + a1v1(s) + … + amvm(s)) (w0(s) + b1w1(s) + … + bmwm(s)) = h(s) t(s), or in other words
(v0(s) + vin(s) + vfree(s)) (w0(s) + w(s)) = h(s) t(s)
still holds. With the modifications, we get
(v0(s) + vin(s) + vfree(s) + δfree t(s)) (w0(s) + w(s) + δw t(s))
and by expanding the product, we see that replacing h(s) by
h(s) + δfree (w0(s) + w(s)) + δw (v0(s) + vin(s) + vfree(s)) + (δfree δw) t(s)
will do the trick.
Tradeoff between Input and Witness Size
As you have seen in the preceding sections, the proof consists only
of 7 elements of a group (typically an elliptic curve). Furthermore, the
work the verifier has to do is checking some equalities involving
pairing functions and computing E(vin(s)), a task that is
linear in the input size. Remarkably, neither the size of the witness
string nor the computational effort required to verify the QSP (without
SNARKs) play any role in verification. This means that SNARKverifying
extremely complex problems and very simple problems all take the same
effort. The main reason for that is because we only check the polynomial
identity for a single point, and not the full polynomial. Polynomials
can get more and more complex, but a point is always a point. The only
parameters that influence the verification effort is the level of
security (i.e. the size of the group) and the maximum size for the
inputs.
It is possible to reduce the second parameter, the input size, by shifting some of it into the witness:
Instead of verifying the function f(u, w), where u is the input and w is the witness, we take a hash function h and verify
f'(H, (u, w)) := f(u, w) ∧ h(u) = H.
This means we replace the input u by a hash of the input h(u) (which
is supposed to be much shorter) and verify that there is some value x
that hashes to H(u) (and thus is very likely equal to u) in addition to
checking f(x, w). This basically moves the original input u into the
witness string and thus increases the witness size but decreases the
input size to a constant.
This is remarkable, because it allows us to verify arbitrarily complex statements in constant time.
How is this Relevant to Ethereum
Since verifying arbitrary computations is at the core of the Ethereum
blockchain, zkSNARKs are of course very relevant to Ethereum. With
zkSNARKs, it becomes possible to not only perform secret arbitrary
computations that are verifiable by anyone, but also to do this
efficiently.
Although Ethereum uses a Turingcomplete virtual machine, it is
currently not yet possible to implement a zkSNARK verifier in Ethereum.
The verifier tasks might seem simple conceptually, but a pairing
function is actually very hard to compute and thus it would use more gas
than is currently available in a single block. Elliptic curve
multiplication is already relatively complex and pairings take that to
another level.
Existing zkSNARK systems like zCash use the same problem / circuit /
computation for every task. In the case of zCash, it is the transaction
verifier. On Ethereum, zkSNARKs would not be limited to a single
computational problem, but instead, everyone could set up a zkSNARK
system for their specialized computational problem without having to
launch a new blockchain. Every new zkSNARK system that is added to
Ethereum requires a new secret trusted setup phase (some parts can be
reused, but not all), i.e. a new CRS has to be generated. It is also
possible to do things like adding a zkSNARK system for a “generic
virtual machine”. This would not require a new setup for a new usecase
in much the same way as you do not need to bootstrap a new blockchain
for a new smart contract on Ethereum.
Getting zkSNARKs to Ethereum
There are multiple ways to enable zkSNARKs for Ethereum. All of them
reduce the actual costs for the pairing functions and elliptic curve
operations (the other required operations are already cheap enough) and
thus allows also the gas costs to be reduced for these operations.
improve the (guaranteed) performance of the EVM
improve the performance of the EVM only for certain pairing functions and elliptic curve multiplications
The first option is of course the one that pays off better in the
long run, but is harder to achieve. We are currently working on adding
features and restrictions to the EVM which would allow better
justintime compilation and also interpretation without too many
required changes in the existing implementations. The other possibility
is to swap out the EVM completely and use something like eWASM.
The second option can be realized by forcing all Ethereum clients to
implement a certain pairing function and multiplication on a certain
elliptic curve as a socalled precompiled contract. The benefit is that
this is probably much easier and faster to achieve. On the other hand,
the drawback is that we are fixed on a certain pairing function and a
certain elliptic curve. Any new client for Ethereum would have to
reimplement these precompiled contracts. Furthermore, if there are
advancements and someone finds better zkSNARKs, better pairing functions
or better elliptic curves, or if a flaw is found in the elliptic curve,
pairing function or zkSNARK, we would have to add new precompiled
contracts.
The possibilities of zkSNARKs are impressive, you can verify the correctness of computations without having to execute them and you will not even learn what was executed – just that it was done correctly. Unfortunately, most explanations of zkSNARKs resort to handwaving at some point and thus they remain something “magical”, suggesting that only the most enlightened actually understand how and why (and if?) they work. The reality is that zkSNARKs can be reduced to four simple techniques and this blog post aims to explain them. Anyone who can understand how the RSA cryptosystem works, should also get a pretty good understanding of currently employed zkSNARKs. Let’s see if it will achieve its goal!
As a very short summary, zkSNARKs as currently implemented, have 4 main ingredients (don’t worry, we will explain all the terms in later sections):
A) Encoding as a polynomial problem
The program that is to be checked is compiled into a quadratic equation of polynomials: t(x) h(x) = w(x) v(x), where the equality holds if and only if the program is computed correctly. The prover wants to convince the verifier that this equality holds.
B) Succinctness by random sampling
The verifier chooses a secret evaluation point s to reduce the problem from multiplying polynomials and verifying polynomial function equality to simple multiplication and equality check on numbers: t(s)h(s) = w(s)v(s)
This reduces both the proof size and the verification time tremendously.
C) Homomorphic encoding / encryption
An encoding/encryption function E is used that has some homomorphic properties (but is not fully homomorphic, something that is not yet practical). This allows the prover to compute E(t(s)), E(h(s)), E(w(s)), E(v(s)) without knowing s, she only knows E(s) and some other helpful encrypted values.
D) Zero Knowledge
The prover permutes the values E(t(s)), E(h(s)), E(w(s)), E(v(s)) by multiplying with a number so that the verifier can still check their correct structure without knowing the actual encoded values.
The very rough idea is that checking t(s)h(s) = w(s)v(s) is identical to checking t(s)h(s) k = w(s)v(s) k for a random secret number k (which is not zero), with the difference that if you are sent only the numbers (t(s)h(s) k) and (w(s)v(s) k), it is impossible to derive t(s)h(s) or w(s)v(s).
This was the handwaving part so that you can understand the essence of zkSNARKs, and now we get into the details.
Let us start with a quick reminder of how RSA works, leaving out some nitpicky details. Remember that we often work with numbers modulo some other number instead of full integers. The notation here is “a + b ≡ c (mod n)”, which means “(a + b) % n = c % n”. Note that the “(mod n)” part does not apply to the right hand side “c” but actually to the “≡” and all other “≡” in the same equation. This makes it quite hard to read, but I promise to use it sparingly. Now back to RSA:
The prover comes up with the following numbers:
The public key is (e, n) and the private key is d. The primes p and q can be discarded but should not be revealed.
The message m is encrypted via
and c = E(m) is decrypted via
Because of the fact that c^{d} ≡ (m^{e} % n)^{d} ≡ m^{ed} (mod n) and multiplication in the exponent of m behaves like multiplication in the group modulo (p1)(q1), we get m^{ed} ≡ m (mod n). Furthermore, the security of RSA relies on the assumption that n cannot be factored efficiently and thus d cannot be computed from e (if we knew p and q, this would be easy).
One of the remarkable feature of RSA is that it is multiplicatively homomorphic. In general, two operations are homomorphic if you can exchange their order without affecting the result. In the case of homomorphic encryption, this is the property that you can perform computations on encrypted data. Fully homomorphic encryption, something that exists, but is not practical yet, would allow to evaluate arbitrary programs on encrypted data. Here, for RSA, we are only talking about group multiplication. More formally: E(x) E(y) ≡ x^{e}y^{e} ≡ (xy)^{e} ≡ E(x y) (mod n), or in words: The product of the encryption of two messages is equal to the encryption of the product of the messages.
This homomorphicity already allows some kind of zeroknowledge proof of multiplication: The prover knows some secret numbers x and y and computes their product, but sends only the encrypted versions a = E(x), b = E(y) and c = E(x y) to the verifier. The verifier now checks that (a b) % n ≡ c % n and the only thing the verifier learns is the encrypted version of the product and that the product was correctly computed, but she neither knows the two factors nor the actual product. If you replace the product by addition, this already goes into the direction of a blockchain where the main operation is to add balances.
Having touched a bit on the zeroknowledge aspect, let us now focus on the other main feature of zkSNARKs, the succinctness. As you will see later, the succinctness is the much more remarkable part of zkSNARKs, because the zeroknowledge part will be given “for free” due to a certain encoding that allows for a limited form of homomorphic encoding.
SNARKs are short for succinct noninteractive arguments of knowledge. In this general setting of socalled interactive protocols, there is a prover and a verifier and the prover wants to convince the verifier about a statement (e.g. that f(x) = y) by exchanging messages. The generally desired properties are that no prover can convince the verifier about a wrong statement (soundness) and there is a certain strategy for the prover to convince the verifier about any true statement (completeness). The individual parts of the acronym have the following meaning:
If you add the zeroknowledge prefix, you also
require the property (roughly speaking) that during the interaction, the
verifier learns nothing apart from the validity of the statement. The
verifier especially does not learn the witness string – we will see later what that is exactly.
As an example, let us consider the following transaction validation computation: f(σ_{1}, σ_{2}, s, r, v, p_{s}, p_{r}, v) = 1 if and only if σ_{1} and σ_{2} are the root hashes of account Merkletrees (the pre and the poststate), s and r are sender and receiver accounts and p_{s}, p_{r} are Merkletree proofs that testify that the balance of s is at least v in σ_{1} and they hash to σ_{2} instead of σ_{1} if v is moved from the balance of s to the balance of r.
It is relatively easy to verify the computation of f if all inputs are known. Because of that, we can turn f into a zkSNARK where only σ_{1} and σ_{2} are publicly known and (s, r, v, p_{s}, p_{r}, v) is the witness string. The zeroknowledge property now causes the verifier to be able to check that the prover knows some witness that turns the root hash from σ_{1} to σ_{2} in a way that does not violate any requirement on correct transactions, but she has no idea who sent how much money to whom.
The formal definition (still leaving out some details) of zeroknowledge is that there is a simulator that, having also produced the setup string, but does not know the secret witness, can interact with the verifier — but an outside observer is not able to distinguish this interaction from the interaction with the real prover.
In order to see which problems and computations zkSNARKs can be used for, we have to define some notions from complexity theory. If you do not care about what a “witness” is, what you will not know after “reading” a zeroknowledge proof or why it is fine to have zkSNARKs only for a specific problem about polynomials, you can skip this section.
First, let us restrict ourselves to functions that only output 0 or 1 and call such functions problems. Because you can query each bit of a longer result individually, this is not a real restriction, but it makes the theory a lot easier. Now we want to measure how “complicated” it is to solve a given problem (compute the function). For a specific machine implementation M of a mathematical function f, we can always count the number of steps it takes to compute f on a specific input x – this is called the runtime of M on x. What exactly a “step” is, is not too important in this context. Since the program usually takes longer for larger inputs, this runtime is always measured in the size or length (in number of bits) of the input. This is where the notion of e.g. an “n^{2} algorithm” comes from – it is an algorithm that takes at most n^{2} steps on inputs of size n. The notions “algorithm” and “program” are largely equivalent here.
Programs whose runtime is at most n^{k} for some k are also called “polynomialtime programs”.
Two of the main classes of problems in complexity theory are P and NP:
Even though the exponent k can be quite large for some problems, P is considered the class of “feasible” problems and indeed, for nonartificial problems, k is usually not larger than 4. Verifying a bitcoin transaction is a problem in P, as is evaluating a polynomial (and restricting the value to 0 or 1). Roughly speaking, if you only have to compute some value and not “search” for something, the problem is almost always in P. If you have to search for something, you mostly end up in a class called NP.
There are zkSNARKs for all problems in the class NP and actually, the practical zkSNARKs that exist today can be applied to all problems in NP in a generic fashion. It is unknown whether there are zkSNARKs for any problem outside of NP.
All problems in NP always have a certain structure, stemming from the definition of NP:
As an example for a problem in NP, let us consider the problem of boolean formula satisfiability (SAT). For that, we define a boolean formula using an inductive definition:
The string “((x_{1}∧ x_{2}) ∧ ¬x_{2})” would be a boolean formula.
A boolean formula is satisfiable if there is a way to assign truth values to the variables so that the formula evaluates to true (where ¬true is false, ¬false is true, true ∧ false is false and so on, the regular rules). The satisfiability problem SAT is the set of all satisfiable boolean formulas.
The example above, “((x_{1}∧ x_{2}) ∧ ¬x_{2})”, is not satisfiable and thus does not lie in SAT. The witness for a given formula is its satisfying assignment and verifying that a variable assignment is satisfying is a task that can be solved in polynomial time.
If you restrict the definition of NP to witness strings of length zero, you capture the same problems as those in P. Because of that, every problem in P also lies in NP. One of the main tasks in complexity theory research is showing that those two classes are actually different – that there is a problem in NP that does not lie in P. It might seem obvious that this is the case, but if you can prove it formally, you can win US$ 1 million. Oh and just as a side note, if you can prove the converse, that P and NP are equal, apart from also winning that amount, there is a big chance that cryptocurrencies will cease to exist from one day to the next. The reason is that it will be much easier to find a solution to a proof of work puzzle, a collision in a hash function or the private key corresponding to an address. Those are all problems in NP and since you just proved that P = NP, there must be a polynomialtime program for them. But this article is not to scare you, most researchers believe that P and NP are not equal.
Let us get back to SAT. The interesting property of this seemingly simple problem is that it does not only lie in NP, it is also NPcomplete. The word “complete” here is the same complete as in “Turingcomplete”. It means that it is one of the hardest problems in NP, but more importantly — and that is the definition of NPcomplete — an input to any problem in NP can be transformed to an equivalent input for SAT in the following sense:
For any NPproblem L there is a socalled reduction function f, which is computable in polynomial time such that:
Such a reduction function can be seen as a compiler: It takes source code written in some programming language and transforms in into an equivalent program in another programming language, which typically is a machine language, which has the some semantic behaviour. Since SAT is NPcomplete, such a reduction exists for any possible problem in NP, including the problem of checking whether e.g. a bitcoin transaction is valid given an appropriate block hash. There is a reduction function that translates a transaction into a boolean formula, such that the formula is satisfiable if and only if the transaction is valid.
In order to see such a reduction, let us consider the problem of evaluating polynomials. First, let us define a polynomial (similar to a boolean formula) as an expression consisting of integer constants, variables, addition, subtraction, multiplication and (correctly balanced) parentheses. Now the problem we want to consider is
We will now construct a reduction from SAT to PolyZero and thus show that PolyZero is also NPcomplete (checking that it lies in NP is left as an exercise).
It suffices to define the reduction function r on the structural elements of a boolean formula. The idea is that for any boolean formula f, the value r(f) is a polynomial with the same number of variables and f(a_{1},..,a_{k}) is true if and only if r(f)(a_{1},..,a_{k}) is zero, where true corresponds to 1 and false corresponds to 0, and r(f) only assumes the value 0 or 1 on variables from {0, 1}:
One might have assumed that r((f ∧ g)) would be defined as r(f) + r(g), but that will take the value of the polynomial out of the {0, 1} set.
Using r, the formula ((x ∧ y) ∨¬x) is translated to (1 – (1 – (1 – x))(1 – (1 – y))(1 – (1 – x)),
Note that each of the replacement rules for r satisfies the goal stated above and thus r correctly performs the reduction:
Witness Preservation
From this example, you can see that the reduction function only defines how to translate the input, but when you look at it more closely (or read the proof that it performs a valid reduction), you also see a way to transform a valid witness together with the input. In our example, we only defined how to translate the formula to a polynomial, but with the proof we explained how to transform the witness, the satisfying assignment. This simultaneous transformation of the witness is not required for a transaction, but it is usually also done. This is quite important for zkSNARKs, because the the only task for the prover is to convince the verifier that such a witness exists, without revealing information about the witness.
In the previous section, we saw how computational problems inside NP can be reduced to each other and especially that there are NPcomplete problems that are basically only reformulations of all other problems in NP – including transaction validation problems. This makes it easy for us to find a generic zkSNARK for all problems in NP: We just choose a suitable NPcomplete problem. So if we want to show how to validate transactions with zkSNARKs, it is sufficient to show how to do it for a certain problem that is NPcomplete and perhaps much easier to work with theoretically.
This and the following section is based on the paper GGPR12 (the linked technical report has much more information than the journal paper), where the authors found that the problem called Quadratic Span Programs (QSP) is particularly well suited for zkSNARKs. A Quadratic Span Program consists of a set of polynomials and the task is to find a linear combination of those that is a multiple of another given polynomial. Furthermore, the individual bits of the input string restrict the polynomials you are allowed to use. In detail (the general QSPs are a bit more relaxed, but we already define the strong version because that will be used later):
A QSP over a field F for inputs of length n consists of
The task here is roughly, to multiply the polynomials by factors and add them so that the sum (which is called a linear combination) is a multiple of t. For each binary input string u, the function f restricts the polynomials that can be used, or more specific, their factors in the linear combinations. For formally:
An input u is accepted (verified) by the QSP if and only if there are tuples a = (a_{1},…,a_{m}), b = (b_{1},…,b_{m}) from the field F such that
Note that there is still some freedom in choosing the tuples a and b if 2n is smaller than m. This means QSP only makes sense for inputs up to a certain size – this problem is removed by using nonuniform complexity, a topic we will not dive into now, let us just note that it works well for cryptography where inputs are generally small.
As an analogy to satisfiability of boolean formulas, you can see the factors a_{1},…,a_{m}, b_{1},…,b_{m} as the assignments to the variables, or in general, the NP witness. To see that QSP lies in NP, note that all the verifier has to do (once she knows the factors) is checking that the polynomial t divides v_{a} w_{b}, which is a polynomialtime problem.
We will not talk about the reduction from generic computations or circuits to QSP here, as it does not contribute to the understanding of the general concept, so you have to believe me that QSP is NPcomplete (or rather complete for some nonuniform analogue like NP/poly). In practice, the reduction is the actual “engineering” part – it has to be done in a clever way such that the resulting QSP will be as small as possible and also has some other nice features.
One thing about QSPs that we can already see is how to verify them much more efficiently: The verification task consists of checking whether one polynomial divides another polynomial. This can be facilitated by the prover in providing another polynomial h such that t h = v_{a} w_{b} which turns the task into checking a polynomial identity or put differently, into checking that t h – v_{a} w_{b} = 0, i.e. checking that a certain polynomial is the zero polynomial. This looks rather easy, but the polynomials we will use later are quite large (the degree is roughly 100 times the number of gates in the original circuit) so that multiplying two polynomials is not an easy task.
So instead of actually computing v_{a}, w_{b} and their product, the verifier chooses a secret random point s (this point is part of the “toxic waste” of zCash), computes the numbers t(s), v_{k}(s) and w_{k}(s) for all k and from them, v_{a}(s) and w_{b}(s) and only checks that t(s) h(s) = v_{a}(s) w_{b} (s). So a bunch of polynomial additions, multiplications with a scalar and a polynomial product is simplified to field multiplications and additions.
Checking a polynomial identity only at a single point instead of at all points of course reduces the security, but the only way the prover can cheat in case t h – v_{a} w_{b} is not the zero polynomial is if she manages to hit a zero of that polynomial, but since she does not know s and the number of zeros is tiny (the degree of the polynomials) when compared to the possibilities for s (the number of field elements), this is very safe in practice.
We now describe the zkSNARK for QSP in detail. It starts with a setup phase that has to be performed for every single QSP. In zCash, the circuit (the transaction verifier) is fixed, and thus the polynomials for the QSP are fixed which allows the setup to be performed only once and reused for all transactions, which only vary the input u. For the setup, which generates the common reference string (CRS), the verifier chooses a random and secret field element s and encrypts the values of the polynomials at that point. The verifier uses some specific encryption E and publishes E(v_{k}(s)) and E(w_{k}(s)) in the CRS. The CRS also contains several other values which makes the verification more efficient and also adds the zeroknowledge property. The encryption E used there has a certain homomorphic property, which allows the prover to compute E(v(s)) without actually knowing v_{k}(s).
Let us first look at a simpler case, namely just the encrypted evaluation of a polynomial at a secret point, and not the full QSP problem.
For this, we fix a group (an elliptic curve is usually chosen here) and a generator g. Remember that a group element is called generator if there is a number n (the group order) such that the list g^{0}, g^{1}, g^{2}, …, g^{n1} contains all elements in the group. The encryption is simply E(x) := g^{x}. Now the verifier chooses a secret field element s and publishes (as part of the CRS)
After that, s can be (and has to be) forgotten. This is exactly what zCash calls toxic waste, because if someone can recover this and the other secret values chosen later, they can arbitrarily spoof proofs by finding zeros in the polynomials.
Using these values, the prover can compute E(f(s)) for arbitrary polynomials f without knowing s: Assume our polynomial is f(x) = 4x^{2} + 2x + 4 and we want to compute E(f(s)), then we get E(f(s)) = E(4s^{2} + 2s + 4) = g^{4s^2 + 2s + 4} = E(s^{2})^{4} E(s^{1})^{2} E(s^{0})^{4}, which can be computed from the published CRS without knowing s.
The only problem here is that, because s was destroyed, the verifier cannot check that the prover evaluated the polynomial correctly. For that, we also choose another secret field element, α, and publish the following “shifted” values:
As with s, the value α is also destroyed after the setup phase and neither known to the prover nor the verifier. Using these encrypted values, the prover can similarly compute E(α f(s)), in our example this is E(4αs^{2} + 2αs + 4α) = E(αs^{2})^{4} E(αs^{1})^{2} E(αs^{0})^{4}. So the prover publishes A := E(f(s)) and B := E(α f(s))) and the verifier has to check that these values match. She does this by using another main ingredient: A socalled pairing function e. The elliptic curve and the pairing function have to be chosen together, so that the following property holds for all x, y:
Using this pairing function, the verifier checks that e(A, g^{α}) = e(B, g) — note that g^{α} is known to the verifier because it is part of the CRS as E(αs^{0}). In order to see that this check is valid if the prover does not cheat, let us look at the following equalities:
e(A, g^{α}) = e(g^{f(s)}, g^{α}) = e(g, g)^{α f(s)}
e(B, g) = e(g^{α f(s)}, g) = e(g, g)^{α f(s)}
The more important part, though, is the question whether the prover can somehow come up with values A, B that fulfill the check e(A, g^{α}) = e(B, g) but are not E(f(s)) and E(α f(s))), respectively. The answer to this question is “we hope not”. Seriously, this is called the “dpower knowledge of exponent assumption” and it is unknown whether a cheating prover can do such a thing or not. This assumption is an extension of similar assumptions that are made for proving the security of other publickey encryption schemes and which are similarly unknown to be true or not.
Actually, the above protocol does not really allow the verifier to check that the prover evaluated the polynomial f(x) = 4x^{2} + 2x + 4, the verifier can only check that the prover evaluated some polynomial at the point s. The zkSNARK for QSP will contain another value that allows the verifier to check that the prover did indeed evaluate the correct polynomial.
What this example does show is that the verifier does not need to evaluate the full polynomial to confirm this, it suffices to evaluate the pairing function. In the next step, we will add the zeroknowledge part so that the verifier cannot reconstruct anything about f(s), not even E(f(s)) – the encrypted value.
For that, the prover picks a random δ and instead of A := E(f(s)) and B := E(α f(s))), she sends over A’ := E(δ + f(s)) and B := E(α (δ + f(s)))). If we assume that the encryption cannot be broken, the zeroknowledge property is quite obvious. We now have to check two things: 1. the prover can actually compute these values and 2. the check by the verifier is still true.
For 1., note that A’ = E(δ + f(s)) = g^{δ + f(s)} = g^{δ}g^{f(s)} = E(δ) E(f(s)) = E(δ) A and similarly, B’ = E(α (δ + f(s)))) = E(α δ + α f(s))) = g^{α δ + α f(s)} = g^{α δ} g^{α f(s)}
= E(α)^{δ}E(α f(s)) = E(α)^{δ} B.
For 2., note that the only thing the verifier checks is that the values A and B she receives satisfy the equation A = E(a) und B = E(α a) for some value a, which is obviously the case for a = δ + f(s) as it is the case for a = f(s).
Ok, so we now know a bit about how the prover can compute the encrypted value of a polynomial at an encrypted secret point without the verifier learning anything about that value. Let us now apply that to the QSP problem.
Remember that in the QSP we are given polynomials v_{0},…,v_{m}, w_{0},…,w_{m,} a target polynomial t (of degree at most d) and a binary input string u. The prover finds a_{1},…,a_{m, }b_{1},…,b_{m} (that are somewhat restricted depending on u) and a polynomial h such that
In the previous section, we already explained how the common reference string (CRS) is set up. We choose secret numbers s and α and publish
Because we do not have a single polynomial, but sets of polynomials that are fixed for the problem, we also publish the evaluated polynomials right away:
and we need further secret numbers β_{v}, β_{w}, γ (they will be used to verify that those polynomials were evaluated and not some arbitrary polynomials) and publish
This is the full common reference string. In practical implementations, some elements of the CRS are not needed, but that would complicated the presentation.
Now what does the prover do? She uses the reduction explained above to find the polynomial h and the values a_{1},…,a_{m, }b_{1},…,b_{m}. Here it is important to use a witnesspreserving reduction (see above) because only then, the values a_{1},…,a_{m, }b_{1},…,b_{m} can be computed together with the reduction and would be very hard to find otherwise. In order to describe what the prover sends to the verifier as proof, we have to go back to the definition of the QSP.
There was an injective function f: {(i, j)  1 ≤ i ≤ n, j ∈ {0, 1}} → {1, …, m} which restricts the values of a_{1},…,a_{m, }b_{1},…,b_{m}. Since m is relatively large, there are numbers which do not appear in the output of f for any input. These indices are not restricted, so let us call them I_{free} and define v_{free}(x) = Σ_{k} a_{k}v_{k}(x) where the k ranges over all indices in I_{free}. For w(x) = b_{1}w_{1}(x) + … + b_{m}w_{m}(x), the proof now consists of
where the last part is used to check that the correct polynomials were used (this is the part we did not cover yet in the other example). Note that all these encrypted values can be generated by the prover knowing only the CRS.
The task of the verifier is now the following:
Since the values of a_{k}, where k is not a “free” index can be computed directly from the input u (which is also known to the verifier, this is what is to be verified), the verifier can compute the missing part of the full sum for v:
With that, the verifier now confirms the following equalities using the pairing function e (don’t be scared):
To grasp the general concept here, you have to understand that the pairing function allows us to do some limited computation on encrypted values: We can do arbitrary additions but just a single multiplication. The addition comes from the fact that the encryption itself is already additively homomorphic and the single multiplication is realized by the two arguments the pairing function has. So e(W’, E(1)) = e(W, E(α)) basically multiplies W’ by 1 in the encrypted space and compares that to W multiplied by α in the encrypted space. If you look up the value W and W’ are supposed to have – E(w(s)) and E(α w(s)) – this checks out if the prover supplied a correct proof.
If you remember from the section about evaluating polynomials at secret points, these three first checks basically verify that the prover did evaluate some polynomial built up from the parts in the CRS. The second item is used to verify that the prover used the correct polynomials v and w and not just some arbitrary ones. The idea behind is that the prover has no way to compute the encrypted combination E(β_{v} v_{free}(s) + β_{w} w(s))) by some other way than from the exact values of E(v_{free}(s)) and E(w(s)). The reason is that the values β_{v} are not part of the CRS in isolation, but only in combination with the values v_{k}(s) and β_{w} is only known in combination with the polynomials w_{k}(s). The only way to “mix” them is via the equally encrypted γ.
Assuming the prover provided a correct proof, let us check that the equality works out. The left and right hand sides are, respectively
The third item essentially checks that (v_{0}(s) + a_{1}v_{1}(s) + … + a_{m}v_{m}(s)) (w_{0}(s) + b_{1}w_{1}(s) + … + b_{m}w_{m}(s)) = h(s) t(s), the main condition for the QSP problem. Note that multiplication on the encrypted values translates to addition on the unencrypted values because E(x) E(y) = g^{x} g^{y} = g^{x+y} = E(x + y).
As I said in the beginning, the remarkable feature about zkSNARKS is rather the succinctness than the zeroknowledge part. We will see now how to add zeroknowledge and the next section will be touch a bit more on the succinctness.
The idea is that the prover “shifts” some values by a random secret amount and balances the shift on the other side of the equation. The prover chooses random δ_{free}, δ_{w} and performs the following replacements in the proof
By these replacements, the values V_{free} and W, which contain an encoding of the witness factors, basically become indistinguishable form randomness and thus it is impossible to extract the witness. Most of the equality checks are “immune” to the modifications, the only value we still have to correct is H or h(s). We have to ensure that
still holds. With the modifications, we get
and by expanding the product, we see that replacing h(s) by
will do the trick.
As you have seen in the preceding sections, the proof consists only of 7 elements of a group (typically an elliptic curve). Furthermore, the work the verifier has to do is checking some equalities involving pairing functions and computing E(v_{in}(s)), a task that is linear in the input size. Remarkably, neither the size of the witness string nor the computational effort required to verify the QSP (without SNARKs) play any role in verification. This means that SNARKverifying extremely complex problems and very simple problems all take the same effort. The main reason for that is because we only check the polynomial identity for a single point, and not the full polynomial. Polynomials can get more and more complex, but a point is always a point. The only parameters that influence the verification effort is the level of security (i.e. the size of the group) and the maximum size for the inputs.
It is possible to reduce the second parameter, the input size, by shifting some of it into the witness:
Instead of verifying the function f(u, w), where u is the input and w is the witness, we take a hash function h and verify
This means we replace the input u by a hash of the input h(u) (which is supposed to be much shorter) and verify that there is some value x that hashes to H(u) (and thus is very likely equal to u) in addition to checking f(x, w). This basically moves the original input u into the witness string and thus increases the witness size but decreases the input size to a constant.
This is remarkable, because it allows us to verify arbitrarily complex statements in constant time.
Since verifying arbitrary computations is at the core of the Ethereum blockchain, zkSNARKs are of course very relevant to Ethereum. With zkSNARKs, it becomes possible to not only perform secret arbitrary computations that are verifiable by anyone, but also to do this efficiently.
Although Ethereum uses a Turingcomplete virtual machine, it is currently not yet possible to implement a zkSNARK verifier in Ethereum. The verifier tasks might seem simple conceptually, but a pairing function is actually very hard to compute and thus it would use more gas than is currently available in a single block. Elliptic curve multiplication is already relatively complex and pairings take that to another level.
Existing zkSNARK systems like zCash use the same problem / circuit / computation for every task. In the case of zCash, it is the transaction verifier. On Ethereum, zkSNARKs would not be limited to a single computational problem, but instead, everyone could set up a zkSNARK system for their specialized computational problem without having to launch a new blockchain. Every new zkSNARK system that is added to Ethereum requires a new secret trusted setup phase (some parts can be reused, but not all), i.e. a new CRS has to be generated. It is also possible to do things like adding a zkSNARK system for a “generic virtual machine”. This would not require a new setup for a new usecase in much the same way as you do not need to bootstrap a new blockchain for a new smart contract on Ethereum.
There are multiple ways to enable zkSNARKs for Ethereum. All of them reduce the actual costs for the pairing functions and elliptic curve operations (the other required operations are already cheap enough) and thus allows also the gas costs to be reduced for these operations.
The first option is of course the one that pays off better in the long run, but is harder to achieve. We are currently working on adding features and restrictions to the EVM which would allow better justintime compilation and also interpretation without too many required changes in the existing implementations. The other possibility is to swap out the EVM completely and use something like eWASM.
The second option can be realized by forcing all Ethereum clients to implement a certain pairing function and multiplication on a certain elliptic curve as a socalled precompiled contract. The benefit is that this is probably much easier and faster to achieve. On the other hand, the drawback is that we are fixed on a certain pairing function and a certain elliptic curve. Any new client for Ethereum would have to reimplement these precompiled contracts. Furthermore, if there are advancements and someone finds better zkSNARKs, better pairing functions or better elliptic curves, or if a flaw is found in the elliptic curve, pairing function or zkSNARK, we would have to add new precompiled contracts.
]]>The bribe attack changes the Nash Equilibrium of the Prisoner’s Dilemma game from (Up, Left) to (Down,Right). The bribing attacker in this example has a cost of 6 if (Down, Right) is played.
The bribing attacker was our first useful model of economic security.
Before the bribing attack, we usually thought about economic attacks as hostile takeovers by foreign, extraprotocol purchasers of tokens or mining power. A pile of external capital would have to come into the system to attack the blockchain. With the bribe attack, the question became “what is the price of bribing the currently existing nodes to get the desired outcome?”.
We hoped that the bribing attacks of our yettobedefined proofofstake protocol would have to spend a lot of money to compensate for lost deposits.
Debate about “reasonableness” aside, this was our first step in learning to reason about economic security. It was fun and simple to use a bribing attacker. You just see how much you have to pay the players to do what the attacker wants. And we were already confident that we would be able to make sure that an attacker has to pay securitydepositsized bribes to revert the chain in an attempted doublespend. We knew we could recognize “doublesigning”. So we were pretty sure that this would give proofofstake a quantifiable economic security advantage over a proofofwork protocol facing a bribing attacker.
Vitalik and I applied the bribing attacker to our proofofstake research. We found that PoS protocols without security deposits could be trivially defeated with small bribes. You simply pay coin holders to move their coins to new addresses and give you the key to their now empty addresses. (I’m not sure who originally thought of this idea.) Our insistence on using the briber model easily ruled out all of the proofofstake protocols we knew about. I liked that. (At the time we had not yet heard of Jae Kwon’s Tendermint, of Dominic William’s nowdefunct Pebble, or of Nick Williamson’s Credits.)
This bribe attack also posed a challenge to securitydeposit based proofofstake: The moment after a security deposit was returned to its original owner, the bribing adversary could buy the keys to their bonded stakeholder address at minimal cost.
This attack is identical to the long range attack. It is acquiring old keys to take control of the blockchain. It meant that the attacker can create “false histories” at will. But only if they start at a height from which all deposits are expired.
Before working on setting the incentives for our proofofstake protocol, therefore, we needed to address the longrange attack problem. If we didn’t address the long range attack problem, then it would be impossible for clients to reliably learn who really had the security deposits.
We did know that developer checkpoints could be used to deal with the longrange attack problem. We thought this was clearly way too centralized.
In the weeks following my conversion to proofofstake, while I was staying at Stephan Tual’s house outside of London, I discovered that there was a natural rule for client reasoning about security deposits. Signed commitments are only meaningful if the sender currently has a deposit. That is to say, after the deposit is withdrawn, the signatures from these nodes are no longer meaningful. Why would I trust you after you withdraw your deposit?
The bribing attack model demanded it. It would cost the bribing attacker almost nothing to break the commitments after the deposit is withdrawn.
This meant that a client would hold a list of bonded nodes, and stop
blocks at the door if they were not signed by one of these nodes. Ignoring consensus messages from nodes who don’t currently have security deposits solves circumvents the longrange attack problem. Instead
of authenticating the current state based on the history starting from
the genesis block, we authenticate it based on a list of who currently
has deposits.
This is radically different from proofofwork.
In PoW, a block is valid if it is chained to the genesis block, and if the block hash meets the difficulty requirement for its chain. In this security depositbased model, a block is valid if it was created by a stakeholder with a currently existing deposit. This meant that you would need to have current information in order to authenticate the blockchain. This subjectivity has caused a lot of people a lot of concern, but it is necessary for securitydeposit based proofofstake to be secure against the bribing attacker.
This realization made it very clear to me that the proofofwork security model and the proofofstake security model are fundamentally not compatible. I therefore abandoned any serious use of “hybrid” PoW/PoS solutions. Trying to authenticate a proofofstake blockchain from genesis now seemed very obviously wrong.
Beyond changing the authentication model, however, we did need to provide a way to manage these lists of security deposits. We had to use signatures from bonded nodes to manage changes to the list of bonded nodes, and we had to do it after the bonded nodes come to consensus on these changes. Otherwise, clients would have different lists of bonded validators, and they would therefore be unable to agree on the state of Ethereum.
Bond time needed to be made long, so that clients have time to learn about the new, incoming set of bonded stakeholders. As long as clients were online enough, they could keep up to date. I thought we would use twitter to share the bonded node list, or at least a hash, so that new and hibernating clients could get synchronized after their user enters a hash into the UI.
If you have the wrong validator list you can get maninthemiddled. But it’s really not that bad. The argument was (and still is!) that you only need to be able to trust an external source for this information once. After that once, you will be able to update your list yourself – at least, if you are able to be online regularly enough to avoid the “long range” of withdrawn deposits.
I know that it might take some getting used to. But we can only rely on fresh security deposits. Vitalik was a bit uncomfortable with this argument at first, trying to hold onto the ability to authenticate from genesis, but eventually was convinced by the necessity of this kind of subjectivity in proof of stake protocols. Vitalik independently came up with his weak subjectivity scoring rule, which seemed to me like a perfectly reasonable alternative to my idea at the time, which was basically “have all the deposits sign every Nth block to update the bonded node list”.
With the nails in the nothingatstake and longrange attack coffins completely hammered in, we were ready to start choosing our slashing conditions.
The next chapter will document what we learned from our first struggles to define a consensus protocol by specifying slashing conditions. I’ll also tell you about what we learned from talking with fine people from our space about our research. The game theory and economic modelling story presented here will continue developing in Chapter 4.
NOTE: The views expressed here are solely my own personal views and do not represent those of the Ethereum Foundation. I am solely responsible for what I’ve written and am not am not acting as a spokesperson for the Foundation.
By
With a light client, it is not possible to search or filter events of a certain address without specifying a log topic (allEvents filter). Looking for topics without specifying an address is also not possible and will not return any results. You can only search or watch for specific (address, topic) pairs, which is the intended use of logs anyway. If the number of possible different events a contract can generate is large, the right approach is to build a hierarchy of possible events and generate log entries both for the specific event type and for more general categories.
Light clients do not receive pending transactions from the main Ethereum network. The only pending transactions a light client knows about are the ones that have been created and sent from that client. When a light client sends a transaction, it starts downloading entire blocks until it finds the sent transaction in one of the blocks, then removes it from the pending transaction set.
Currently you can only find locally created transactions by hash. These transactions and their inclusion blocks are stored in the database and can be found by hash later. Finding other transactions is a bit trickier. It is possible (though not implemented as of yet) to download them from a server and verify the transaction is actually included in the block if the server found it. Unfortunately, if the server says that the transaction does not exist, it is not possible for the client to verify the validity of this answer. It is possible to ask multiple servers in case the first one did not know about it, but the client can never be absolutely sure about the nonexistence of a given transaction. For most applications this might not be an issue but it is something one should keep in mind if something important may depend on the existence of a transaction. A coordinated attack to fool a light client into believing that no transaction exists with a given hash would probably be difficult to execute but not entirely impossible.
The only thing a light client always has in its database is the last few thousand block headers. This means that retrieving anything else requires the client to send requests and get answers from light servers. The light client tries to optimize request distribution and collects statistical data of each server’s usual response times in order to reduce latency. Latency is the key performance parameter of a light client. It is usually in the 100200ms order of magnitude, and it applies to every state/contract storage read, block and receipt set retrieval. If many requests are made sequentially to perform an operation, it may result in a slow response time for the user. Running API functions in parallel whenever possible can greatly improve performance.
Full clients employ a socalled “MIP mapped” bloom filter to find events quickly in a long list of blocks so that it is reasonably cheap to search for certain events in the entire block history. Unfortunately, using a MIPmapped filter is not easy to do with a light client, as searches are only performed in individual headers, which is a lot slower. Searching a few days’ worth of block history usually returns after an acceptable amount of time, but at the moment you should not search for anything in the entire history because it will take an extremely long time.
Here is the good news: a light client does not need a big database since it can retrieve anything on demand. With garbage collection enabled (which scheduled to be implemented), the database will function more like a cache, and a light client will be able to run with as low as 10Mb of storage space. Note that the current Geth implementation uses around 200Mb of memory, which can probably be further reduced. Bandwidth requirements are also lower when the client is not used heavily. Bandwidth used is usually well under 1Mb/hour when running idle, with an additional 23kb for an average state/storage request.
Sometimes it is unnecessary to pass data back and forth multiple times between the client and the server in order to evaluate a function. It would be possible to execute functions on the server side, then collect all the Merkle proofs proving every piece of state data the function accessed and return all the proofs at once so that the client can rerun the code and verify the proofs. This method can be used for both readonly functions of the contracts as well as any applicationspecific code that operates on the blockchain/state as an input.
One of the main limitations we are working to improve is the slow search speed of log histories. Many of the limitations mentioned above, including the difficulty of obtaining MIPmapped bloom filters, follow the same pattern: the server (which is a full node) can easily calculate a certain piece of information, which can be shared with the light clients. But the light clients currently have no practical way of checking the validity of that information, since verifying the entire calculation of the results directly would require so much processing power and bandwidth, which would make using a light client pointless.
Fortunately there is a safe and trustless solution to the general task of indirectly validating remote calculations based on an input dataset that both parties assume to be available, even if the receiving party does not have the actual data, only its hash. This is the exact the case in our scenario where the Ethereum blockchain itself can be used as an input for such a verified calculation. This means it is possible for light clients to have capabilities close to that of full nodes because they can ask a light server to remotely evaluate an operation for them that they would not be able to otherwise perform themselves. The details of this feature are still being worked out and are outside the scope of this document, but the general idea of the verification method is explained by Dr. Christian Reitwiessner in this Devcon 2 talk.
Complex applications accessing huge amounts of contract storage can also benefit from this approach by evaluating accessor functions entirely on the server side and not having to download proofs and reevaluate the functions. Theoretically it would also be possible to use indirect verification for filtering events that light clients could not watch for otherwise. However, in most cases generating proper logs is still simpler and more efficient.
By,Péter Szilágyi
To provide Ethereum integration for your mobile applications, the very first thing you should be interested in doing is account management.
Although all current leading Ethereum implementations provide account management built in, it is ill advised to keep accounts in any location that is shared between multiple applications and/or multiple people. The same way you do not entrust your ISP (who is after all your gateway into the internet) with your login credentials; you should not entrust an Ethereum node (who is your gateway into the Ethereum network) with your credentials either.
The proper way to handle user accounts in your mobile applications is to do client side account management, everything selfcontained within your own application. This way you can ensure as fine grained (or as coarse) access permissions to the sensitive data as deemed necessary, without relying on any third party application's functionality and/or vulnerabilities.
To support this, goethereum
provides a simple, yet
thorough accounts library that gives you all the tools to do properly
secured account management via encrypted keystores and passphrase
protected accounts. You can leverage all the security of the goethereum
crypto implementation while at the same time running everything in your own application.
Although handling your users' accounts locally on their own mobile device does provide certain security guarantees, access keys to Ethereum accounts should never lay around in cleartext form. As such, we provide an encrypted keystore that provides the proper security guarantees for you without requiring a thorough understanding from your part of the associated cryptographic primitives.
The important thing to know when using the encrypted keystore is that the cryptographic primitives used within can operate either in standard or light mode. The former provides a higher level of security at the cost of increased computational burden and resource consumption:
As such, light is more suitable for mobile applications, but you should be aware of the tradeoffs nonetheless.
For those interested in the cryptographic and/or implementation details, the keystore uses the secp256k1
elliptic curve as defined in the Standards for Efficient Cryptographylibsecp256k
library and wrapped by Web3 Secret Storage format.
Keystores on Android (Java)
The encrypted keystore on Android is implemented by the AccountManager
class from the org.ethereum.geth
package. The configuration constants (for the standard or light security modes described above) are located in the Geth
abstract class, similarly from the org.ethereum.geth
package. Hence to do client side account management on Android, you'll need to import two classes into your Java code:
import org.ethereum.geth.AccountManager;
import org.ethereum.geth.Geth;
Afterwards you can create a new encrypted account manager via:
AccountManager am = new AccountManager("/path/to/keystore", Geth.LightScryptN, Geth.LightScryptP);
The path to the keystore folder needs to be a location that is
writable by the local mobile application but nonreadable for other
installed applications (for security reasons obviously), so we'd
recommend placing it inside your app's data directory. If you are
creating the AccountManager
from within a class extending an Android object, you will most probably have access to the Context.getFilesDir()
method via this.getFilesDir()
, so you could set the keystore path to this.getFilesDir() + "/keystore"
.
The last two arguments of the AccountManager
constructor
are the crypto parameters defining how resourceintensive the keystore
encryption should be. You can choose between Geth.StandardScryptN, Geth.StandardScryptP
, Geth.LightScryptN, Geth.LightScryptP
or specify your own numbers (please make sure you understand the underlying cryptography for this). We recommend using the light version.
Keystores on iOS (Swift 3)
The encrypted keystore on iOS is implemented by the GethAccountManager
class from the Geth
framework. The configuration constants (for the standard or light
security modes described above) are located in the same namespace as
global variables. Hence to do client side account management on iOS,
you'll need to import the framework into your Swift code:
import Geth
Afterwards you can create a new encrypted account manager via:
let am = GethNewAccountManager("/path/to/keystore", GethLightScryptN, GethLightScryptP);
The path to the keystore folder needs to be a location that is
writable by the local mobile application but nonreadable for other
installed applications (for security reasons obviously), so we'd
recommend placing it inside your app's document directory. You should be
able to retrieve the document directory via let datadir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
, so you could set the keystore path to datadir + "/keystore"
.
The last two arguments of the GethNewAccountManager
factory method are the crypto parameters defining how resourceintensive
the keystore encryption should be. You can choose between GethStandardScryptN, GethStandardScryptP
, GethLightScryptN, GethLightScryptP
or specify your own numbers (please make sure you understand the underlying cryptography for this). We recommend using the light version.
Account lifecycle
Having created an encrypted keystore for your Ethereum accounts, you
can use this account manager for the entire account lifecycle
requirements of your mobile application. This includes the basic
functionality of creating new accounts and deleting existing ones; as
well as the more advanced functionality of updating access credentials,
exporting existing accounts, and importing them on another device.
Although the keystore defines the encryption strength it uses to
store your accounts, there is no global master password that can grant
access to all of them. Rather each account is maintained individually,
and stored on disk in its encrypted format individually, ensuring a much cleaner and stricter separation of credentials.
This individuality however means that any operation requiring access
to an account will need to provide the necessary authentication
credentials for that particular account in the form of a passphrase:
 When creating a new account, the caller must supply a passphrase to
encrypt the account with. This passphrase will be required for any
subsequent access, the lack of which will forever forfeit using the
newly created account.
 When deleting an existing account, the caller must supply a
passphrase to verify ownership of the account. This isn't
cryptographically necessary, rather a protective measure agaist
accidental loss of accounts.
 When updating an existing account, the caller must supply both
current and new passphrases. After completing the operation, the account
will not be accessible via the old passphrase any more.
 When exporting an existing account, the caller must supply both the
current passphrase to decrypt the account, as well as an export
passphrase to reencrypt it with before returning the keyfile to the
user. This is required to allow moving accounts between devices without
sharing original credentials.
 When importing a new account, the caller must supply both the
encryption passphrase of the keyfile being imported, as well as a new
passhprase with which to store the account. This is required to allow
storing account with different credentials than used for moving them
around.
Please note, there is no recovery mechanisms for losing the
passphrases. The cryptographic properties of the encrypted keystore (if
using the provided parameters) guarantee that account credentials cannot
be brute forced in any meaningful time.
Accounts on Android (Java)
An Ethereum account on Android is implemented by the Account
class from the org.ethereum.geth
package. Assuming we already have an instance of an AccountManager
called am
from the previous section, we can easily execute all of the described lifecycle operations with a handful of function calls.
// Create a new account with the specified encryption passphrase.
Account newAcc = am.newAccount("Creation password");
// Export the newly created account with a different passphrase. The returned
// data from this method invocation is a JSON encoded, encrypted keyfile.
byte[] jsonAcc = am.exportKey(newAcc, "Creation password", "Export password");
// Update the passphrase on the account created above inside the local keystore.
am.updateAccount(newAcc, "Creation password", "Update password");
// Delete the account updated above from the local keystore.
am.deleteAccount(newAcc, "Update password");
// Import back the account we've exported (and then deleted) above with yet
// again a fresh passphrase.
Account impAcc = am.importKey(jsonAcc, "Export password", "Import password");
Although instances of Account
can be used to access
various information about specific Ethereum accounts, they do not
contain any sensitive data (such as passphrases or private keys), rather
act solely as identifiers for client code and the keystore.
Accounts on iOS (Swift 3)
An Ethereum account on iOS is implemented by the GethAccount
class from the Geth
framework. Assuming we already have an instance of an GethAccountManager
called am
from the previous section, we can easily execute all of the described lifecycle operations with a handful of function calls.
// Create a new account with the specified encryption passphrase.
let newAcc = try! am?.newAccount("Creation password")
// Export the newly created account with a different passphrase. The returned
// data from this method invocation is a JSON encoded, encrypted keyfile.
let jsonKey = try! am?.exportKey(newAcc!, passphrase: "Creation password", newPassphrase: "Export password")
// Update the passphrase on the account created above inside the local keystore.
try! am?.update(newAcc, passphrase: "Creation password", newPassphrase: "Update password")
// Delete the account updated above from the local keystore.
try! am?.delete(newAcc, passphrase: "Update password")
// Import back the account we've exported (and then deleted) above with yet
// again a fresh passphrase.
let impAcc = try! am?.importKey(jsonKey, passphrase: "Export password", newPassphrase: "Import password")
Although instances of GethAccount
can be used to
access various information about specific Ethereum accounts, they do not
contain any sensitive data (such as passphrases or private keys),
rather act solely as identifiers for client code and the keystore.
Signing authorization
As mentioned above, account objects do not hold the sensitive private
keys of the associated Ethereum accounts, but are merely placeholders
to identify the cryptographic keys with. All operations that require
authorization (e.g. transaction signing) are performed by the account
manager after granting it access to the private keys.
There are a few different ways one can authorize the account manager
to execute signing operations, each having its advantages and drawbacks.
Since the different methods have wildly different security guarantees,
it is essential to be clear on how each works:

Single authorization: The simplest way to sign a
transaction via the account manager is to provide the passphrase of the
account every time something needs to be signed, which will ephemerally
decrypt the private key, execute the signing operation and immediately
throw away the decrypted key. The drawbacks are that the passphrase
needs to be queried from the user every time, which can become annoying
if done frequently; or the application needs to keep the passphrase in
memory, which can have security consequences if not done properly; and
depending on the keystore's configured strength, constantly decrypting
keys can result in nonnegligible resource requirements.

Multiple authorizations: A more complex way of signing
transactions via the account manager is to unlock the account via its
passphrase once, and allow the account manager to cache the decrypted
private key, enabling all subsequent signing requests to complete
without the passphrase. The lifetime of the cached private key may be
managed manually (by explicitly locking the account back up) or
automatically (by providing a timeout during unlock). This mechanism is
useful for scenarios where the user may need to sign many transactions
or the application would need to do so without requiring user input. The
crucial aspect to remember is that anyone with access to the account manager can sign transactions while a particular account is unlocked (e.g. device left unattended; application running untrusted code).
Note, creating transactions is out of scope here, so the
remainder of this section will assume we already have a transaction hash
to sign, and will focus only on creating a cryptographic signature
authorizing it. Creating an actual transaction and injecting the
authorization signature into it will be covered later.
Signing on Android (Java)
Assuming we already have an instance of an AccountManager
called am
from the previous sections, we can create a new account to sign transactions with via it's already demonstrated newAccount
method; and to avoid going into transaction creation for now, we can hardcode a random Hash
to sign instead.
// Create a new account to sign transactions with
Account signer = am.newAccount("Signer password");
Hash txHash = new Hash("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef");
With the boilerplate out of the way, we can now sign transaction using the authorization methods described above:
// Sign a transaction with a single authorization
byte[] signature = am.signPassphrase(signer, "Signer password", txHash.getBytes());
// Sign a transaction with multiple manually cancelled authorizations
am.unlock(signer, "Signer password");
signature = am.sign(signer.getAddress(), txHash.getBytes());
am.lock(signer.getAddress());
// Sign a transaction with multiple automatically cancelled authorizations
am.timedUnlock(signer, "Signer password", 1000000000); // 1 second in nanoseconds
signature = am.sign(signer.getAddress(), txHash.getBytes());
You may wonder why signPassphrase
takes an Account
as the signer, whereas sign
takes only an Address
. The reason is that an Account
object may also contain a custom keypath, allowing signPassphrase
to sign using accounts outside of the keystore; however sign
relies on accounts already unlocked within the keystore, so it cannot specify custom paths.
Signing on iOS (Swift 3)
Assuming we already have an instance of a GethAccountManager
called am
from the previous sections, we can create a new account to sign transactions with via it's already demonstrated newAccount
method; and to avoid going into transaction creation for now, we can hardcode a random Hash
to sign instead.
// Create a new account to sign transactions with
let signer = try! am?.newAccount("Signer password")
var error: NSError?
let txHash = GethNewHashFromHex("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", &error)
Note, although Swift usually rewrites NSError
returns to throws, this particular instance seems to have been missed
for some reason (possibly due to it being a constructor). It will be
fixed in a later version of the iOS bindings when the appropriate fixed
are implemented upstream in the gomobile
project.
With the boilerplate out of the way, we can now sign transaction using the authorization methods described above:
// Sign a transaction with a single authorization
var signature = try! am?.signPassphrase(signer, passphrase: "Signer password", hash: txHash?.getBytes())
// Sign a transaction with multiple manually cancelled authorizations
try! am?.unlock(signer, passphrase: "Signer password")
signature = try! am?.sign(signer?.getAddress(), hash: txHash?.getBytes())
try! am?.lock(signer?.getAddress())
// Sign a transaction with multiple automatically cancelled authorizations
try! am?.timedUnlock(signer, passphrase: "Signer password", timeout: 1000000000) // 1 second in nanoseconds
signature = try! am?.sign(signer?.getAddress(), hash: txHash?.getBytes())
You may wonder why signPassphrase
takes a GethAccount
as the signer, whereas sign
takes only a GethAddress
. The reason is that a GethAccount
object may also contain a custom keypath, allowing signPassphrase
to sign using accounts outside of the keystore; however sign
relies on accounts already unlocked within the keystore, so it cannot specify custom paths.
What is EDCON?
A: The EDCON (European Ethereum Development Conference) is a conference that will take place in Paris at the Ecole Supérieure de Commerce de Paris  Europe (ESCP) on 1718 February 2017. The conference will cover Ethereum technology and research (PoS, Scalability, Privacy) as well as Ethereumbased applications.
Q: Who is organizing EDCON?
A: EDCON is organized by LinkTime with the support and cooperation of developers from the Ethereum Foundation and the wider Ethereum community, as well as ADETIF, the Ecole Supérieure de Commerce de Paris  Europe (ESCP), the Asseth (French Ethereum, nonprofit), La ChainTech (French blockchain, nonprofit).
Q: What topics will be discussed at EDCON?
A: Talks will cover: * Ethereum baselayer technology * Ethereum research (PoS, scalability) * Privacy (eg. zero knowledge proofs) * Formal verification * Ethereum consortium chain development * Applications being built on Ethereum * Growing the Ethereum community
Q: How do I buy a ticket?
A: There are two types of tickets: standard tickets and VIP tickets. Standard Ticket: Able to attend the Main Conferences, morning community event and activities of Ethereum Community in Subconference. VIP Ticket: 100 Tickets only. Able to attend the Main Conferences, Cocktail Party and activities of Ethereum Community in Subconference. VIPs are able to build deeper connections with core developers, investors and entrepreneurs. Highly recommended for those who want communicate more with core participants. Tickets for the conference are available here: https://edcon.io/register.html.
Vitalik Buterin
Founder of Ethereum
Ming Chan
Ethereum Foundation
Executive Director
Nick Johnson
Ethereum Core Developer
Gavin Wood
Ethcore/Parity founder
Martin Becze
Ethereum Core Developer
Vlad Zamfir
Ethereum Core Researcher
Joseph Chow
Ethereum DeveloperConsenSys
Founder of Ledger Labs
Ethereum State Channels Researcher
Slock It CTO
Ethereum Security Researcher
Alex Beregszaszi
Ethereum Core Developer
Loi Luu
Founder of SmartPool
Heiko Hees
Brainbot/Raiden CEO
Rick Dudley
Ethereum Mechanism Designer
Omise Lab DAPP Architect
Thomas Bertani
Oraclize CEO
Jae Kwon
Founder of Tendermint & Cosmos
Nicolas Bacca
Ledger CTO
Yoichi Hirai
Formal Verification Engineer at Ethereum DEV
Quentin de Beauchesne
Ledgys.net Cofounder
Griff Green
Founder of Giveth
For more Details:https://edcon.io/
https://uquid.com/ethereumdeb...
Ethereum debit card allows you to pay, simply and securely, in person, online, over the phone or through the mail. UQUID account help you loading money into your card, keep track of your spending and balance.
Instant load with 0% fee
We do not require for ID or verification.
You can get unlimited cards with only 1 UQUID account
Our card ships free to 178 + countries with no fees. Typically within 23 working days
You can link your card with your address information. Get easy for shopping at Amazon, Uber, Skrill ...
]]>
Members of the Ethereum R&D team and the Zcash Company are collaborating on a research project addressing the combination of programmability and privacy in blockchains. This joint post is being concurrently posted on the Zcash blog, and is coauthored by Ariel Gabizon (Zcash) and Christian Reitwiessner (Ethereum).
Ethereum’s flexible smart contract interface enables a large variety of applications, many of which have probably not yet been conceived. The possibilities grow considerably when adding the capacity for privacy. Imagine, for example, an election or auction conducted on the blockchain via a smart contract such that the results can be verified by any observer of the blockchain, but the individual votes or bids are not revealed. Another possible scenario may involve selective disclosure where users would have the ability to prove they are in a certain city without disclosing their exact location. The key to adding such capabilities to Ethereum is zeroknowledge succinct noninteractive arguments of knowledge (zkSNARKs) – precisely the cryptographic engine underlying Zcash.
One of the goals of the Zcash company, codenamed Project Alchemy, is to enable a direct decentralized exchange between Ethereum and Zcash. Connecting these two blockchains and technologies, one focusing on programmability and the other on privacy, is a natural way to facilitate the development of applications requiring both.
As part of the Zcash/Ethereum technical collaboration, Ariel Gabizon from Zcash visited Christian Reitwiessner from the Ethereum hub at Berlin a few weeks ago. The highlight of the visit is a proof of concept implementation of a zkSNARK verifier written in Solidity, based on precompiled Ethereum contracts implemented for the Ethereum C++ client. This work complements Baby ZoE , where a zkSNARK precompiled contract was written for Parity (the Ethereum Rust client). The updates we’ve made involved adding tiny cryptographic primitives (elliptic curve multiplication, addition and pairing) and implementing the rest in Solidity, all of which allows for a greater flexibility and enables using a variety of zkSNARK constructions without requiring a hard fork. Details will be shared as they are available later. We tested the new code by successfully verifying a real privacypreserving Zcash transaction on a testnet of the Ethereum blockchain.
The verification took only 42 milliseconds, which shows that such precompiled contracts can be added, and the gas costs for using them can be made to be quite affordable.
The Zcash system can be reused on Ethereum to create shielded custom tokens. Such tokens already allow many applications like voting, (see below) or simple blind auctions where participants make bids without the knowledge of the amounts bid by others.
If you want to try compiling the proof of concept, you can use the following commands. If you need help, see https://gitter.im/ethereum/pri...
git clone https://github.com/sciprlab/libsnark.git cd libsnark sudo PREFIX=/usr/local make NO_PROCPS=1 NO_GTEST=1 NO_DOCS=1 \ CURVE=ALT_BN128 \ FEATUREFLAGS="DBINARY_OUTPUT=1 DMONTGOMERY_OUTPUT=1 \ DNO_PT_COMPRESSION=1" \ lib install cd .. git clone recursive b snark https://github.com/ethereum/cppethereum.git cd cppethereum ./scripts/install_deps.sh && cmake . DEVMJIT=0 DETHASHCL=0 && make eth cd .. git clone recursive b snarks https://github.com/ethereum/solidity.git cd solidity ./scripts/install_deps.sh && cmake . && make soltest cd .. ./cppethereum/eth/eth test d /tmp/test # And on a second terminal: ./solidity/test/soltest t "*/snark"  ipcpath /tmp/test/geth.ipc showmessages
We also discussed various aspects of integrating zkSNARKs into the Ethereum blockchain, upon which we now expand.
Recall that a SNARK is a short proof of some property, and what is needed for adding the privacy features to the Ethereum blockchain are clients that have the ability to verify such a proof.
In all recent constructions, the verification procedure consisted solely of operations on elliptic curves. Specifically, the verifier requires scalar multiplication and addition on an elliptic curve group, and would also require a heavier operation called a bilinear pairing.
As mentioned here, implementing these operations directly in the EVM is too costly. Thus, we would want to implement precompiled contracts that perform these operations. Now, the question debated is: what level of generality should these precompiled contracts aim for.
The security level of the SNARK corresponds to the parameters of the curve. Roughly, the larger the curve order is, and the larger something called the embedding degree is, and the more secure the SNARK based on this curve is. On the other hand, the larger these quantities are, naturally the more costly the operations on the corresponding curve are. Thus, a contract designer using SNARKs may wish to choose these parameters according to their own desired efficiency/security tradeoff. This tradeoff is one reason for implementing a precompiled contract with a high level of generality, where the contract designer can choose from a large family of curves. We indeed began by aiming for a high level of generality, where the description of the curve is given as part of the input to the contract. In such a case, a smart contract would be able to perform addition in any elliptic curve group.
A complication with this approach is assigning gas cost to the operation. Yu must assess, merely from the description of the curve, and with no access to a specific implementation, how expensive a group operation on that curve would be in the worst case. A somewhat less general approach is to allow all curves from a given family. We noticed that when working with the BarretoNaehrig (BN) family of curves, one can assess roughly how expensive the pairing operation will be, given the curve parameters, as all such curves support a specific kind of optimal Ate pairing. Here’s a sketch of how such a precompile would work and how the gas cost would be computed.
We learned a lot from this debate, but ultimately, decided to “keep it simple” for this proof of concept: we chose to implement contracts for the specific curve currently used by Zcash. We did this by using wrappers of the corresponding functions in the libsnark library, which is also used by Zcash.
Note that we could have simply used a wrapper for the entire SNARK verification function currently used by Zcash, as was done in the above mentioned Baby ZoE project. However, the advantage of explicitly defining elliptic curve operations is enabling using a wide variety of SNARK constructions which, again, all have a verifier working by some combination of the three previously mentioned elliptic curve operations.
As you may have heard, using SNARKs requires a complex setup phase in which the socalled public parameters of the system are constructed. The fact that these public parameters need to be generated in a secure way every time we want to use a SNARK for a particular circuit significantly, hinders the usability of SNARKs. Simplifying this setup phase is an important goal that we have given thought to, but haven’t had any success in so far.
The good news is that someone desiring to issue a token supporting privacypreserving transactions can simply reuse the public parameters that have already been securely generated by Zcash. It can be reused because the circuit used to verify privacypreserving transactions is not inherently tied to one currency or blockchain. Rather, one of its explicit inputs is the root of a Merkle tree that contains all the valid notes of the currency. Thus, this input can be changed according to the currency one wishes to work with. Moreover, if it is easy to start a new anonymous token. You can already accomplish many tasks that do not look like tokens at first glance. For example, suppose we wish to conduct an anonymous election to choose a preferred option amongst two. We can issue an anonymous custom token for the vote, and send one coin to each voting party. Since there is no “mining”, it will not be possible to generate tokens any other way. Now each party sends their coin to one of two addresses according to their vote. The address with a larger final balance corresponds to the election result.
A nontokenbased system that is fairly simple to build and allows for “selective disclosure” follows. You can, for example, post an encrypted message in regular intervals, containing your physical location to the blockchain (perhaps with other people’s signatures to prevent spoofing). If you use a different key for each message, you can reveal your location only at a certain time by publishing the key. However, with zkSNARKs you can additionally prove that you were in a certain area without revealing exactly where you were. Inside the zkSNARK, you decrypt your location and check that it is inside the area. Because of the zeroknowledge property, everyone can verify that check, but nobody will be able to retrieve your actual location.
Achieving the mentioned functionalities – creating anonymous tokens and verifying Zcash transactions on the Ethereum blockchain, will require implementing other elements used by Zcash in Solidity.
For the first functionality, we must have an implementation of tasks performed by nodes on the Zcash network such as updating the note commitment tree.
For the second functionality, we need an implementation of the equihash proof of work algorithm used by Zcash in Solidity. Otherwise, transactions can be verified as valid in themselves, but we do not know whether the transaction was actually integrated into the Zcash blockchain.
Fortunately, such an implementation was written; however, its efficiency needs to be improved in order to be used in practical applications.
Acknowledgement: We thank Sean Bowe for technical assistance. We also thank Sean and Vitalik Buterin for helpful comments, and Ming Chan for editing.
Geth v1.5.8 is a patch release to address bugs and annoyances. For a full rundown of the changes please see the 1.5.8 milestone.
Notable changes:
cmd/wnode
, allows testing the Whisper v5 protocol. (#3580)Binaries and mobile libraries are available on our download page.
]]>https://github.com/ethereum/mi...
datadir
of the ethereum node. It's one installer for both 32 and 64bit computers.Note that thedatadir
is set as a parameter in Mist shortcut properties, at the installation stage; not in Mist's preferences.
App Signing: Mist for Mac OS X is now signed by the Ethereum Foundation.
Solidity Compiler: Now featuring version 0.4.8.
Remix IDE option on menu
0.8.9 also has a new menu entry to open Remix IDE, so now you have
plenty of room to write your contracts without leaving Mist. Head to Develop > Open Remix IDE
.
A test suite is born: It was about time for Mist to have a solid set of integration tests. Now we're starting to kill this debt with a Spectron#1571.
See the full changelog at Milestone 0.8.9.
EthereumWalletmacosx089.dmg a244daa82abd4e607672dc375e5b5060266104f81f12045e199265e92655c8c3 EthereumWalletlinux32089.deb 0d37b4710b6eab39467df4dd3587c693c40f54cae919e815693cb14c92836586 EthereumWalletlinux32089.zip 9b61e43c0ec1655de04382f67c99f518cf854bc57f89cd7a63d9d93752723d01 EthereumWalletlinux64089.deb 53c6a839859c5ba824fbaff427326e05e6b238d05387ff61a83041e9bfb81dfc EthereumWalletlinux64089.zip 2ee9a5d3ac0a4eb944f9d397392a77e7fda45439ae787e13684bdef58d29b538 EthereumWalletwin32089.zip 7df2f1e8ba097aefe65fe8310024e61ccecc6b91cf34f916d38f396c1ff37fb0 EthereumWalletwin64089.zip a46f09c1b63e63c8e42fea96bc184dc508381cfe29672c6417d37230966a6493
mistinstaller089.exe 959bbe051f63f3a4e2336b69308e9b6a5e8564b68ae361c3aad3d55cb03e6ee3 Mistlinux32089.deb 97b2ee47159bf32772fe21704f72333d0a597181282ec546f43494546f48e417 Mistlinux32089.zip ab62752d235bafc878bd68e461be45c6d45d7d746883c6b3b79fdddf4ea1c15b Mistlinux64089.deb 9657a9261e25173087eda29499db88aed7adcb4344ead914eaa692093c55ba62 Mistlinux64089.zip 2d19445afc242b6337c5681627b9a21aca5ba5b7aa60cc7ba683e2f5d9bea6bb Mistmacosx089.dmg 3d09306f8e53e315da73571d52adf15adfd4c30e43a8b4251099bc5f7aeda986]]>