diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bcf54ee46..a122a6f60 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,12 +12,11 @@ variables: CARGO_HOME: "${CI_PROJECT_DIR}/.cargo" CARGO_TARGET: x86_64-unknown-linux-gnu -.no_git: &no_git +.no_git: &no_git #disable git strategy variables: GIT_STRATEGY: none GIT_SUBMODULE_STRATEGY: none - .releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries") only: &releaseable_branches - stable @@ -25,7 +24,6 @@ variables: - tags - schedules - .collect_artifacts: &collect_artifacts artifacts: name: "${CI_JOB_NAME}_${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" @@ -34,34 +32,66 @@ variables: paths: - artifacts/ -test-linux: - stage: test - variables: - RUN_TESTS: all - script: - - scripts/gitlab/test-all.sh +.docker-cache-status: &docker-cache-status + dependencies: [] + before_script: + - sccache -s + after_script: - sccache -s tags: - linux-docker -test-audit: + +cargo-check 0 3: + stage: test + <<: *docker-cache-status + script: + - time cargo check --target $CARGO_TARGET --locked --no-default-features + +cargo-check 1 3: + stage: test + <<: *docker-cache-status + script: + - time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --no-default-features + +cargo-check 2 3: + stage: test + <<: *docker-cache-status + script: + - time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --features "mio" + +cargo-audit: stage: test script: - - set -e - - set -u - cargo audit tags: - linux-docker +validate-chainspecs: + stage: test + <<: *docker-cache-status + script: + - ./scripts/gitlab/validate-chainspecs.sh + +test-cpp: + stage: build + <<: *docker-cache-status + script: + - ./scripts/gitlab/test-cpp.sh + +test-linux: + stage: build + <<: *docker-cache-status + script: + - ./scripts/gitlab/test-linux.sh + build-linux: &build-linux stage: build only: *releaseable_branches + <<: *docker-cache-status script: - - scripts/gitlab/build-unix.sh - - sccache -s + - scripts/gitlab/build-linux.sh <<: *collect_artifacts - tags: - - linux-docker build-linux-i386: <<: *build-linux @@ -89,7 +119,7 @@ build-darwin: CC: gcc CXX: g++ script: - - scripts/gitlab/build-unix.sh + - scripts/gitlab/build-linux.sh tags: - rust-osx <<: *collect_artifacts @@ -102,7 +132,7 @@ build-windows: script: - sh scripts/gitlab/build-windows.sh tags: - - rust-windows + - rust-windows <<: *collect_artifacts publish-docker: @@ -178,17 +208,16 @@ publish-awss3-release: script: - echo "__________Push binaries to AWS S3____________" - case "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" in - (beta|stable|nightly) - export BUCKET=releases.parity.io/ethereum; - ;; - (*) - export BUCKET=builds-parity; - ;; - esac + (beta|stable|nightly) + export BUCKET=releases.parity.io/ethereum; + ;; + (*) + export BUCKET=builds-parity; + ;; + esac - aws s3 sync ./artifacts s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/ - after_script: - - aws s3 ls s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/ - --recursive --human-readable --summarize + - echo "__________Read from S3____________" + - aws s3 ls s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}} --recursive --human-readable --summarize tags: - linux-docker @@ -206,13 +235,12 @@ publish-docs: - linux-docker build-android: - stage: optional + stage: build image: parity/rust-android:gitlab-ci variables: CARGO_TARGET: armv7-linux-androideabi script: - - scripts/gitlab/build-unix.sh + - scripts/gitlab/build-linux.sh tags: - linux-docker - allow_failure: true <<: *collect_artifacts diff --git a/Cargo.lock b/Cargo.lock index 4b29e6525..64cbfa4a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2441,7 +2441,7 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", - "parity-ethereum 2.4.0", + "parity-ethereum 2.4.1", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2471,7 +2471,7 @@ dependencies = [ [[package]] name = "parity-ethereum" -version = "2.4.0" +version = "2.4.1" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2524,7 +2524,7 @@ dependencies = [ "parity-rpc 1.12.0", "parity-runtime 0.1.0", "parity-updater 1.12.0", - "parity-version 2.4.0", + "parity-version 2.4.1", "parity-whisper 0.1.0", "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2675,7 +2675,7 @@ dependencies = [ "parity-crypto 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parity-updater 1.12.0", - "parity-version 2.4.0", + "parity-version 2.4.1", "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2773,7 +2773,7 @@ dependencies = [ "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-hash-fetch 1.12.0", "parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-version 2.4.0", + "parity-version 2.4.1", "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2783,7 +2783,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "2.4.0" +version = "2.4.1" dependencies = [ "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index a6b1c005d..abcdd8a2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "Parity Ethereum client" name = "parity-ethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "2.4.0" +version = "2.4.1" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 90ebba39a..8205ae2ab 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -116,6 +116,9 @@ pub trait LightChainClient: Send + Sync { /// Query whether a block is known. fn is_known(&self, hash: &H256) -> bool; + /// Set the chain via a spec name. + fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()>; + /// Clear the queue. fn clear_queue(&self); @@ -164,6 +167,8 @@ pub struct Client { listeners: RwLock>>, fetcher: T, verify_full: bool, + /// A closure to call when we want to restart the client + exit_handler: Mutex>>, } impl Client { @@ -190,6 +195,7 @@ impl Client { listeners: RwLock::new(vec![]), fetcher, verify_full: config.verify_full, + exit_handler: Mutex::new(None), }) } @@ -360,6 +366,14 @@ impl Client { self.chain.heap_size_of_children() } + /// Set a closure to call when the client wants to be restarted. + /// + /// The parameter passed to the callback is the name of the new chain spec to use after + /// the restart. + pub fn set_exit_handler(&self, f: F) where F: Fn(String) + 'static + Send { + *self.exit_handler.lock() = Some(Box::new(f)); + } + /// Get a handle to the verification engine. pub fn engine(&self) -> &Arc { &self.engine @@ -563,6 +577,17 @@ impl LightChainClient for Client { Client::engine(self) } + fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()> { + trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name); + if let Some(ref h) = *self.exit_handler.lock() { + (*h)(new_spec_name); + Ok(()) + } else { + warn!("Not hypervised; cannot change chain."); + Err(()) + } + } + fn is_known(&self, hash: &H256) -> bool { self.status(hash) == BlockStatus::InChain } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index d40fc3033..0be48a636 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1706,15 +1706,17 @@ impl BlockChainClient for Client { self.config.spec_name.clone() } - fn set_spec_name(&self, new_spec_name: String) { + fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()> { trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name); if !self.enabled.load(AtomicOrdering::Relaxed) { - return; + return Err(()); } if let Some(ref h) = *self.exit_handler.lock() { (*h)(new_spec_name); + Ok(()) } else { warn!("Not hypervised; cannot change chain."); + Err(()) } } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 5236f7cd4..fbad806fd 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -863,7 +863,7 @@ impl BlockChainClient for TestBlockChainClient { fn spec_name(&self) -> String { "foundation".into() } - fn set_spec_name(&self, _: String) { unimplemented!(); } + fn set_spec_name(&self, _: String) -> Result<(), ()> { unimplemented!(); } fn disable(&self) { self.disabled.store(true, AtomicOrder::Relaxed); } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 2bc702622..8e4abc01c 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -360,7 +360,7 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra fn spec_name(&self) -> String; /// Set the chain via a spec name. - fn set_spec_name(&self, spec_name: String); + fn set_spec_name(&self, spec_name: String) -> Result<(), ()>; /// Disable the client from importing blocks. This cannot be undone in this session and indicates /// that a subsystem has reason to believe this executable incapable of syncing the chain. diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 2a42acfe2..4a16bed6c 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -1405,8 +1405,10 @@ impl Engine for AuthorityRound { let first = chain_head.number() == 0; - // apply immediate transitions. + // Apply transitions that don't require finality and should be enacted immediately (e.g from chain spec) if let Some(change) = self.validators.is_epoch_end(first, chain_head) { + info!(target: "engine", "Immediately applying validator set change signalled at block {}", chain_head.number()); + self.epoch_manager.lock().note_new_epoch(); let change = combine_proofs(chain_head.number(), &change, &[]); return Some(change) } diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 4413e6a77..9287f6272 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -634,7 +634,7 @@ impl LightDependencies { handler.extend_with(ParityAccounts::to_delegate(ParityAccountsClient::new(&self.accounts))); } Api::ParitySet => handler.extend_with( - light::ParitySetClient::new(self.sync.clone(), self.fetch.clone()) + light::ParitySetClient::new(self.client.clone(), self.sync.clone(), self.fetch.clone()) .to_delegate(), ), Api::Traces => handler.extend_with(light::TracesClient.to_delegate()), diff --git a/parity/run.rs b/parity/run.rs index 13e93c1e2..c4a3c7512 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -165,7 +165,9 @@ impl ::local_store::NodeInfo for FullNodeInfo { type LightClient = ::light::client::Client<::light_helpers::EpochFetch>; // helper for light execution. -fn execute_light_impl(cmd: RunCmd, logger: Arc) -> Result { +fn execute_light_impl(cmd: RunCmd, logger: Arc, on_client_rq: Cr) -> Result + where Cr: Fn(String) + 'static + Send +{ use light::client as light_client; use sync::{LightSyncParams, LightSync, ManageNetwork}; use parking_lot::{Mutex, RwLock}; @@ -367,6 +369,8 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc) -> Result(cmd: RunCmd, logger: Arc, Rr: Fn() + 'static + Send { if cmd.light { - execute_light_impl(cmd, logger) + execute_light_impl(cmd, logger, on_client_rq) } else { execute_impl(cmd, logger, on_client_rq, on_updater_rq) } diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index eebd76dbe..1ff40f979 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -59,6 +59,7 @@ mod codes { pub const NO_PEERS: i64 = -32066; pub const DEPRECATED: i64 = -32070; pub const EXPERIMENTAL_RPC: i64 = -32071; + pub const CANNOT_RESTART: i64 = -32080; } pub fn unimplemented(details: Option) -> Error { @@ -125,6 +126,14 @@ pub fn account(error: &str, details: T) -> Error { } } +pub fn cannot_restart() -> Error { + Error { + code: ErrorCode::ServerError(codes::CANNOT_RESTART), + message: "Parity could not be restarted. This feature is disabled in development mode and if the binary name isn't parity.".into(), + data: None, + } +} + /// Internal error signifying a logic error in code. /// Should not be used when function can just fail /// because of invalid parameters or incomplete node state. diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index f744095cb..0d5b2d225 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -24,6 +24,7 @@ use crypto::DEFAULT_MAC; use ethkey::{crypto::ecies, Brain, Generator}; use ethstore::random_phrase; use sync::{LightSyncInfo, LightSyncProvider, LightNetworkDispatcher, ManageNetwork}; +use updater::VersionInfo as UpdaterVersionInfo; use ethcore_logger::RotatingLogger; use jsonrpc_core::{Result, BoxFuture}; @@ -298,7 +299,7 @@ where } fn version_info(&self) -> Result { - Err(errors::light_unimplemented(None)) + Ok(UpdaterVersionInfo::this().into()) } fn releases_info(&self) -> Result> { @@ -388,7 +389,7 @@ where } fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture> { - let filter = match filter.try_into() { + let filter = match filter.try_into() { Ok(value) => value, Err(err) => return Box::new(future::err(err)), }; diff --git a/rpc/src/v1/impls/light/parity_set.rs b/rpc/src/v1/impls/light/parity_set.rs index c7bd7da17..1bd66dc68 100644 --- a/rpc/src/v1/impls/light/parity_set.rs +++ b/rpc/src/v1/impls/light/parity_set.rs @@ -23,6 +23,7 @@ use std::sync::Arc; use sync::ManageNetwork; use fetch::{self, Fetch}; use hash::keccak_buffer; +use light::client::LightChainClient; use jsonrpc_core::{Result, BoxFuture}; use jsonrpc_core::futures::Future; @@ -32,14 +33,16 @@ use v1::types::{Bytes, H160, H256, U256, ReleaseInfo, Transaction}; /// Parity-specific rpc interface for operations altering the settings. pub struct ParitySetClient { + client: Arc, net: Arc, fetch: F, } impl ParitySetClient { /// Creates new `ParitySetClient` with given `Fetch`. - pub fn new(net: Arc, fetch: F) -> Self { + pub fn new(client: Arc, net: Arc, fetch: F) -> Self { ParitySetClient { + client: client, net: net, fetch: fetch, } @@ -117,8 +120,8 @@ impl ParitySet for ParitySetClient { Err(errors::light_unimplemented(None)) } - fn set_spec_name(&self, _spec_name: String) -> Result { - Err(errors::light_unimplemented(None)) + fn set_spec_name(&self, spec_name: String) -> Result { + self.client.set_spec_name(spec_name).map(|_| true).map_err(|()| errors::cannot_restart()) } fn hash_content(&self, url: String) -> BoxFuture { diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index 3e0d26974..995b7988c 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -212,8 +212,7 @@ impl ParitySet for ParitySetClient where } fn set_spec_name(&self, spec_name: String) -> Result { - self.client.set_spec_name(spec_name); - Ok(true) + self.client.set_spec_name(spec_name).map(|_| true).map_err(|()| errors::cannot_restart()) } fn hash_content(&self, url: String) -> BoxFuture { @@ -241,7 +240,7 @@ impl ParitySet for ParitySetClient where let hash = hash.into(); Ok(self.miner.remove_transaction(&hash) - .map(|t| Transaction::from_pending(t.pending().clone())) + .map(|t| Transaction::from_pending(t.pending().clone())) ) } } diff --git a/scripts/gitlab/build-unix.sh b/scripts/gitlab/build-linux.sh similarity index 100% rename from scripts/gitlab/build-unix.sh rename to scripts/gitlab/build-linux.sh diff --git a/scripts/gitlab/test-all.sh b/scripts/gitlab/rust-changes.sh similarity index 87% rename from scripts/gitlab/test-all.sh rename to scripts/gitlab/rust-changes.sh index 925124b7a..236a20d59 100755 --- a/scripts/gitlab/test-all.sh +++ b/scripts/gitlab/rust-changes.sh @@ -1,7 +1,9 @@ #!/bin/bash +echo "________Running rust_changes.sh________" set -e # fail on any error set -u # treat unset variables as error +echo "__________Checking if Rust files were changed__________" git log --graph --oneline --decorate=short -n 10 case ${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}} in @@ -26,5 +28,3 @@ then fi rustup show - -exec ./test.sh diff --git a/scripts/gitlab/test-cpp.sh b/scripts/gitlab/test-cpp.sh new file mode 100755 index 000000000..9f825ec8c --- /dev/null +++ b/scripts/gitlab/test-cpp.sh @@ -0,0 +1,17 @@ +#!/bin/bash +echo "________Running test-cpp.sh________" +set -e # fail on any error +set -u # treat unset variables as error +#use nproc `linux only +THREADS=$(nproc) + +echo "________Running the C++ example________" +DIR=parity-clib/examples/cpp/build +mkdir -p $DIR +cd $DIR +cmake .. +make -j $THREADS +# Note: we don't try to run the example because it tries to sync Kovan, and we don't want +# that to happen on CI +cd - +rm -rf $DIR diff --git a/scripts/gitlab/test-linux.sh b/scripts/gitlab/test-linux.sh new file mode 100755 index 000000000..6a98d2f7b --- /dev/null +++ b/scripts/gitlab/test-linux.sh @@ -0,0 +1,12 @@ +#!/bin/bash +echo "________Running test-linux.sh________" +set -e # fail on any error +set -u # treat unset variables as error + +FEATURES="json-tests,ci-skip-tests" +OPTIONS="--release" +#use nproc `linux only +THREADS=$(nproc) + +echo "________Running Parity Full Test Suite________" +time cargo test $OPTIONS --features "$FEATURES" --locked --all --target $CARGO_TARGET -- --test-threads $THREADS diff --git a/scripts/validate_chainspecs.sh b/scripts/gitlab/validate-chainspecs.sh similarity index 51% rename from scripts/validate_chainspecs.sh rename to scripts/gitlab/validate-chainspecs.sh index c350445dd..9b7ef39e7 100755 --- a/scripts/validate_chainspecs.sh +++ b/scripts/gitlab/validate-chainspecs.sh @@ -1,7 +1,12 @@ -#!/usr/bin/env sh +#!/bin/bash +set -e # fail on any error +set -u # treat unset variables as error +echo "________Running validate_chainspecs.sh________" ERR=0 -cargo build --release -p chainspec + +echo "________Validate chainspecs________" +time cargo build --release -p chainspec for spec in ethcore/res/*.json; do if ! ./target/release/chainspec "$spec"; then ERR=1; fi diff --git a/test.sh b/test.sh deleted file mode 100755 index e7d8e2a78..000000000 --- a/test.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh -# Running Parity Full Test Suite -echo "________Running test.sh________" - -FEATURES="json-tests,ci-skip-tests" -OPTIONS="--release" -VALIDATE=1 -THREADS=8 - -set -e - - -validate () { - if [ "$VALIDATE" -eq "1" ] - then - echo "________Validate build________" - time cargo check $@ --locked --no-default-features - time cargo check $@ --locked --manifest-path util/io/Cargo.toml --no-default-features - time cargo check $@ --locked --manifest-path util/io/Cargo.toml --features "mio" - - # Validate chainspecs - echo "________Validate chainspecs________" - time ./scripts/validate_chainspecs.sh - else - echo "# not validating due to \$VALIDATE!=1" - fi -} - -cpp_test () { - case $CARGO_TARGET in - (x86_64-unknown-linux-gnu) - # Running the C++ example - echo "________Running the C++ example________" - DIR=parity-clib/examples/cpp/build - mkdir -p $DIR - cd $DIR - cmake .. - make -j $THREADS - # Note: we don't try to run the example because it tries to sync Kovan, and we don't want - # that to happen on CI - cd - - rm -rf $DIR - ;; - (*) - echo "________Skipping the C++ example________" - ;; - esac -} - -cargo_test () { - echo "________Running Parity Full Test Suite________" - git submodule update --init --recursive - time cargo test $OPTIONS --features "$FEATURES" --locked --all $@ -- --test-threads $THREADS -} - - -if [ "$CARGO_TARGET" ] -then - validate --target $CARGO_TARGET -else - validate -fi - -test "${RUN_TESTS}" = "all" && cpp_test - -if [ "$CARGO_TARGET" ] -then - - case "${RUN_TESTS}" in - (cargo|all) - cargo_test --target $CARGO_TARGET $@ - ;; - ('') - cargo_test --no-run --target $CARGO_TARGET $@ - ;; - esac -else - cargo_test $@ -fi diff --git a/util/version/Cargo.toml b/util/version/Cargo.toml index b5c608be3..62755866e 100644 --- a/util/version/Cargo.toml +++ b/util/version/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "parity-version" # NOTE: this value is used for Parity Ethereum version string (via env CARGO_PKG_VERSION) -version = "2.4.0" +version = "2.4.1" authors = ["Parity Technologies "] build = "build.rs"