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

Add wrapper classes for config section of genesis file #208

Merged
merged 7 commits into from
Nov 1, 2018

Conversation

ajsutton
Copy link
Contributor

PR description

Introduce classes to wrap the config section of a genesis file instead of accessing it directly in multiple places. This provides a centralised place for accessing the config and makes it simple to test that the config was loaded correctly.

Fixes discrepancy in how CliqueProtocolSchedule and CliquePantheonController loaded the block period configuration. They were looking for different keys with different default values for what should be the same configuration item.

ajsutton and others added 4 commits October 30, 2018 06:25
…y in multiple places.

Fix discrepancy in how CliqueProtocolSchedule and CliquePantheonController loaded the block period configuration.
…fig as optionals instead of providing the default.

import io.vertx.core.json.JsonObject;

public class CliqueConfigOptions {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could/should this have a base interface, then this is the "Json" version of it?

If you did that, the default values would live in the base class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems overly complicated to be honest. I don't see any real need to support multiple genesis config formats now and it would be easy to extract a base class or interface if we ever do want to, so I would apply You Ain't Gonna Need It here and just keep things simple.


public static final CliqueConfigOptions DEFAULT = new CliqueConfigOptions(new JsonObject());

private static final long DEFAULT_EPOCH_LENGTH = 30_000;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh - I really hate default values for this - people should configure their network to actually work - not just get lucky that things came out well.
These defaults would need to become part of the clique spec to ensure unconfigured clients would interact correctly ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mean this to sound defensive, but I didn't introduce those defaults, you did. I just moved them. :)

In general though I think it makes a lot of sense to have defaults for these config values and it seems like pretty common behaviour in other clients. The spec does explicitly recommend 30000 block epoch length.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I put them in because other people did ... the defaults do now form part of our spec, maybe not a bad thing.

private final JsonObject cliqueConfigRoot;

public CliqueConfigOptions(final JsonObject cliqueConfigRoot) {
this.cliqueConfigRoot = cliqueConfigRoot;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit/ymmv: is it worth pre-parsing the config such that if its bad, we fail at startup rather than when we go to use the config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these config objects have the primary responsibility for validation - they do some incidental validation in terms of "must be a number" but even then a lot of the time they just return a String and leave parsing to the caller.

The values from these config objects are actually used during startup anyway and it would be a smell to me if the config objects continued to live on past startup.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do you see validation living then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, the same place it currently does - at the point of usage. I can see some benefit in having specific validation for config objects but I think that would be a separate validator object that uses these config objects to extract the data to validate. I think this is a big enough PR without attempting to rework validation at the same time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to revisit it later in another PR. My thoughts to carry forward are I think the validation should come earlier than it's point of usage so whatever is being used can be treated as untainted.

}

public boolean isEthHash() {
return configRoot.containsKey("ethash");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason this doesn't do the same as IBFT/clique with regard a class constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That string was only referenced once so locality of reference was very useful, but will move it for consistency since it is very much like the IBFT and Clique keys so should follow the same pattern.


public static final IbftConfigOptions DEFAULT = new IbftConfigOptions(new JsonObject());

private static final long DEFAULT_EPOCH_LENGTH = 30_000;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comments as for clique.


@Test
public void shouldGetEpochLengthFromConfig() {
final CliqueConfigOptions config = fromConfigOptions(singletonMap("epochLength", 10_000));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So - does this imply you an create a valid clique config options,even if period is missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if it's not specified it would use the default. But mostly it just means CliqueConfigOptions isn't doing validation and I'm taking advantage of that to keep the test as simple as possible.

* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.config;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be in consensus.clique? Having the config class knowing about the requirements of all modules and the modules being dependent on config seems to be a step in the wrong direction with regards to the modular goals of the application.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my initial inclination but two things persuaded me otherwise:

  1. Knowledge of the specific consensus algorithms that are available and how they fit into the config file is already outside of the specific consensus modules (see PantheonController.fromConfig).
  2. If we try to model the config as separate domains with each consensus implementation having it's config objects in separate modules, there's no way to expose those separate config objects from the top level GenesisConfigOptions without also exposing the inner workings of the config which is what we were trying to encapsulate in the first place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those don't quite persuade me, but not going to block the improvement. Can revisit it later if the config starts getting in the way of the architecture requirements.

@ajsutton ajsutton merged commit 824b56f into PegaSysEng:master Nov 1, 2018
@ajsutton ajsutton deleted the fix-config1 branch November 1, 2018 03:23
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants