mirror of https://github.com/poanetwork/quorum.git
Merge pull request #241 from jpmorganchase/doc-updates
Update docs for Quorum v2.
This commit is contained in:
commit
37ccab5c24
|
@ -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
|
||||
|
|
100
docs/api.md
100
docs/api.md
|
@ -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"
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
105
docs/running.md
105
docs/running.md
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue