From 6aa91b115f5e23a3766ebeb4dfc55d0c52f49bd4 Mon Sep 17 00:00:00 2001 From: Chetan Sarva Date: Mon, 14 Nov 2016 19:23:29 -0500 Subject: [PATCH] Rewrite of main readme; detailed docs moved to docs/ folder --- BUILDING.md | 18 ++ README.md | 368 ++++++++------------------------------ docs/README.md | 8 + docs/api.md | 90 ++++++++++ docs/design.md | 65 +++++++ docs/img/architecture.png | Bin 0 -> 84557 bytes docs/privacy.md | 24 +++ docs/running.md | 145 +++++++++++++++ 8 files changed, 422 insertions(+), 296 deletions(-) create mode 100644 BUILDING.md create mode 100644 docs/README.md create mode 100644 docs/api.md create mode 100644 docs/design.md create mode 100644 docs/img/architecture.png create mode 100644 docs/privacy.md create mode 100644 docs/running.md diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 000000000..80c059cac --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,18 @@ + +# Building Quorum + +Clone the repository and build the source: + +``` +git clone https://github.com/jpmorganchase/quorum.git +cd quorum +make all +``` + +Binaries are placed within `$REPO_ROOT/build/bin`. + +Run the tests: + +``` +make test +``` diff --git a/README.md b/README.md index 430564309..eaa569848 100644 --- a/README.md +++ b/README.md @@ -1,341 +1,117 @@ # Quorum -Quorum is a blockchain with properties that make it suitable as a consortium or private chain. -One of its core features is the ability to keep certain state private and only accessible by granted parties. +Quorum is an Ethereum-based distributed ledger protocol that has been developed to provide the Financial Services industry with a permissioned implementation of Ethereum that supports transaction and contract privacy. -## Consensus algorithm +The key components are: -Quorum is a majority voting protocol where a subset of nodes within the network are given the `voting` role. -The voting role allows a node to vote which block should be the canonical head on a particular height. -The block with the most votes will win and is considered the canonical head of the chain. +* __QuorumChain__ - a new consensus model based on majority voting +* __Constellation__ - a peer-to-peer encrypted message exchange +* __Peer Security__ - node/peer permissioning using Smart Contracts -Block creation is only allowed by nodes with the `block maker` role. -A node with this role can create a block, sign the block and put the signature within in `ExtraData` field of the block. -On block import nodes can verify if the block was signed by one of the nodes that have the `block maker` role. +## Architecture -Nodes can be given no role, one of the roles or both roles through command line arguments. -The collection of addresses with special roles is tracked within the Quorum smart contract. +![Quorum privacy architecture](docs/img/architecture.png) -Quorum is implemented in a smart contract pre-deployed on address `0x0000000000000000000000000000000000000020` and can be found [here](https://github.com/jpmorganchase/quorum/blob/master/core/quorum/block_voting.sol). -Voters and block makers can be added or removed and the minimum number of votes before a block is selected as winner can be configured. +The above diagram is a high-level overview of the privacy architecture used by Quorum. For more in-depth discussion of the components, refer to the wiki pages. -## State +## Quickstart -Quorum supports dual state: +The quickest way to get started with Quorum is using [VirtualBox](https://www.virtualbox.org/wiki/Downloads) and [Vagrant](https://www.vagrantup.com/downloads.html). Once you have both installed, run the following: -- public state, accessible by all nodes within the network -- private state, only accessible by nodes with the correct permissions - -The difference is made through the use of transactions with encrypted (private) and non-encrypted payload (public) transactions. -Nodes can determine if a transaction is private by looking at the V value of the signature. -Public transactions have a V value of 27 or 28, private transactions have a value of 37 or 38. - -If the transaction is private and the node has the ability to decrypt the payload it can execute the transaction. -Nodes who are not involved in the transaction cannot decrypt the payload and process the transaction. -As a result all nodes share a common public state which is created through public transactions and have a local unique private state. - -This model imposes a restriction in the ability to modify state in private transactions. -Since its a common use case that a (private) contract reads data from a public contract the virtual machine has the ability to jump into read only mode. -For each call from a private contract to a public contract the virtual machine will change to read only mode. -If the virtual machine is in read only mode and the code tries to make a stage change the virtual machine stops execution and throws an exception. - -The following transactions are allowed: - -S: sender, (X): private, X: public, ->: direction, []: read only mode -``` -1. S -> A -> B -2. S -> (A) -> (B) -3. S -> (A) -> [B -> C] -``` -The following transaction are unsupported: - -``` -1. (S) -> A -2. (S) -> (A) +```sh +git clone https://github.com/jpmorganchase/quorum-examples +cd quorum-examples/vagrant +vagrant up +# (should take 5 or so minutes) +vagrant ssh ``` -### State verification +Now that you have a fully-functioning Quorum environment set up, let's run the 7-node cluster example. This will spin up several nodes with a mix of voters, block makers, and unprivileged nodes. -To determine if nodes are in sync the public state root hash is included in the block. -Since private transactions can only be processed by nodes that are involved its impossible to get global consensus on the private state. -To overcome this issue the RPC method `eth_storageRoot(address[, blockNumber]) -> hash` can be used. -It returns the storage root for the given address at an (optional) block number. -If the optional block number is not given the latest block number is used. -The storage root hash can be on or off chain compared by the parties involved. +```sh +# (from within vagrant env, use `vagrant ssh` to enter) +ubuntu@ubuntu-xenial:~$ cd quorum-examples/7nodes -## Building Quorum +$ ./init.sh +# (output condensed for clarity) +[*] Cleaning up temporary data directories +[*] Configuring node 1 +[*] Configuring node 2 as block maker and voter +[*] Configuring node 3 +[*] Configuring node 4 as voter +[*] Configuring node 5 as voter +[*] Configuring node 6 +[*] Configuring node 7 -Clone the repository and build the source: - -``` -git clone https://github.com/jpmorganchase/quorum.git -cd quorum -make all +$ ./start.sh +[*] Starting Constellation nodes +[*] Starting bootnode +wait for bootnode to start... +[*] Starting node 1 +[*] Starting node 2 +[*] Starting node 3 +[*] Starting node 4 +[*] Starting node 5 +[*] Starting node 6 +[*] Starting node 7 +[*] Unlocking account and sending first transaction +Contract transaction send: TransactionHash: 0x5828de9bf1c11d0db7cde96337c3c4d678da93a9040ac0790d38518e5f8c072d waiting to be mined... +true ``` -Binaries are placed within `$REPO_ROOT/build/bin`. +We now have a 7-node Quorum cluster with a [private smart contract](https://github.com/jpmorganchase/quorum-examples/blob/master/7nodes/script1.js) (SimpleStorage) sent from `node1` to `node7` (denoted by the public key `ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc=`). -Run the tests: +Connect to any of the nodes and inspect them using the following commands: -``` -make test -``` +```sh +geth attach ipc:qdata/dd1/geth.ipc +geth attach ipc:qdata/dd2/geth.ipc +... +geth attach ipc:qdata/dd7/geth.ipc -## Running Quorum -Describing all command line arguments it out of the scope of this document. They can be viewed with: `geth --help`. +# e.g. -### Initialize chain +$ geth attach ipc:qdata/dd2/geth.ipc +Welcome to the Geth JavaScript console! -The first step is to generate the genesis block. +instance: Geth/v1.5.0-unstable/linux/go1.7.3 +coinbase: 0xca843569e3427144cead5e4d5999a3d0ccf92b8e +at block: 679 (Tue, 15 Nov 2016 00:01:05 UTC) + datadir: /home/ubuntu/quorum-examples/7nodes/qdata/dd2 + modules: admin:1.0 debug:1.0 eth:1.0 net:1.0 personal:1.0 quorum:1.0 rpc:1.0 txpool:1.0 web3:1.0 -``` -geth init genesis.json -``` - -The genesis block should include the Quorum voting contract address `0x0000000000000000000000000000000000000020`. -The code can be generated with [browser solidity](http://ethereum.github.io/browser-solidity/#version=soljson-latest.js) (note, use the runtime code) or using the solidity compiler `solc --optimize --bin-runtime block_voting.sol`. - -The `7nodes` directory in the `quorum-examples` repository contains several keys (using an empty password) that are used in the example genesis file: -``` -key1 vote key 1 -key2 vote key 2 -key3 vote key 3 -key4 block maker 1 -key5 block maker 2 -``` - -Example genesis file: -``` -{ - "alloc": { - "0x0000000000000000000000000000000000000020": { - "code": "606060405236156100c45760e060020a60003504631290948581146100c9578063284d163c146100f957806342169e4814610130578063488099a6146101395780634fe437d514610154578063559c390c1461015d57806368bb8bb61461025d57806372a571fc146102c857806386c1ff681461036957806398ba676d146103a0578063a7771ee31461040b578063adfaa72e14610433578063cf5289851461044e578063de8fa43114610457578063e814d1c71461046d578063f4ab9adf14610494575b610002565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c45760018190555b50565b610548600435600160a060020a03331660009081526005602052604090205460ff16156100c4576004546001141561055e57610002565b61045b60025481565b61054a60043560056020526000908152604090205460ff1681565b61045b60015481565b61045b60043560006000600060006000600050600186038154811015610002579080526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630192505b60018301548110156105d75760018301805484916000918490811015610002576000918252602080832090910154835282810193909352604091820181205485825292869052205410801561023257506001805490840180548591600091859081101561000257906000526020600020900160005054815260208101919091526040016000205410155b156102555760018301805482908110156100025760009182526020909120015491505b6001016101a8565b610548600435602435600160a060020a03331660009081526003602052604081205460ff16156100c4578054839010156105e45780548084038101808355908290829080158290116105df576002028160020283600052602060002091820191016105df919061066b565b610548600435600160a060020a03331660009081526005602052604090205460ff16156100c457600160a060020a0381166000908152604090205460ff1615156100f65760406000819020805460ff191660019081179091556004805490910190558051600160a060020a038316815290517f1a4ce6942f7aa91856332e618fc90159f13a340611a308f5d7327ba0707e56859181900360200190a16100f6565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c4576002546001141561071457610002565b61045b600435602435600060006000600050600185038154811015610002579080526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630181509050806001016000508381548110156100025750825250602090200154919050565b61054a600435600160a060020a03811660009081526003602052604090205460ff165b919050565b61054a60043560036020526000908152604090205460ff1681565b61045b60045481565b6000545b60408051918252519081900360200190f35b61054a600435600160a060020a03811660009081526005602052604090205460ff1661042e565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c457600160a060020a03811660009081526003602052604090205460ff1615156100f65760406000818120600160a060020a0384169182905260036020908152815460ff1916600190811790925560028054909201909155825191825291517f0ad2eca75347acd5160276fe4b5dad46987e4ff4af9e574195e3e9bc15d7e0ff929181900390910190a16100f6565b005b604080519115158252519081900360200190f35b600160a060020a03811660009081526005602052604090205460ff16156100f65760406000819020805460ff19169055600480546000190190558051600160a060020a038316815290517f8cee3054364d6799f1c8962580ad61273d9d38ca1ff26516bd1ad23c099a60229181900360200190a16100f6565b509392505050565b505050505b60008054600019850190811015610002578382526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563016020819052604082205490925014156106b8578060010160005080548060010182818154818355818115116106a5578183600052602060002091820191016106a5919061068d565b50506002015b808211156106a157600181018054600080835591825260208220610665918101905b808211156106a1576000815560010161068d565b5090565b5050506000928352506020909120018290555b600082815260208281526040918290208054600101905581514381529081018490528151600160a060020a033316927f3d03ba7f4b5227cdb385f2610906e5bcee147171603ec40005b30915ad20e258928290030190a2505050565b600160a060020a03811660009081526003602052604090205460ff16156100f65760406000819020805460ff19169055600280546000190190558051600160a060020a038316815290517f183393fc5cffbfc7d03d623966b85f76b9430f42d3aada2ac3f3deabc78899e89181900360200190a16100f656", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x02", - - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x04", - "0x29ecdbdf95c7f6ceec92d6150c697aa14abeb0f8595dd58d808842ea237d8494": "0x01", - "0x6aa118c6537572d8b515a9f9154be55a3377a8de7991cd23bf6e5ceb368688e3": "0x01", - "0x50793743212c6f01d326957d7069005b912f8215f10c7536be6b10782c6c44cd": "0x01", - "0x38f6c908c5cc7ca668cec2f476abe61b4dbb1df20f0ad8e07ef5dbf6a2f1ffd4": "0x01", - - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x02", - "0xaca3b76ed4968740c3180dd7fa37f4aa229a2c758a848f53920e9ccb4c4bb74e": "0x01", - "0xd188ba2dc293670542c1befaf7678b0859e5354a0727d1188b2afb6f47fe24d1": "0x01" - } - }, - "0xed9d02e382b34818e88b88a309c7fe71e65f419d": { - "balance": "1000000000000000000000000000" - }, - "0xca843569e3427144cead5e4d5999a3d0ccf92b8e": { - "balance": "1000000000000000000000000000" - }, - "0x0fbdc686b912d7722dc86510934589e0aaf3b55a": { - "balance": "1000000000000000000000000000" - }, - "0x9186eb3d20cbd1f5f992a950d808c4495153abd5": { - "balance": "1000000000000000000000000000" - }, - "0xed9d02e382b34818e88b88a309c7fe71e65f419d": { - "balance": "1000000000000000000000000000" - }, - "0x0638e1574728b6d862dd5d3a3e0942c3be47d996": { - "balance": "1000000000000000000000000000" - } - }, - "coinbase": "0x0000000000000000000000000000000000000000", - "config": { - "homesteadBlock": 0 - }, - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2FEFD800", - "mixhash": "0x00000000000000000000000000000000000000647572616c65787365646c6578", - "nonce": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x00" -} -``` - -The storage key for voters and block makers is calculated with `web3.sha3(<256 bit aligned key value> + <256 bit variable index>)`. -The console can be used to calculate the storage key, in this case for vote key 1: -``` -> key = "000000000000000000000000ed9d02e382b34818e88b88a309c7fe71e65f419d" + "0000000000000000000000000000000000000000000000000000000000000003" -"000000000000000000000000ed9d02e382b34818e88b88a309c7fe71e65f419d0000000000000000000000000000000000000000000000000000000000000003" -> web3.sha3(key, {"encoding": "hex"}) -"0x29ecdbdf95c7f6ceec92d6150c697aa14abeb0f8595dd58d808842ea237d8494" -``` - -The `genesis.json` file can be found in the `7nodes` folder in the `quorum-examples` repository. - -### Start node - -Starting a node is as simple as `geth`. This will start the node without any of the roles and makes the node a spectator. - -### Voting role - -Start a node with the voting role: - -``` -geth --voteaccount 0xed9d02e382b34818e88b88a309c7fe71e65f419d -``` - -Optionally the `--votepassword` can be used to unlock the account. -If this flag is omitted the node will prompt for the password. - -### Block maker role - -Start a node with the block maker role: -``` -geth --blockmakeraccount 0x9186eb3d20cbd1f5f992a950d808c4495153abd5 -``` - -Created blocks will be signed with this account. - -Optionally the `--blockmakerpassword` can be used to unlock the account. -If this flag is omitted the node will prompt for the password. - -## Setup multi-node network - -Quorum comes with several scripts to setup a private test network with 7 nodes: - -* node 1, has no special roles -* node 2, has the block maker role -* node 3, has no special roles -* node 4, has the voting role -* node 5, has the voting role -* node 6, has no special roles - -All scripts can be found in the `7nodes` folder in the `quorum-examples` repository. - -1. Step 1, run `init.sh` and initialize data directories (change variables accordingly) -2. Step 2, start nodes with `start.sh` (change variables accordingly) -3. Step 3, stop network with `stop.sh` - -### API - -Quorum provides an API to inspect the current state of the voting contract. - -$ quorum.nodeInfo returns the quorum capabilities of this node. -Example output for a node that is configured as block maker and voter: -``` > quorum.nodeInfo { - blockMakerAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d", + blockMakerAccount: "0xca843569e3427144cead5e4d5999a3d0ccf92b8e", blockmakestrategy: { - maxblocktime: 6, + maxblocktime: 10, minblocktime: 3, status: "active", type: "deadline" }, canCreateBlocks: true, canVote: true, - voteAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d" + voteAccount: "0x0fbdc686b912d7722dc86510934589e0aaf3b55a" } ``` -$ quorum.vote accepts a block hash and votes for this hash to be the canonical head on the current height. It returns the tx hash. -``` -> quorum.vote(eth.getBlock("latest").hash) -"0x16c69b9bdf9f10c64e65dbfe50bc997d2bc1ed321c6041db602908b7f6cab2a9" -``` +## Further Reading -$ quorum.canonicalHash accepts a block height and returns the canonical hash for that height (+1 will return the hash where the current pending block will be based on top of). -``` -> quorum.canonicalHash(eth.blockNumber+1) -"0xf2c8a36d0c54c7013246fddebfc29bc881f6f10f74f761d511b5ebfaa103adfa" -``` +Further documentation can be found in the [docs](docs/) folder and on the [wiki](https://github.com/jpmorganchase/quorum/wiki/). -$ quorum.isVoter accepts an address and returns an indication if the given address is allowed to vote for new blocks -``` -> quorum.isVoter("0xed9d02e382b34818e88b88a309c7fe71e65f419d") -true -``` +## See also -$ quorum.isBlockMaker accepts an address and returns an indication if the given address is allowed to make blocks -``` -> quorum.isBlockMaker("0xed9d02e382b34818e88b88a309c7fe71e65f419d") -true -``` +* Quorum - https://github.com/jpmorganchase/quorum (this repository) +* Constellation - https://github.com/jpmorganchase/constellation +* quorum-examples - https://github.com/jpmorganchase/quorum-examples +* Quorum Wiki - https://github.com/jpmorganchase/quorum/wiki -$ quorum.makeBlock() orders the node to create a block bypassing block maker strategy. -``` -> quorum.makeBlock() -"0x3a07e82a48ab3c19a3d09d247e189e3a3041d1d9eafd2e1515b4ddd5b016bfd9" -``` +## Contributing -$ quorum.pauseBlockMaker (temporary) orders the node to stop creating blocks -``` -> quorum.pauseBlockMaker() -null -> quorum.nodeInfo -{ - blockMakerAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d", - blockmakestrategy: { - maxblocktime: 6, - minblocktime: 3, - status: "paused", - type: "deadline" - }, - canCreateBlocks: true, - canVote: true, - voteAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d" -} -``` +Thank you for your interest in contributing to Quorum! -$ quorum.resumeBlockMaker instructs the node stop begin creating blocks again when its paused. -``` -> quorum.resumeBlockMaker() -null -> quorum.nodeInfo -{ - blockMakerAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d", - blockmakestrategy: { - maxblocktime: 6, - minblocktime: 3, - status: "active", - type: "deadline" - }, - canCreateBlocks: true, - canVote: true, - voteAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d" -} -``` - -## Sending Private Transactions - -To send a private transaction, a PrivateTransactionManager must be configured. This is the -service which transfers private payloads to their intended recipients, performing -encryption and related operations in the process. - -Currently, `constellation` is supported out of the box via the PRIVATE_CONFIG environment -variable (please note that this integration method will change in the near future.) See the -`7nodes` folder in the `quorum-examples` repository for a complete example of how to use it. -The transaction sent in `script1.js` is private for node 7's PrivateTransactionManager -public key. - -Once `constellation` is launched and PRIVATE_CONFIG points to a valid configuration file, -a `SendTransaction` call can be made private by specifying the `privateFor` argument. -`privateFor` is a list of public keys of the intended recipients. (Note that in the case of -`constellation`, this public key is distinct from Ethereum account keys.) When a transaction -is private, the transaction contents will be sent to the PrivateTransactionManager and the -identifier returned will be placed in the transaction instead. When other Quorum nodes -receive a private transaction, they will query their PrivateTransactionManager for the -identifier and replace the transaction contents with the result (if any; nodes which are -not party to a transaction will not be able to retrieve the original contents.) - -## Command line flags -``` -QUORUM OPTIONS: - --voteaccount value Address that is used to vote for blocks - --votepassword value Password to unlock the voting address - --blockmakeraccount value Address that is used to create blocks - --blockmakerpassword value Password to unlock the block maker address - --singleblockmaker Indicate this node is the only node that can create blocks - --minblocktime value Set minimum block time (default: 3) - --maxblocktime value Set max block time (default: 10) -``` +Quorum is built on open source and we fully intend to accept public contributions in the near future. There are many ways to contribute, and we appreciate all of them, so stay tuned to this space. ## License diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..6f40ad02a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,8 @@ + +# Quorum documentation + +* [Whitepaper](./whitepaper.pdf) (PDF) - Quroum Whitepaper +* [Design](./design.md) - Quorum design overview +* [Privacy](./privacy.md) - Sending private transactions +* [Running](./running.md) - Detailed instructions for running Quorum nodes (see also [Constellation](https://github.com/jpmorganchase/constellation)) +* [API](./api.md) - new APIs for interacting with QuorumChain consensus diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 000000000..057a87138 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,90 @@ + +# API + +Quorum provides an API to inspect the current state of the voting contract. + +$ quorum.nodeInfo returns the quorum capabilities of this node. +Example output for a node that is configured as block maker and voter: +``` +> quorum.nodeInfo +{ + blockMakerAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d", + blockmakestrategy: { + maxblocktime: 6, + minblocktime: 3, + status: "active", + type: "deadline" + }, + canCreateBlocks: true, + canVote: true, + voteAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d" +} +``` + +$ quorum.vote accepts a block hash and votes for this hash to be the canonical head on the current height. It returns the tx hash. +``` +> quorum.vote(eth.getBlock("latest").hash) +"0x16c69b9bdf9f10c64e65dbfe50bc997d2bc1ed321c6041db602908b7f6cab2a9" +``` + +$ quorum.canonicalHash accepts a block height and returns the canonical hash for that height (+1 will return the hash where the current pending block will be based on top of). +``` +> quorum.canonicalHash(eth.blockNumber+1) +"0xf2c8a36d0c54c7013246fddebfc29bc881f6f10f74f761d511b5ebfaa103adfa" +``` + +$ quorum.isVoter accepts an address and returns an indication if the given address is allowed to vote for new blocks +``` +> quorum.isVoter("0xed9d02e382b34818e88b88a309c7fe71e65f419d") +true +``` + +$ quorum.isBlockMaker accepts an address and returns an indication if the given address is allowed to make blocks +``` +> quorum.isBlockMaker("0xed9d02e382b34818e88b88a309c7fe71e65f419d") +true +``` + +$ quorum.makeBlock() orders the node to create a block bypassing block maker strategy. +``` +> quorum.makeBlock() +"0x3a07e82a48ab3c19a3d09d247e189e3a3041d1d9eafd2e1515b4ddd5b016bfd9" +``` + +$ quorum.pauseBlockMaker (temporary) orders the node to stop creating blocks +``` +> quorum.pauseBlockMaker() +null +> quorum.nodeInfo +{ + blockMakerAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d", + blockmakestrategy: { + maxblocktime: 6, + minblocktime: 3, + status: "paused", + type: "deadline" + }, + canCreateBlocks: true, + canVote: true, + voteAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d" +} +``` + +$ quorum.resumeBlockMaker instructs the node stop begin creating blocks again when its paused. +``` +> quorum.resumeBlockMaker() +null +> quorum.nodeInfo +{ + blockMakerAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d", + blockmakestrategy: { + maxblocktime: 6, + minblocktime: 3, + status: "active", + type: "deadline" + }, + canCreateBlocks: true, + canVote: true, + voteAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d" +} +``` diff --git a/docs/design.md b/docs/design.md new file mode 100644 index 000000000..29bb431c0 --- /dev/null +++ b/docs/design.md @@ -0,0 +1,65 @@ + +# Design + +## Consensus algorithm + +Quorum introduces a new consensus algorithm called QuorumChain, a majority +voting protocol where a subset of nodes within the network are given the +`voting` role. The voting role allows a node to vote on which block should be the +canonical head at a particular height. The block with the most votes will win +and is considered the canonical head of the chain. + +Block creation is only allowed by nodes with the `block maker` role. +A node with this role can create a block, sign the block and put the signature within the `ExtraData` field of the block. +On `block import`, nodes can verify if the block was signed by one of the nodes that have the `block maker` role. + +Nodes can be given no role, one of the roles or both roles through command line arguments. +The collection of addresses with special roles is tracked within the Quorum smart contract. + +Quorum is implemented in a smart contract pre-deployed on address `0x0000000000000000000000000000000000000020` and can be found [here](https://github.com/jpmorganchase/quorum/blob/master/core/quorum/block_voting.sol). +Voters and block makers can be added or removed and the minimum number of votes before a block is selected as winner can be configured. + + +## Public/Private State + +Quorum supports dual state: + +- public state, accessible by all nodes within the network +- private state, only accessible by nodes with the correct permissions + +The difference is made through the use of transactions with encrypted (private) and non-encrypted payloads (public). +Nodes can determine if a transaction is private by looking at the V value of the signature. +Public transactions have a V value of 27 or 28, private transactions have a value of 37 or 38. + +If the transaction is private and the node has the ability to decrypt the payload it can execute the transaction. +Nodes who are not involved in the transaction cannot decrypt the payload and process the transaction. +As a result all nodes share a common public state which is created through public transactions and have a local unique private state. + +This model imposes a restriction in the ability to modify state in private transactions. +Since its a common use case that a (private) contract reads data from a public contract the virtual machine has the ability to jump into read only mode. +For each call from a private contract to a public contract the virtual machine will change to read only mode. +If the virtual machine is in read only mode and the code tries to make a state change the virtual machine stops execution and throws an exception. + +The following transactions are allowed: + +S: sender, (X): private, X: public, ->: direction, []: read only mode +``` +1. S -> A -> B +2. S -> (A) -> (B) +3. S -> (A) -> [B -> C] +``` +The following transaction are unsupported: + +``` +1. (S) -> A +2. (S) -> (A) +``` + +### State verification + +To determine if nodes are in sync the public state root hash is included in the block. +Since private transactions can only be processed by nodes that are involved its impossible to get global consensus on the private state. +To overcome this issue the RPC method `eth_storageRoot(address[, blockNumber]) -> hash` can be used. +It returns the storage root for the given address at an (optional) block number. +If the optional block number is not given the latest block number is used. +The storage root hash can be on or off chain compared by the parties involved. diff --git a/docs/img/architecture.png b/docs/img/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..f09ff8e7b76b9286e562c7dc9cd7fd0aec50c74a GIT binary patch literal 84557 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/privacy.md b/docs/privacy.md new file mode 100644 index 000000000..1d38a9d25 --- /dev/null +++ b/docs/privacy.md @@ -0,0 +1,24 @@ + +# Privacy + +## Sending Private Transactions + +To send a private transaction, a PrivateTransactionManager must be configured. This is the +service which transfers private payloads to their intended recipients, performing +encryption and related operations in the process. + +Currently, `constellation` is supported out of the box via the PRIVATE_CONFIG environment +variable (please note that this integration method will change in the near future.) See the +`7nodes` folder in the `quorum-examples` repository for a complete example of how to use it. +The transaction sent in `script1.js` is private for node 7's PrivateTransactionManager +public key. + +Once `constellation` is launched and PRIVATE_CONFIG points to a valid configuration file, +a `SendTransaction` call can be made private by specifying the `privateFor` argument. +`privateFor` is a list of public keys of the intended recipients. (Note that in the case of +`constellation`, this public key is distinct from Ethereum account keys.) When a transaction +is private, the transaction contents will be sent to the PrivateTransactionManager and the +identifier returned will be placed in the transaction instead. When other Quorum nodes +receive a private transaction, they will query their PrivateTransactionManager for the +identifier and replace the transaction contents with the result (if any; nodes which are +not party to a transaction will not be able to retrieve the original contents.) diff --git a/docs/running.md b/docs/running.md new file mode 100644 index 000000000..ad827fd13 --- /dev/null +++ b/docs/running.md @@ -0,0 +1,145 @@ + +# Running Quorum + +The following new CLI arguments were introduced as part of Quorum: + +``` +QUORUM OPTIONS: + --voteaccount value Address that is used to vote for blocks + --votepassword value Password to unlock the voting address + --blockmakeraccount value Address that is used to create blocks + --blockmakerpassword value Password to unlock the block maker address + --singleblockmaker Indicate this node is the only node that can create blocks + --minblocktime value Set minimum block time (default: 3) + --maxblocktime value Set max block time (default: 10) +``` + +The full list of arguments can be viewed by running `geth --help`. + +### Initialize chain + +The first step is to generate the genesis block. + +``` +geth init genesis.json +``` + +The genesis block should include the Quorum voting contract address `0x0000000000000000000000000000000000000020`. +The code can be generated with [browser solidity](http://ethereum.github.io/browser-solidity/#version=soljson-latest.js) (note, use the runtime code) or using the solidity compiler `solc --optimize --bin-runtime block_voting.sol`. + +The `7nodes` directory in the `quorum-examples` repository contains several keys (using an empty password) that are used in the example genesis file: +``` +key1 vote key 1 +key2 vote key 2 +key3 vote key 3 +key4 block maker 1 +key5 block maker 2 +``` + +Example genesis file: +``` +{ + "alloc": { + "0x0000000000000000000000000000000000000020": { + "code": "606060405236156100c45760e060020a60003504631290948581146100c9578063284d163c146100f957806342169e4814610130578063488099a6146101395780634fe437d514610154578063559c390c1461015d57806368bb8bb61461025d57806372a571fc146102c857806386c1ff681461036957806398ba676d146103a0578063a7771ee31461040b578063adfaa72e14610433578063cf5289851461044e578063de8fa43114610457578063e814d1c71461046d578063f4ab9adf14610494575b610002565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c45760018190555b50565b610548600435600160a060020a03331660009081526005602052604090205460ff16156100c4576004546001141561055e57610002565b61045b60025481565b61054a60043560056020526000908152604090205460ff1681565b61045b60015481565b61045b60043560006000600060006000600050600186038154811015610002579080526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630192505b60018301548110156105d75760018301805484916000918490811015610002576000918252602080832090910154835282810193909352604091820181205485825292869052205410801561023257506001805490840180548591600091859081101561000257906000526020600020900160005054815260208101919091526040016000205410155b156102555760018301805482908110156100025760009182526020909120015491505b6001016101a8565b610548600435602435600160a060020a03331660009081526003602052604081205460ff16156100c4578054839010156105e45780548084038101808355908290829080158290116105df576002028160020283600052602060002091820191016105df919061066b565b610548600435600160a060020a03331660009081526005602052604090205460ff16156100c457600160a060020a0381166000908152604090205460ff1615156100f65760406000819020805460ff191660019081179091556004805490910190558051600160a060020a038316815290517f1a4ce6942f7aa91856332e618fc90159f13a340611a308f5d7327ba0707e56859181900360200190a16100f6565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c4576002546001141561071457610002565b61045b600435602435600060006000600050600185038154811015610002579080526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630181509050806001016000508381548110156100025750825250602090200154919050565b61054a600435600160a060020a03811660009081526003602052604090205460ff165b919050565b61054a60043560036020526000908152604090205460ff1681565b61045b60045481565b6000545b60408051918252519081900360200190f35b61054a600435600160a060020a03811660009081526005602052604090205460ff1661042e565b610548600435600160a060020a03331660009081526003602052604090205460ff16156100c457600160a060020a03811660009081526003602052604090205460ff1615156100f65760406000818120600160a060020a0384169182905260036020908152815460ff1916600190811790925560028054909201909155825191825291517f0ad2eca75347acd5160276fe4b5dad46987e4ff4af9e574195e3e9bc15d7e0ff929181900390910190a16100f6565b005b604080519115158252519081900360200190f35b600160a060020a03811660009081526005602052604090205460ff16156100f65760406000819020805460ff19169055600480546000190190558051600160a060020a038316815290517f8cee3054364d6799f1c8962580ad61273d9d38ca1ff26516bd1ad23c099a60229181900360200190a16100f6565b509392505050565b505050505b60008054600019850190811015610002578382526002027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563016020819052604082205490925014156106b8578060010160005080548060010182818154818355818115116106a5578183600052602060002091820191016106a5919061068d565b50506002015b808211156106a157600181018054600080835591825260208220610665918101905b808211156106a1576000815560010161068d565b5090565b5050506000928352506020909120018290555b600082815260208281526040918290208054600101905581514381529081018490528151600160a060020a033316927f3d03ba7f4b5227cdb385f2610906e5bcee147171603ec40005b30915ad20e258928290030190a2505050565b600160a060020a03811660009081526003602052604090205460ff16156100f65760406000819020805460ff19169055600280546000190190558051600160a060020a038316815290517f183393fc5cffbfc7d03d623966b85f76b9430f42d3aada2ac3f3deabc78899e89181900360200190a16100f656", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x02", + + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x04", + "0x29ecdbdf95c7f6ceec92d6150c697aa14abeb0f8595dd58d808842ea237d8494": "0x01", + "0x6aa118c6537572d8b515a9f9154be55a3377a8de7991cd23bf6e5ceb368688e3": "0x01", + "0x50793743212c6f01d326957d7069005b912f8215f10c7536be6b10782c6c44cd": "0x01", + "0x38f6c908c5cc7ca668cec2f476abe61b4dbb1df20f0ad8e07ef5dbf6a2f1ffd4": "0x01", + + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x02", + "0xaca3b76ed4968740c3180dd7fa37f4aa229a2c758a848f53920e9ccb4c4bb74e": "0x01", + "0xd188ba2dc293670542c1befaf7678b0859e5354a0727d1188b2afb6f47fe24d1": "0x01" + } + }, + "0xed9d02e382b34818e88b88a309c7fe71e65f419d": { + "balance": "1000000000000000000000000000" + }, + "0xca843569e3427144cead5e4d5999a3d0ccf92b8e": { + "balance": "1000000000000000000000000000" + }, + "0x0fbdc686b912d7722dc86510934589e0aaf3b55a": { + "balance": "1000000000000000000000000000" + }, + "0x9186eb3d20cbd1f5f992a950d808c4495153abd5": { + "balance": "1000000000000000000000000000" + }, + "0xed9d02e382b34818e88b88a309c7fe71e65f419d": { + "balance": "1000000000000000000000000000" + }, + "0x0638e1574728b6d862dd5d3a3e0942c3be47d996": { + "balance": "1000000000000000000000000000" + } + }, + "coinbase": "0x0000000000000000000000000000000000000000", + "config": { + "homesteadBlock": 0 + }, + "difficulty": "0x0", + "extraData": "0x", + "gasLimit": "0x2FEFD800", + "mixhash": "0x00000000000000000000000000000000000000647572616c65787365646c6578", + "nonce": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x00" +} +``` + +The storage key for voters and block makers is calculated with `web3.sha3(<256 bit aligned key value> + <256 bit variable index>)`. +The console can be used to calculate the storage key, in this case for vote key 1: +``` +> key = "000000000000000000000000ed9d02e382b34818e88b88a309c7fe71e65f419d" + "0000000000000000000000000000000000000000000000000000000000000003" +"000000000000000000000000ed9d02e382b34818e88b88a309c7fe71e65f419d0000000000000000000000000000000000000000000000000000000000000003" +> web3.sha3(key, {"encoding": "hex"}) +"0x29ecdbdf95c7f6ceec92d6150c697aa14abeb0f8595dd58d808842ea237d8494" +``` + +The `genesis.json` file can be found in the `7nodes` folder in the `quorum-examples` repository. + +### Start node + +Starting a node is as simple as `geth`. This will start the node without any of the roles and makes the node a spectator. + +### Voting role + +Start a node with the voting role: + +``` +geth --voteaccount 0xed9d02e382b34818e88b88a309c7fe71e65f419d +``` + +Optionally the `--votepassword` can be used to unlock the account. +If this flag is omitted the node will prompt for the password. + +### Block maker role + +Start a node with the block maker role: +``` +geth --blockmakeraccount 0x9186eb3d20cbd1f5f992a950d808c4495153abd5 +``` + +Created blocks will be signed with this account. + +Optionally the `--blockmakerpassword` can be used to unlock the account. +If this flag is omitted the node will prompt for the password. + +## Setup multi-node network + +Quorum comes with several scripts to setup a private test network with 7 nodes: + +* node 1, has no special roles +* node 2, has the block maker role +* node 3, has no special roles +* node 4, has the voting role +* node 5, has the voting role +* node 6, has no special roles + +All scripts can be found in the `7nodes` folder in the `quorum-examples` repository. + +1. Step 1, run `init.sh` and initialize data directories (change variables accordingly) +2. Step 2, start nodes with `start.sh` (change variables accordingly) +3. Step 3, stop network with `stop.sh`