Skip to content

Commit

Permalink
POATestnet: Apply suggestions from code review
Browse files Browse the repository at this point in the history
Co-Authored-By: Jan Xie <[email protected]>
  • Loading branch information
jjyr and Jan Xie committed Dec 30, 2019
1 parent 7c18d78 commit 0af1d61
Showing 1 changed file with 14 additions and 15 deletions.
29 changes: 14 additions & 15 deletions rfcs/0000-poa-testnet/0000-poa-testnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ Created: 2019-12-9

The original intention of the aggron testnet is to provide a stable environment for contract development.

However, the mining power on aggron is volatile (shown in [charts](https://explorer.nervos.org/aggron/charts)), since a rational miner has no incentive to mine the testnet coins continuously. If any new miner or mining pool joins, the mining difficulty rises fast. Once they leave, the testnet block produce becomes extremely slow due to a sudden drop of hashrate, and the average block time would require minutes or even longer.
However, the mining power on aggron is volatile (shown in [charts](https://explorer.nervos.org/aggron/charts)), since a rational miner has no incentive to mine the testnet coins continuously. If any new miner or mining pool joins, the mining difficulty rises fast. Once they leave, new block generation becomes extremely slow due to a sudden drop of hashrate, and the average block time would require minutes or even longer.

A POW blockchain only works when the miner has economic incentives, it's not adapted for the testnet, so we propose a new POA consensus testnet to serve the contract development purpose.
A POW blockchain only works when the miner has economic incentives that conflict with the nature of the testnet, so we propose a new POA consensus testnet to serve the contract development purpose.

We expect the new POA testnet to be long term stable, and the testnet should be just like the mainnet without using POW. A contract developer should feel no difference when developing on POA testnet and mainnet.

Expand All @@ -32,7 +32,7 @@ We define the following variables:
* `VALIDATOR_COUNT` - Number of current validators, this value changed due to new validators join or old validator leaves.
* `ATTEST_INTERVAL` - A validator cannot attest two blocks within `ATTEST_INTERVAL` number. For example, a validator who attest block (6) must wait for at least `ATTEST_INTERVAL` blocks to do next attest: block (6 + `ATTEST_INTERVAL` + 1). Notice when the `VALIDATOR_COUNT` <= `ATTEST_INTERVAL`, the POA testnet will stuck forever due to no validators can attest a new block.
* `BLOCK_INTERVAL` - the interval of blocks, set to 8 seconds.
* `VOTE_LIMIT` - The least votes to make a new validator join or to evict an old validator, should be at least `VALIDATOR_COUNT / 2 + 1`.
* `VOTE_THRESHOLD` - The least votes to make a new validator join or to evict an old validator, should be at least `VALIDATOR_COUNT / 2 + 1`.

### attest a new block

Expand Down Expand Up @@ -61,7 +61,7 @@ The first malicious validator must wait for `ATTEST_INTERVAL + 1` blocks to prod

### validator list and on-chain governance

As previously described, the POA testnet maintained by a group of validators. We have a build-in on-chain governance mechanism to allows updating the exists validator list. The on-chain governance mechanism designed to be loose; it allows several validators that greater than `VOTE_LIMIT` to sign a transaction together that updating the exists validators to a list of new validators.
As previously described, the POA testnet maintained by a group of validators. We have a build-in on-chain governance mechanism to update the exists validator list; it allows several validators that greater than `VOTE_THRESHOLD` to sign a transaction together that updating the exists validators to a list of new validators.

As a natural thought, we can use a CKB cell to store the validator list, and the validator list can represent in a list of pubkey hash.

Expand All @@ -76,42 +76,41 @@ The pre-defined [multisig script] satisfies our on-chain governance requirements
So we choose to use a cell to represent the POA validator list. The cell contains the following `multisig script` in its data field, and with a multisig lock to lock the cell, the `multisig script` in data must corresponding to the lock's `multisig script`.

``` txt
0 | 0 | VOTE_LIMIT | VALIDATOR_COUNT | blake160(Pubkey1) | blake160(Pubkey2) | ...
0 | 0 | VOTE_THRESHOLD | VALIDATOR_COUNT | blake160(Pubkey1) | blake160(Pubkey2) | ...
```

We use a cell with `M of N` multisig lock to describe the validator list, the`M` set to `VOTE_LIMIT`, and `N` set to `VALIDATORS_COUNT`, we need an extra parameter to represent `ATTEST_INTERVAL`, so the final data is a 4 bytes little-endian number to represent `ATTEST_INTERVAL` plus a `multisig script`:
We use a cell with `M of N` multisig lock to describe the validator list, the `M` set to `VOTE_THRESHOLD`, and `N` set to `VALIDATORS_COUNT`, we need an extra parameter to represent `ATTEST_INTERVAL`, so the final data is a 4 bytes little-endian number to represent `ATTEST_INTERVAL` plus a `multisig script`:

``` txt
ATTEST_INTERVAL(4 bytes little-endian) | 0 | 0 | VOTE_LIMIT | VALIDATOR_COUNT | blake160(Pubkey1) | blake160(Pubkey2) | ...
ATTEST_INTERVAL(4 bytes little-endian) | 0 | 0 | VOTE_THRESHOLD | VALIDATOR_COUNT | blake160(Pubkey1) | blake160(Pubkey2) | ...
```

To change the validator list, anyone that collects enough votes(the signatures) can send a transaction to update the old validator list cell and construct a new validator list cell.

For simplify to track this cell, we assign a `type_id` on it; validators or anyone who wants to verify POA blocks must track this cell to keep validator list fresh.
To simplify the tracking of this cell, we assign a `type_id` on it; validators or anyone who wants to keep a fresh validator list can track the change of this cell by its `type_id`.

Before sign a vote transaction, validators must make sure the `multisig script` in the cell is valid and corresponding to the lock, and only one cell constructed to represent the validator list; otherwise, the POA consensus wound broken.
Before signing a vote transaction, validators must make sure the `multisig script` in the cell is valid and corresponding to the lock, and only one cell constructed to represent the validator list; otherwise, the POA consensus wound broken.

To simplify, the process of collecting votes do not include in the POA protocol.

### off-chain governance

The main intention of this document is to describe the POA testnet protocol. However, to better explain how the POA testnet validator works, we add this section as a suggestion to the off-chain governance, notice this section is more like a suggestion than a specification.

The intention of on-chain governance and dynamic validators design is to decentralize the POA testnet. Instead of the foundation itself, the community should finally maintain the POA testnet validators.
The intention of on-chain governance and dynamic validators design is to decentralize the POA testnet. Instead of the foundation, the community should be the maintainer of the POA testnet.

In the initial stage of the POA testnet, there may be just a small group validator that invited by the Nervos foundation. The validators together should governance the testnet and invite more validators from the community. A candidate validator may be a company or organization that influences the community.
In the initial stage of the POA testnet, there may be just a small group validator that invited by the Nervos foundation. The validators together should governance the testnet and invite more validators from the community. A candidate validator may be a reputable company or organization in the community.

A possible way to elect candidate validators:

The exists validators deploy a permissionless voting DAPP on the mainnet allows any company and organization can register them as a candidate.
The exists validators deploy a permissionless voting DAPP on the mainnet allows any company and organization to register as a candidate.
Anyone can deposit mainnet coins to vote on the candidates.
The POA testnet validators obey the result of the DApp to invites the candidate to become the testnet validator.

Such an election should periodically host.

## POA header

CKB header encoded in fixed-length, the size of the `nonce` field is 128 bits, we can't put 256 bits secp256k1 signature into the header directly.
CKB header is length fixed, the size of the `nonce` field is 128 bits, we can't put 256 bits secp256k1 signature into the header directly.

For the ease of implementation, instead of changing the block header structure, we put an extra POA payload `POAContext` in the cellbase transaction's first witness. To verify a header, we need both the header and the cellbase transaction.

Expand Down Expand Up @@ -154,7 +153,7 @@ A node does the following steps to verify a POA header:
3. re-comute the block's `transaction_root` and block hash.
4. recovery the pubkey, then check the pubkey hash is belongs to a validator.

Now we can verify a POAHeader with fixed validators. However, when validator list updated, the header-first synchronization may couldn't handle it correctly, think the following situation:
Now we can verify a POAHeader with fixed validators. However, when validator list updated, the header-first synchronization may couldn't handle it correctly, consider the following situation:
The initial validators list is `[A, B, C, D]`.
Since block `N`, the validator list updated to `[A, B, D, E]`.
A header-first synchronization from `N - 1` to `N + 4` wound fails to sync due to the unknown validator `E`.
Expand Down

0 comments on commit 0af1d61

Please sign in to comment.