Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract genesis config and improve adding builtin services [ECR-3750] #1541

Merged
merged 63 commits into from
Dec 4, 2019

Conversation

skletsun
Copy link
Contributor

@skletsun skletsun commented Nov 14, 2019

Overview

  • Genesis config is extracted into separated entity.
  • Improved adding builtin services.

UPD: Current status (since [c7abbea]):

  • Add ability to specify default instances for ServiceFactory.
  • Remove InstanceConfig.
  • Fix majourity of relatively small comments.
  • Refactor Node::new().
  • WellKnownRuntime and the rest of tasks from ECR-3744.
  • Get rid of InstanceCollection.

See: https://jira.bf.local/browse/ECR-3750, https://jira.bf.local/browse/ECR-3690.

Definition of Done

  • There are no TODOs left in the merged code
  • Change is covered by automated tests
  • Benchmark results are attached (if applicable)
  • The coding guidelines are followed
  • Public API has proper documentation
  • Changelog is updated if needed (in case of notable or breaking changes)
  • The continuous integration build passes

@skletsun skletsun changed the title Extract genesis config [ECR-3750] Extract genesis config [ECR-3750][ECR-3609] Nov 14, 2019
@skletsun skletsun changed the title Extract genesis config [ECR-3750][ECR-3609] Extract genesis config and improve adding builtin services [ECR-3750] [ECR-3609] Nov 14, 2019
exonum/src/blockchain/config.rs Outdated Show resolved Hide resolved
self
}

pub fn from_spec(instance_spec: InstanceSpec, constructor: impl BinaryValue) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

By this method there is no way to set deploy args, is this a correct approach?

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. The main intention of this method was using in tests for converting in tests. I wanted to reflect this in the documentation, but forgot. Now I see that this method is now such useful, so probably it will be better to get rid of it.

@aleksuss aleksuss added this to the Release 0.13 milestone Nov 14, 2019
@skletsun
Copy link
Contributor Author

There are some minor tasks left (like write docs, rename structs), but the PR, in general, is ready for review.

@codecov
Copy link

codecov bot commented Nov 14, 2019

Codecov Report

Merging #1541 into master will decrease coverage by 0.02%.
The diff coverage is 94.1%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1541      +/-   ##
==========================================
- Coverage   93.81%   93.79%   -0.03%     
==========================================
  Files         204      204              
  Lines       30047    30302     +255     
==========================================
+ Hits        28188    28421     +233     
- Misses       1859     1881      +22
Impacted Files Coverage Δ
test-suite/testkit/tests/counter/main.rs 99.24% <ø> (-0.01%) ⬇️
...sts/inflating_currency/inflating_cryptocurrency.rs 97.4% <ø> (ø) ⬆️
test-suite/testkit/tests/interfaces/services.rs 98.43% <ø> (ø) ⬆️
services/supervisor/src/lib.rs 85.83% <ø> (-0.57%) ⬇️
test-suite/testkit/tests/service_hooks/hooks.rs 100% <ø> (ø) ⬆️
...est-suite/testkit/tests/inflating_currency/main.rs 100% <ø> (ø) ⬆️
cli/src/lib.rs 0% <ø> (ø) ⬆️
services/supervisor/tests/supervisor/inc.rs 96.07% <ø> (-0.22%) ⬇️
test-suite/testkit/tests/counter/counter.rs 85.71% <ø> (ø) ⬆️
exonum/src/proto/mod.rs 95.23% <ø> (ø) ⬆️
... and 30 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 97d2c71...b94ae16. Read the comment docs.

@popzxc popzxc added core Changes affecting exonum core update changelog labels Nov 14, 2019
exonum/src/helpers/mod.rs Show resolved Hide resolved
exonum/src/helpers/mod.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/mod.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/mod.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/config.rs Show resolved Hide resolved
exonum/src/blockchain/config.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/config.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/config.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/config.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/builder.rs Outdated Show resolved Hide resolved
@dmitry-timofeev dmitry-timofeev removed their request for review November 14, 2019 16:45
Copy link
Contributor

@slowli slowli left a comment

Choose a reason for hiding this comment

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

Comments as of 53f362a. I'd suggest to remove InstanceConfig within this PR; if possible, refactor Node::new() as well. (Is there a task to make genesis config optional for node startup? If I understand correctly, it is not used once the network is launched.)

examples/sample_runtime/src/main.rs Outdated Show resolved Hide resolved
examples/sample_runtime/src/main.rs Outdated Show resolved Hide resolved
examples/sample_runtime/src/main.rs Outdated Show resolved Hide resolved
exonum/benches/criterion/block.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/builder.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/config.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/config.rs Outdated Show resolved Hide resolved
exonum/src/blockchain/mod.rs Outdated Show resolved Hide resolved
@@ -950,8 +951,14 @@ impl Node {
node_cfg.service_keypair(),
ApiSender::new(channel.api_requests.0.clone()),
);
let blockchain = BlockchainBuilder::new(blockchain, node_cfg.consensus.clone())
.with_rust_runtime(channel.endpoints.0.clone(), services)
let (rust_runtime, genesis_config) = create_rust_runtime_and_genesis_config(
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest to refactor Node::new for clarity. Ideally, it should accept GenesisConfig directly or via a field in NodeConfig (since the consensus config is already there). Likewise, service factories should be accepted instead of InstanceCollections.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should we even pass service factories here? Wouldn't it be better to pass RustRuntime populated with factories along with other runtimes instead?

exonum/src/runtime/types.rs Show resolved Hide resolved
exonum/tests/explorer/blockchain/mod.rs Outdated Show resolved Hide resolved
);

let blockchain = BlockchainBuilder::new(blockchain, genesis_config)
.with_runtime(rust_runtime)
.with_external_runtimes(external_runtimes)
Copy link
Contributor

Choose a reason for hiding this comment

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

This method looks like an redundant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Going to get rid of it during the Node::new() refactoring.

@aleksuss aleksuss changed the base branch from dynamic_services to master November 22, 2019 12:25
)
.with_additional_runtime(SampleRuntime::default())
let supervisor_service = SimpleSupervisor::new();
let genesis_config = GenesisConfigBuilder::with_consensus_config(consensus_config)
Copy link
Contributor

Choose a reason for hiding this comment

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

I suppose GenesisConfigBuilder::new().with_consensus_config(consensus_config) would be more idiomatic ?

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 any condition when we don't want to call with_consensus_config? I suggest to just rename this method to new, so it'll be GensisConfigBuilder::new(consensus_config).

Copy link
Contributor

@popzxc popzxc Dec 2, 2019

Choose a reason for hiding this comment

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

However maybe it can be done later.

Copy link
Contributor Author

@skletsun skletsun Dec 2, 2019

Choose a reason for hiding this comment

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

Well, perhaps it makes sense for this. But I'd also suggest to do this later.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that since it's not a common scenario, it's better to have a separate constructor like without_consensus_config.

@skletsun skletsun changed the title Extract genesis config and improve adding builtin services [ECR-3750] [ECR-3609] Extract genesis config and improve adding builtin services [ECR-3750] Dec 2, 2019
Copy link
Contributor

@slowli slowli left a comment

Choose a reason for hiding this comment

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

Couple of comments as of 2e803d0.

instances: Vec<InstanceInitParams>,
artifacts: HashMap<ArtifactId, Vec<u8>>,
artifacts: HashSet<ArtifactSpec>,
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a difference between HashMap<ArtifactId, Vec<u8>> and HashSet<ArtifactSpec>; the first overrides different specs for the same ArtifactId, while the second admits several ArtifactIds with different specs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing out, corrected.

let (id, runtime) = runtime.into();
if id == RustRuntime::ID as u32 || self.additional_runtimes.contains_key(&id) {
panic!("TestkitBuilder already contains runtime with id {}", id);
pub fn with_additional_runtime(mut self, runtime: impl Into<RuntimeInstance>) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not impl WellKnownRuntime?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I implemented it in analogue to the BlockchainBuilder.with_runtime() which has to accept RuntimeInstance as well, but for this case impl WellKnownRuntime looks better.

.or_insert_with(|| deploy_spec.into_bytes());
pub fn with_artifact(mut self, artifact: impl Into<ArtifactSpec>) -> Self {
let artifact = artifact.into();
if !self.artifacts.contains(&artifact) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: This check seems redundant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Re-wrote it to be actual again.

self,
runtimes: impl IntoIterator<Item = impl Into<(u32, Box<dyn Runtime>)>>,
) -> TestKit {
pub fn resume(self, runtimes: impl IntoIterator<Item = impl Into<RuntimeInstance>>) -> TestKit {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I'm almost sure this argument won't work with multiple runtimes of different types since the iterator items need to have the same type. Oh well, the old definition had the same problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, in fact, it is used exactly for this situation. More presize - in tests there are a few places where we pass RustRuntime this way.

test-suite/testkit/tests/interfaces/services.rs Outdated Show resolved Hide resolved
exonum/src/runtime/mod.rs Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
Copy link
Contributor

@popzxc popzxc left a comment

Choose a reason for hiding this comment

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

I've avoided all the nitpicks for this to get merged, but there is still one moment I can't agree with.

Once fixed, I'll approve.

}
}

impl<T: Into<ArtifactId>> From<T> for ArtifactSpec {
Copy link
Contributor

Choose a reason for hiding this comment

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

This conversion seems to be very error-prone, since it hides the fact of setting payload to empty value.
Service having no payload is not an invariant, but From conversion makes it feel like it is.

I suggest it to be a method with the name explaining it unambiguously, e.g. new_without_spec (and @slowli originally suggested it to be a method, and his suggestion still makes sense).

@@ -324,6 +371,15 @@ impl Display for InstanceSpec {
}
}

impl From<InstanceSpec> for InstanceInitParams {
fn from(spec: InstanceSpec) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here.

/// Adds a new Runtime to the list of available runtimes.
///
/// Note that you don't have to add a Rust Runtime, since it's included by default.
pub fn with_external_runtime(mut self, runtime: impl Into<(u32, Box<dyn Runtime>)>) -> Self {
pub fn with_external_runtime(mut self, runtime: impl WellKnownRuntime) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

One small nit: It turns that all possible runtimes are well known. :)

I think that we should think about trait name after that this PR will be merged.

exonum/src/blockchain/mod.rs Outdated Show resolved Hide resolved
@aleksuss aleksuss merged commit 0729abf into exonum:master Dec 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Changes affecting exonum core update changelog
Development

Successfully merging this pull request may close these issues.

6 participants