Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Commit

Permalink
Merge branch 'master' into feature/NC-1909.ibft_gossip_2
Browse files Browse the repository at this point in the history
  • Loading branch information
Errorific authored Jan 7, 2019
2 parents a6b2d47 + dcedfea commit e819d1f
Show file tree
Hide file tree
Showing 14 changed files with 338 additions and 40 deletions.
7 changes: 4 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ The process described here has several goals:

Please follow these steps to have your contribution considered by the approvers:

1. Complete the ICLA, as described in [CLA.md]
1. Complete the CLA, as described in [CLA.md]
2. Follow all instructions in [PULL-REQUEST-TEMPLATE.md](.github/pull_request_template.md)
3. Include appropriate test coverage. Testing is 100% automated. There is no such thing as a manual test.
4. Follow the [styleguides](#Style Guides)
4. Follow the [Style Guides](#style-guides)
5. After you submit your pull request, verify that all [status checks](https://help.github.com/articles/about-status-checks/) are passing <details><summary>What if the status checks are failing?</summary>If a status check is failing, and you believe that the failure is unrelated to your change, please leave a comment on the pull request explaining why you believe the failure is unrelated. A maintainer will re-run the status check for you. If we conclude that the failure was a false positive, then we will open an issue to track that problem with our status check suite.</details>

While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted. Please refer to [Code Reviews].
Expand All @@ -166,7 +166,7 @@ We have a set of [coding conventions](CODING-CONVENTIONS.md) to which we try to
* Provide a summary on the first line with more details on additional lines as needed
* Reference issues and pull requests liberally

#Issue and Pull Request Labels
# Issue and Pull Request Labels
#### Type of Issue and Issue State

| Label name | Search Link :mag_right: | Description |
Expand Down Expand Up @@ -220,6 +220,7 @@ We have a set of [coding conventions](CODING-CONVENTIONS.md) to which we try to
[search-label-duplicate]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3APegasysEng%2FPantheon+label%3Aduplicate
[search-label-wontfix]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3APegasysEng%2FPantheon+label%3Awontfix
[search-label-invalid]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3APegasysEng%2FPantheon+label%3Ainvalid
[search-label-do-we-want-this]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3APegasysEng%2FPantheon+label%3Ado%20we%20want%20this
[search-label-work-in-progress]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3APegasysEng%2FPantheon+label%3Awork%20in%20progress
[search-label-requires-changes]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3APegasysEng%2FPantheon+label%3Arequires%20changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public static int calculateRequiredValidatorQuorum(final int validatorCount) {
return Util.fastDivCeiling(2 * validatorCount, 3);
}

public static long prepareMessageCountForQuorum(final long quorum) {
return quorum - 1;
}

public static Block createSealedBlock(
final Block block, final Collection<Signature> commitSeals) {
final BlockHeader initialHeader = block.getHeader();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package tech.pegasys.pantheon.consensus.ibft.statemachine;

import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.prepareMessageCountForQuorum;

import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftHelpers;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.RoundChangeCertificate;
Expand Down Expand Up @@ -89,7 +91,10 @@ public RoundChangeManager(
this.quorumSize = IbftHelpers.calculateRequiredValidatorQuorum(validators.size());
this.roundChangeMessageValidator =
new RoundChangeMessageValidator(
messageValidityFactory, validators, quorumSize - 1, sequenceNumber);
messageValidityFactory,
validators,
prepareMessageCountForQuorum(quorumSize),
sequenceNumber);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package tech.pegasys.pantheon.consensus.ibft.statemachine;

import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.prepareMessageCountForQuorum;

import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.CommitPayload;
import tech.pegasys.pantheon.consensus.ibft.ibftmessagedata.PreparePayload;
Expand Down Expand Up @@ -92,7 +94,9 @@ public void addCommitMessage(final SignedData<CommitPayload> msg) {
private void updateState() {
// NOTE: The quorumSize for Prepare messages is 1 less than the quorum size as the proposer
// does not supply a prepare message
prepared = (preparePayloads.size() >= (quorumSize - 1)) && proposalMessage.isPresent();
prepared =
(preparePayloads.size() >= prepareMessageCountForQuorum(quorumSize))
&& proposalMessage.isPresent();
committed = (commitPayloads.size() >= quorumSize) && proposalMessage.isPresent();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package tech.pegasys.pantheon.consensus.ibft.validation;

import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.prepareMessageCountForQuorum;

import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.IbftHelpers;
Expand Down Expand Up @@ -56,7 +58,8 @@ public RoundChangeMessageValidator createRoundChangeMessageValidator(
return new RoundChangeMessageValidator(
roundIdentifier -> createMessageValidator(roundIdentifier, parentHeader),
validators,
IbftHelpers.calculateRequiredValidatorQuorum(validators.size()),
prepareMessageCountForQuorum(
IbftHelpers.calculateRequiredValidatorQuorum(validators.size())),
parentHeader.getNumber() + 1);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package tech.pegasys.pantheon.consensus.ibft.validation;

import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.findLatestPreparedCertificate;
import static tech.pegasys.pantheon.consensus.ibft.IbftHelpers.prepareMessageCountForQuorum;

import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier;
import tech.pegasys.pantheon.consensus.ibft.blockcreation.ProposerSelector;
Expand Down Expand Up @@ -123,7 +124,10 @@ private boolean validateRoundChangeMessagesAndEnsureTargetRoundMatchesRoot(
roundChangeCert.getRoundChangePayloads()) {
final RoundChangeMessageValidator roundChangeValidator =
new RoundChangeMessageValidator(
messageValidatorFactory, validators, quorumSize, chainHeight);
messageValidatorFactory,
validators,
prepareMessageCountForQuorum(quorumSize),
chainHeight);

if (!roundChangeValidator.validateMessage(roundChangeMsg)) {
LOG.info("Invalid NewRound message, embedded RoundChange message failed validation.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void newRoundFromNonProposerFails() {
}

@Test
public void newRoundTargettingRoundZeroFails() {
public void newRoundTargetingRoundZeroFails() {
msgBuilder.setRoundChangeIdentifier(
new ConsensusRoundIdentifier(roundIdentifier.getSequenceNumber(), 0));

Expand Down Expand Up @@ -205,7 +205,7 @@ public void newRoundWithProposalNotMatchingLatestRoundChangeFails() {
public void roundChangeMessagesDoNotAllTargetRoundOfNewRoundMsgFails() {
final ConsensusRoundIdentifier prevRound = TestHelpers.createFrom(roundIdentifier, 0, -1);

RoundChangeCertificate.Builder roundChangeBuilder = new RoundChangeCertificate.Builder();
final RoundChangeCertificate.Builder roundChangeBuilder = new RoundChangeCertificate.Builder();
roundChangeBuilder.appendRoundChangeMessage(
proposerMessageFactory.createSignedRoundChangePayload(roundIdentifier, Optional.empty()));
roundChangeBuilder.appendRoundChangeMessage(
Expand All @@ -222,7 +222,7 @@ public void roundChangeMessagesDoNotAllTargetRoundOfNewRoundMsgFails() {
public void invalidEmbeddedRoundChangeMessageFails() {
final ConsensusRoundIdentifier prevRound = TestHelpers.createFrom(roundIdentifier, 0, -1);

RoundChangeCertificate.Builder roundChangeBuilder = new RoundChangeCertificate.Builder();
final RoundChangeCertificate.Builder roundChangeBuilder = new RoundChangeCertificate.Builder();
roundChangeBuilder.appendRoundChangeMessage(
proposerMessageFactory.createSignedRoundChangePayload(
roundIdentifier,
Expand Down Expand Up @@ -260,8 +260,6 @@ public void lastestPreparedCertificateMatchesNewRoundProposalIsSuccessful() {
differentProposal,
Lists.newArrayList(
validatorMessageFactory.createSignedPreparePayload(
roundIdentifier, proposedBlock.getHash()),
otherValidatorMessageFactory.createSignedPreparePayload(
roundIdentifier, proposedBlock.getHash()))));

// An earlier PrepareCert is added to ensure the path to find the latest PrepareCert
Expand All @@ -277,8 +275,6 @@ public void lastestPreparedCertificateMatchesNewRoundProposalIsSuccessful() {
earlierProposal,
Lists.newArrayList(
validatorMessageFactory.createSignedPreparePayload(
earlierPreparedRound, proposedBlock.getHash()),
otherValidatorMessageFactory.createSignedPreparePayload(
earlierPreparedRound, proposedBlock.getHash()))));

final SignedData<NewRoundPayload> msg =
Expand All @@ -287,9 +283,7 @@ public void lastestPreparedCertificateMatchesNewRoundProposalIsSuccessful() {
new RoundChangeCertificate(
Lists.newArrayList(
proposerMessageFactory.createSignedRoundChangePayload(
roundIdentifier, earlierPreparedCert),
proposerMessageFactory.createSignedRoundChangePayload(
roundIdentifier, preparedCert))),
roundIdentifier, earlierPreparedCert))),
proposal);
proposerMessageFactory.createSignedProposalPayload(roundIdentifier, proposedBlock);

Expand Down
22 changes: 13 additions & 9 deletions docs/Configuring-Pantheon/Testing-Developing-Nodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Bootnodes are used to initially discover peers.

### Mainnet and Public Testnets

For mainnet and Rinkeby, Pantheon predefines a list of enonde URLs. For Ropsten, bootnodes are specified using the [`--bootnodes`](../Reference/Pantheon-CLI-Syntax.md#bootnodes) option.
For mainnet, Rinkeby, Ropsten, and Görli, Pantheon predefines a list of enode URLs.

### Private Networks

Expand All @@ -21,18 +21,22 @@ To start a bootnode for a private network:

!!! example
```bash
pantheon export-pub-key bootnode
pantheon --genesis=privateNetworkGenesis.json --datadir=nodeDataDir export-pub-key bootnode
```
Where `privateNetworkGenesis.json` and `nodeDataDir` are changed to the relevant values for
your private network.

The node public key is exported to the `bootnode` file.

2. Start the bootnode, specifying:

* An empty string for the [`--bootnodes`](../Reference/Pantheon-CLI-Syntax.md#bootnodes) option because this is the bootnode.
* The network ID for your private network.
* Empty string for the [`--bootnodes`](../Reference/Pantheon-CLI-Syntax.md#bootnodes) option because this is the bootnode.
* Network ID for your private network.
* Genesis file and data directory as in the previous step.

!!! example
```bash
pantheon --bootnodes="" --network-id 123
```
pantheon --bootnodes="" --genesis=privateNetworkGenesis.json --datadir=nodeDataDir --network-id 123
```

To specify this bootnode for another node, the enode URL for the `--bootnodes` option is `enode://<id>@<host:port>` where:
Expand All @@ -43,15 +47,15 @@ To specify this bootnode for another node, the enode URL for the `--bootnodes` o
!!! example
If the `--p2p-listen` option is not specified and the node public key exported is `0xc35c3ec90a8a51fd5703594c6303382f3ae6b2ecb9589bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f`

Then the enode URL is:
The enode URL is:
`enode://c35c3ec90a8a51fd5703594c6303382f3ae6b2ecb9589bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f@127.0.0.1:30303`

!!! info
The default host and port for P2P peer discovery is `127.0.0.1:30303`. The `--p2p-listen` option can be used to specify a host and port.
The default host and port for P2P peer discovery is `127.0.0.1:30303`. Use the `--p2p-listen` option to specify a host and port.

To start a node specifying the bootnode for P2P discovery:

!!! example
```bash
pantheon --datadir=/tmp/pantheon/30301 --p2p-listen=127.0.0.1:30301 --network-id=123 --bootnodes=enode://c35c3ec90a8a51fd5703594c6303382f3ae6b2ecb99bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f@127.0.0.1:30303
pantheon --genesis=privateNetworkGenesis.json --datadir=nodeDataDir --p2p-listen=127.0.0.1:30301 --network-id=123 --bootnodes=enode://c35c3ec90a8a51fd5703594c6303382f3ae6b2ecb99bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f@127.0.0.1:30303
```
56 changes: 48 additions & 8 deletions docs/Reference/JSON-RPC-API-Methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -812,38 +812,78 @@ You can interact with contracts using [eth_sendRawTransaction or eth_call](../Us

### eth_estimateGas

Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. (Per Etherscan: gas price * gas used.) The transaction is added to the blockchain. The estimate may be significantly more than the amount of gas actually used by the transaction for reasons including EVM mechanics and node performance.
Returns an estimate of how much gas is needed for the transaction to complete. The estimate process does not use
gas and is not added to the blockchain as a transaction. The estimate can be greater than the amount of gas that the
transaction actually uses, for reasons including EVM mechanics and node performance.

The `eth_estimateGas` call does not send a transaction. You must make a subsequent call to
[eth_sendRawTransaction](#eth_sendRawTransaction) to execute the transaction.

**Parameters**

!!!note
Parameters are the same as the eth_call parameters, except that all properties are optional. If you do not specify a `gas` limit, Pantheon uses the gas limit from the pending block as an upper bound. As a result, the returned estimate might not be enough to execute the call or transaction when the amount of gas is higher than the pending block's gas limit.
The transaction call object parameters are the same as those for [eth_call](#eth_call), except that in `eth_estimateGas`
all fields are optional. If you do not specify a `gas` amount in the transaction call object, Pantheon uses the
`gasLimit` amount from the block at the head of the chain as the upper limit. If the amount of gas needed is higher
than the estimated upper limit, the transaction might not have enough gas to execute.

*OBJECT* - [Transaction call object](JSON-RPC-API-Objects.md#transaction-call-object).

*QUANTITY|TAG* - Integer representing a block number or one of the string tags `latest`, `earliest`, or `pending`, as described in [Block Parameter](Using-JSON-RPC-API.md#block-parameter).

**Returns**

`result` (*QUANTITY*) - Amount of gas used.
`result` : `quantity` - Amount of gas used.

The following example returns an estimate of 21000 wei (0x5208) for the transaction.

!!! example
```bash tab="curl HTTP request"
$ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"from":"0x687422eea2cb73b5d3e242ba5456b782919afc85","to":"0xdd37f65db31c107f773e82a4f85c693058fef7a9","value":"0x1"}],"id":53}' <JSON-RPC-http-endpoint:port>
$ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"from":"0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73","to":"0x44Aa93095D6749A706051658B970b941c72c1D53","value":"0x1"}],"id":53}' <JSON-RPC-endpoint:port>
```

```bash tab="wscat WS request"
{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"from":"0x687422eea2cb73b5d3e242ba5456b782919afc85","to":"0xdd37f65db31c107f773e82a4f85c693058fef7a9","value":"0x1"}],"id":53}
{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"from":"0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73","to":"0x44Aa93095D6749A706051658B970b941c72c1D53","value":"0x1"}],"id":53}
```

```json tab="JSON result"
{
"jsonrpc" : "2.0",
"id" : 54,
"id" : 53,
"result" : "0x5208"
}
```

The following example request estimates the cost of deploying a simple storage smart contract to the network. The data field
contains the hash of the compiled contract to be deployed. (You can obtain the compiled contract hash from your IDE;
for example, **Remix > Compile tab > details > WEB3DEPLOY**.) The result is 113355 wei.

**Returns**

!!! example
```bash tab="curl HTTP request"
$ curl -X POST \
http://localhost:8545 \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [{
"from": "0x8bad598904ec5d93d07e204a366d084a80c7694e",
"data": "0x608060405234801561001057600080fd5b5060e38061001f6000396000f3fe6080604052600436106043576000357c0100000000000000000000000000000000000000000000000000000000900480633fa4f24514604857806355241077146070575b600080fd5b348015605357600080fd5b50605a60a7565b6040518082815260200191505060405180910390f35b348015607b57600080fd5b5060a560048036036020811015609057600080fd5b810190808035906020019092919050505060ad565b005b60005481565b806000819055505056fea165627a7a7230582020d7ad478b98b85ca751c924ef66bcebbbd8072b93031073ef35270a4c42f0080029"
}],
"id": 1
}'
```

!!! example
```json tab="JSON result"
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x1bacb"
}
```


### eth_getBlockByHash

Returns information about the block by hash.
Expand Down
Loading

0 comments on commit e819d1f

Please sign in to comment.