Merge pull request #241 from jpmorganchase/doc-updates

Update docs for Quorum v2.
This commit is contained in:
Patrick Mylund Nielsen 2018-01-25 11:59:29 -05:00 committed by GitHub
commit 37ccab5c24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 9 additions and 248 deletions

View File

@ -5,4 +5,4 @@
* [Design](./design.md) - Quorum design overview
* [Privacy](./privacy.md) - Sending private transactions [privacy video](https://vimeo.com/user5833792/review/210456729/8f70cfaaa5)
* [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
* [API](./api.md) - new privacy API

View File

@ -48,103 +48,3 @@ web3.eth.sendTransaction({
}
});
```
## QuorumChain APIs
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` votes for the given hash to be the canonical head on the current height and returns the tx hash
```
> quorum.vote(eth.getBlock("latest").hash)
"0x16c69b9bdf9f10c64e65dbfe50bc997d2bc1ed321c6041db602908b7f6cab2a9"
```
### `quorum.canonicalHash` returns the canonical hash for the given block height (add 1 for the hash that the current pending block will be based on top of)
```
> quorum.canonicalHash(eth.blockNumber+1)
"0xf2c8a36d0c54c7013246fddebfc29bc881f6f10f74f761d511b5ebfaa103adfa"
```
### `quorum.isVoter` returns whether the given address is allowed to vote for new blocks
```
> quorum.isVoter("0xed9d02e382b34818e88b88a309c7fe71e65f419d")
true
```
### `quorum.isBlockMaker` returns whether 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 a paused node to begin creating blocks again
```
> quorum.resumeBlockMaker()
null
> quorum.nodeInfo
{
blockMakerAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d",
blockmakestrategy: {
maxblocktime: 6,
minblocktime: 3,
status: "active",
type: "deadline"
},
canCreateBlocks: true,
canVote: true,
voteAccount: "0xed9d02e382b34818e88b88a309c7fe71e65f419d"
}
```

View File

@ -1,25 +1,6 @@
# 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 QuorumChain smart contract.
QuorumChain 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:

View File

@ -1,31 +0,0 @@
# How a block gets added to the chain in quorum
A code walkthrough showing the making of a new block and how nodes receive and vote for it.
## Pre-requisites for all nodes:
The [BlockVoting service has been started](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/cmd/geth/main.go#L332) with a [block maker strategy in place](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/eth/block_voting.go#L11-L13)
## On the block maker
1. BlockMaker reaches its deadline waiting for a new block from others and [fires an event to trigger the creation of a new one itself](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/quorum/vote_strategy.go#L91)
2. The event is [picked up by the BlockVoting loop](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/quorum/block_voting.go#L261)
3. A new block is [constructed, inserted into the chain](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/quorum/block_voting.go#L348-L349)
4. A [ChainHeadEvent is published on BlockChain.chainEvents](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/blockchain.go#L1239)
5. A [NewMinedBlockEvent is published](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/quorum/block_voting.go#L353)
6. The NewMinedBlockEvent will eventually cause the ProtocolManager to [broadcast the new block](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/eth/handler.go#L759-L761)
7. Finally, the ChainHeadEvent will cause the node to [reset its pending state and vote for its own block](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/quorum/block_voting.go#L232-L236)
## On other nodes
1. Node [receives a message notifying about new block](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/eth/handler.go#L653)
2. [Enqueues it for import](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/eth/handler.go#L664)
3. The fetcher [detects a new import has been queued](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/eth/fetcher/fetcher.go#L293)
4. And [imports it](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/eth/fetcher/fetcher.go#L313) by [calling ProtocolManager.insertChain()](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/eth/handler.go#L178)
5. Which in turn calls BlockChain.InsertChain(), which checks that [the block was created by a block maker](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/block_validator.go#L334) (via [BlockValidator.ValidateBlock()](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/blockchain.go#L879) -> [ValidateHeader()](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/block_validator.go#L97) -> [ValidateExtraData()](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/block_validator.go#L329)),
and [call BlockValidator.ValidateState()](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/blockchain.go#L945)
to check that [its parent is the current head](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/block_validator.go#L172)
6. It will then send a [ChainHeadEvent on BlockChain.chainEvents](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/blockchain.go#L1239)
6. Which is processed in BlockVoting.run(), causing the Node's [pending state to be reset and the node to vote for the new block](https://github.com/jpmorganchase/quorum/blob/856c9fe43e3eb675678c55ceda7eb4d298a7ca7d/core/quorum/block_voting.go#L232-L236)

View File

@ -1,17 +1,10 @@
# Running Quorum
The following new CLI arguments were introduced as part of Quorum:
A `--permissioned` CLI argument was introduced with 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)
--permissioned If enabled, the node will allow only a defined list of nodes to connect
```
@ -21,9 +14,6 @@ The full list of arguments can be viewed by running `geth --help`.
The first step is to generate the genesis block.
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:
```
@ -37,37 +27,7 @@ key5 block maker 2
Example genesis file (copy to `genesis.json`):
```json
{
"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"
},
"0x0638e1574728b6d862dd5d3a3e0942c3be47d996": {
"balance": "1000000000000000000000000000"
}
},
"alloc": {},
"coinbase": "0x0000000000000000000000000000000000000000",
"config": {
"homesteadBlock": 0
@ -88,25 +48,8 @@ Now we can initialize geth:
geth init genesis.json
```
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"
```
From the above example, the `<256 bit aligned key value>` is the ethereum account address that should be added to the voting map, ed9d02e382b34818e88b88a309c7fe71e65f419d, padded to 256bits. The `<256 bit variable index>` is the index(3) of the canVote mapping in the solidity [voting smart contract](https://github.com/jpmorganchase/quorum/blob/master/core/quorum/block_voting.sol#L42) padded to 256bits. The index is calculated based on the location of canVote:
* Period[] periods --> index 0
* uint public voteThreshold --> index 1
* uint public voterCount --> index 2
* mapping(address => bool) public canVote --> index 3
The `genesis.json` file can be found in the `7nodes` folder in the `quorum-examples` repository.
### Setup Bootnode
Optionally you can set up a bootnode that all the other nodes will first connect to in order to find other peers in the network. You will first need to generate a bootnode key:
Optionally you can set up a bootnode that all the other nodes will first connect to in order to find other peers in the network. You will first need to generate a bootnode key:
1- To generate the key for the first time:
@ -115,9 +58,9 @@ Optionally you can set up a bootnode that all the other nodes will first connect
2- To later restart the bootnode using the same key (and hence use the same enode url):
`bootnode -nodekey tmp_file.txt`
or
`bootnode -nodekeyhex 77bd02ffa26e3fb8f324bda24ae588066f1873d95680104de5bc2db9e7b2e510 // Key from tmp_file.txt`
@ -127,44 +70,12 @@ Starting a node is as simple as `geth`. This will start the node without any of
`geth --bootnodes $BOOTNODE_ENODE`
### 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:
Quorum comes with several scripts to setup a private test network with 7 nodes in the `7nodes` folder in the `quorum-examples` repository.
* 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)
1. Step 1, run `raft-init.sh` and initialize data directories (change variables accordingly)
2. Step 2, start nodes with `raft-start.sh` (change variables accordingly)
3. Step 3, stop network with `stop.sh`
## Permissioned Network