Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33860c3f32 | ||
|
|
e1c1ecf0a5 | ||
|
|
72c8b79035 |
124
.gitlab-ci.yml
124
.gitlab-ci.yml
@@ -9,15 +9,13 @@ variables:
|
||||
GIT_STRATEGY: fetch
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
CI_SERVER_NAME: "GitLab CI"
|
||||
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 +23,6 @@ variables:
|
||||
- tags
|
||||
- schedules
|
||||
|
||||
|
||||
.collect_artifacts: &collect_artifacts
|
||||
artifacts:
|
||||
name: "${CI_JOB_NAME}_${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}"
|
||||
@@ -34,34 +31,89 @@ variables:
|
||||
paths:
|
||||
- artifacts/
|
||||
|
||||
test-linux:
|
||||
stage: test
|
||||
.docker-cache-status: &docker-cache-status
|
||||
variables:
|
||||
RUN_TESTS: all
|
||||
script:
|
||||
- scripts/gitlab/test-all.sh
|
||||
CARGO_HOME: "/cargo/${CI_JOB_NAME}"
|
||||
before_script:
|
||||
- SCCACHE_ERROR_LOG=/builds/parity/parity-ethereum/sccache_error.log RUST_LOG=sccache::server=debug sccache --start-server
|
||||
- sccache -s
|
||||
after_script:
|
||||
- echo "All crate-types:"
|
||||
- grep 'parse_arguments.*--crate-type' sccache_error.log | sed -re 's/.*"--crate-type", "([^"]+)".*/\1/' | sort | uniq -c
|
||||
- echo "Non-cacheable reasons:"
|
||||
- grep CannotCache sccache_error.log | sed -re 's/.*CannotCache\((.+)\).*/\1/' | sort | uniq -c
|
||||
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
|
||||
- sccache -s
|
||||
|
||||
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
|
||||
- sccache -s
|
||||
|
||||
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"
|
||||
- sccache -s
|
||||
|
||||
cargo-audit:
|
||||
stage: test
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- set -e
|
||||
- set -u
|
||||
- cargo audit
|
||||
- sccache -s
|
||||
|
||||
validate-chainspecs:
|
||||
stage: test
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- ./scripts/gitlab/validate-chainspecs.sh
|
||||
- sccache -s
|
||||
|
||||
test-cpp:
|
||||
stage: build
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- ./scripts/gitlab/test-cpp.sh
|
||||
- sccache -s
|
||||
|
||||
test-linux:
|
||||
stage: build
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- ./scripts/gitlab/test-linux.sh
|
||||
- sccache -s
|
||||
|
||||
build-android:
|
||||
stage: build
|
||||
image: parity/rust-android:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: armv7-linux-androideabi
|
||||
script:
|
||||
- scripts/gitlab/build-linux.sh
|
||||
tags:
|
||||
- linux-docker
|
||||
<<: *collect_artifacts
|
||||
|
||||
build-linux: &build-linux
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- scripts/gitlab/build-unix.sh
|
||||
- scripts/gitlab/build-linux.sh
|
||||
- sccache -s
|
||||
<<: *collect_artifacts
|
||||
tags:
|
||||
- linux-docker
|
||||
|
||||
build-linux-i386:
|
||||
<<: *build-linux
|
||||
@@ -86,10 +138,11 @@ build-darwin:
|
||||
only: *releaseable_branches
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-apple-darwin
|
||||
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
script:
|
||||
- scripts/gitlab/build-unix.sh
|
||||
- scripts/gitlab/build-linux.sh
|
||||
tags:
|
||||
- rust-osx
|
||||
<<: *collect_artifacts
|
||||
@@ -99,16 +152,17 @@ build-windows:
|
||||
only: *releaseable_branches
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-pc-windows-msvc
|
||||
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
|
||||
script:
|
||||
- sh scripts/gitlab/build-windows.sh
|
||||
tags:
|
||||
- rust-windows
|
||||
- rust-windows
|
||||
<<: *collect_artifacts
|
||||
|
||||
publish-docker:
|
||||
stage: publish
|
||||
only: *releaseable_branches
|
||||
cache: {}
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux
|
||||
tags:
|
||||
@@ -122,7 +176,7 @@ publish-snap: &publish-snap
|
||||
image: snapcore/snapcraft
|
||||
variables:
|
||||
BUILD_ARCH: amd64
|
||||
cache: {}
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux
|
||||
tags:
|
||||
@@ -178,17 +232,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
|
||||
|
||||
@@ -199,20 +252,9 @@ publish-docs:
|
||||
- tags
|
||||
except:
|
||||
- nightly
|
||||
cache: {}
|
||||
cache: {}
|
||||
script:
|
||||
- scripts/gitlab/publish-docs.sh
|
||||
tags:
|
||||
- linux-docker
|
||||
|
||||
build-android:
|
||||
stage: optional
|
||||
image: parity/rust-android:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: armv7-linux-androideabi
|
||||
script:
|
||||
- scripts/gitlab/build-unix.sh
|
||||
tags:
|
||||
- linux-docker
|
||||
allow_failure: true
|
||||
<<: *collect_artifacts
|
||||
|
||||
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -753,6 +753,7 @@ dependencies = [
|
||||
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"stats 0.1.0",
|
||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time-utils 0.1.0",
|
||||
"trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"trie-standardmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -2441,7 +2442,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.3",
|
||||
"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 +2472,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parity-ethereum"
|
||||
version = "2.4.0"
|
||||
version = "2.4.3"
|
||||
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 +2525,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.3",
|
||||
"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 +2676,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.3",
|
||||
"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 +2774,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.3",
|
||||
"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 +2784,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parity-version"
|
||||
version = "2.4.0"
|
||||
version = "2.4.3"
|
||||
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)",
|
||||
@@ -2826,6 +2827,7 @@ dependencies = [
|
||||
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time-utils 0.1.0",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -3781,6 +3783,10 @@ dependencies = [
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-utils"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "timer"
|
||||
version = "0.2.0"
|
||||
|
||||
@@ -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.3"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
@@ -138,7 +138,8 @@ members = [
|
||||
"util/triehash-ethereum",
|
||||
"util/keccak-hasher",
|
||||
"util/patricia-trie-ethereum",
|
||||
"util/fastmap"
|
||||
"util/fastmap",
|
||||
"util/time-utils"
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
|
||||
@@ -64,6 +64,7 @@ serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
stats = { path = "../util/stats" }
|
||||
tempdir = {version="0.3", optional = true}
|
||||
time-utils = { path = "../util/time-utils" }
|
||||
trace-time = "0.1"
|
||||
triehash-ethereum = { version = "0.2", path = "../util/triehash-ethereum" }
|
||||
unexpected = { path = "../util/unexpected" }
|
||||
|
||||
@@ -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<T> {
|
||||
listeners: RwLock<Vec<Weak<LightChainNotify>>>,
|
||||
fetcher: T,
|
||||
verify_full: bool,
|
||||
/// A closure to call when we want to restart the client
|
||||
exit_handler: Mutex<Option<Box<Fn(String) + 'static + Send>>>,
|
||||
}
|
||||
|
||||
impl<T: ChainDataFetcher> Client<T> {
|
||||
@@ -190,6 +195,7 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
listeners: RwLock::new(vec![]),
|
||||
fetcher,
|
||||
verify_full: config.verify_full,
|
||||
exit_handler: Mutex::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -360,6 +366,14 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
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<F>(&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<EthEngine> {
|
||||
&self.engine
|
||||
@@ -563,6 +577,17 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -255,4 +255,78 @@ mod tests {
|
||||
hash: Field::BackReference(0, 0),
|
||||
})).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn batch_tx_index_backreference() {
|
||||
let mut builder = Builder::default();
|
||||
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
|
||||
num: 100.into(), // header proof puts hash at output 0.
|
||||
})).unwrap();
|
||||
builder.push(Request::TransactionIndex(IncompleteTransactionIndexRequest {
|
||||
hash: Field::BackReference(0, 0),
|
||||
})).unwrap();
|
||||
|
||||
let mut batch = builder.build();
|
||||
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Hash(42.into())));
|
||||
|
||||
assert!(batch.next_complete().is_some());
|
||||
batch.answered += 1;
|
||||
assert!(batch.next_complete().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn batch_tx_index_backreference_wrong_output() {
|
||||
let mut builder = Builder::default();
|
||||
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
|
||||
num: 100.into(), // header proof puts hash at output 0.
|
||||
})).unwrap();
|
||||
builder.push(Request::TransactionIndex(IncompleteTransactionIndexRequest {
|
||||
hash: Field::BackReference(0, 0),
|
||||
})).unwrap();
|
||||
|
||||
let mut batch = builder.build();
|
||||
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Number(42)));
|
||||
|
||||
batch.next_complete();
|
||||
batch.answered += 1;
|
||||
batch.next_complete();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn batch_receipts_backreference() {
|
||||
let mut builder = Builder::default();
|
||||
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
|
||||
num: 100.into(), // header proof puts hash at output 0.
|
||||
})).unwrap();
|
||||
builder.push(Request::Receipts(IncompleteReceiptsRequest {
|
||||
hash: Field::BackReference(0, 0),
|
||||
})).unwrap();
|
||||
|
||||
let mut batch = builder.build();
|
||||
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Hash(42.into())));
|
||||
|
||||
assert!(batch.next_complete().is_some());
|
||||
batch.answered += 1;
|
||||
assert!(batch.next_complete().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn batch_receipts_backreference_wrong_output() {
|
||||
let mut builder = Builder::default();
|
||||
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
|
||||
num: 100.into(), // header proof puts hash at output 0.
|
||||
})).unwrap();
|
||||
builder.push(Request::Receipts(IncompleteReceiptsRequest {
|
||||
hash: Field::BackReference(0, 0),
|
||||
})).unwrap();
|
||||
|
||||
let mut batch = builder.build();
|
||||
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Number(42)));
|
||||
|
||||
batch.next_complete();
|
||||
batch.answered += 1;
|
||||
batch.next_complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -907,7 +907,7 @@ pub mod transaction_index {
|
||||
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||
if let Field::BackReference(req, idx) = self.hash {
|
||||
self.hash = match oracle(req, idx) {
|
||||
Ok(Output::Number(hash)) => Field::Scalar(hash.into()),
|
||||
Ok(Output::Hash(hash)) => Field::Scalar(hash.into()),
|
||||
_ => Field::BackReference(req, idx),
|
||||
}
|
||||
}
|
||||
@@ -982,7 +982,7 @@ pub mod block_receipts {
|
||||
fn fill<F>(&mut self, oracle: F) where F: Fn(usize, usize) -> Result<Output, NoSuchOutput> {
|
||||
if let Field::BackReference(req, idx) = self.hash {
|
||||
self.hash = match oracle(req, idx) {
|
||||
Ok(Output::Number(hash)) => Field::Scalar(hash.into()),
|
||||
Ok(Output::Hash(hash)) => Field::Scalar(hash.into()),
|
||||
_ => Field::BackReference(req, idx),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -47,6 +47,9 @@ use types::header::{Header, ExtendedHeader};
|
||||
use types::ancestry_action::AncestryAction;
|
||||
use unexpected::{Mismatch, OutOfBounds};
|
||||
|
||||
#[cfg(not(time_checked_add))]
|
||||
use time_utils::CheckedSystemTime;
|
||||
|
||||
mod finality;
|
||||
|
||||
/// `AuthorityRound` params.
|
||||
@@ -570,8 +573,15 @@ fn verify_timestamp(step: &Step, header_step: u64) -> Result<(), BlockError> {
|
||||
// NOTE This error might be returned only in early stage of verification (Stage 1).
|
||||
// Returning it further won't recover the sync process.
|
||||
trace!(target: "engine", "verify_timestamp: block too early");
|
||||
let oob = oob.map(|n| SystemTime::now() + Duration::from_secs(n));
|
||||
Err(BlockError::TemporarilyInvalid(oob).into())
|
||||
|
||||
let now = SystemTime::now();
|
||||
let found = now.checked_add(Duration::from_secs(oob.found)).ok_or(BlockError::TimestampOverflow)?;
|
||||
let max = oob.max.and_then(|m| now.checked_add(Duration::from_secs(m)));
|
||||
let min = oob.min.and_then(|m| now.checked_add(Duration::from_secs(m)));
|
||||
|
||||
let new_oob = OutOfBounds { min, max, found };
|
||||
|
||||
Err(BlockError::TemporarilyInvalid(new_oob).into())
|
||||
},
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
@@ -607,6 +617,7 @@ fn combine_proofs(signal_number: BlockNumber, set_proof: &[u8], finality_proof:
|
||||
stream.out()
|
||||
}
|
||||
|
||||
|
||||
fn destructure_proofs(combined: &[u8]) -> Result<(BlockNumber, &[u8], &[u8]), Error> {
|
||||
let rlp = Rlp::new(combined);
|
||||
Ok((
|
||||
@@ -622,7 +633,7 @@ trait AsMillis {
|
||||
|
||||
impl AsMillis for Duration {
|
||||
fn as_millis(&self) -> u64 {
|
||||
self.as_secs()*1_000 + (self.subsec_nanos()/1_000_000) as u64
|
||||
self.as_secs() * 1_000 + (self.subsec_nanos() / 1_000_000) as u64
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1405,8 +1416,10 @@ impl Engine<EthereumMachine> 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)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![warn(missing_docs, unused_extern_crates)]
|
||||
#![cfg_attr(feature = "time_checked_add", feature(time_checked_add))]
|
||||
|
||||
//! Ethcore library
|
||||
//!
|
||||
@@ -149,6 +150,9 @@ extern crate fetch;
|
||||
#[cfg(all(test, feature = "price-info"))]
|
||||
extern crate parity_runtime;
|
||||
|
||||
#[cfg(not(time_checked_add))]
|
||||
extern crate time_utils;
|
||||
|
||||
pub mod block;
|
||||
pub mod builtin;
|
||||
pub mod client;
|
||||
|
||||
@@ -40,24 +40,8 @@ use types::{BlockNumber, header::Header};
|
||||
use types::transaction::SignedTransaction;
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
|
||||
|
||||
/// Returns `Ok<SystemTime>` when the result less or equal to `i32::max_value` to prevent `SystemTime` to panic because
|
||||
/// it is platform specific, may be i32 or i64.
|
||||
///
|
||||
/// `Err<BlockError::TimestampOver` otherwise.
|
||||
///
|
||||
// FIXME: @niklasad1 - remove this when and use `SystemTime::checked_add`
|
||||
// when https://github.com/rust-lang/rust/issues/55940 is stabilized.
|
||||
fn timestamp_checked_add(sys: SystemTime, d2: Duration) -> Result<SystemTime, BlockError> {
|
||||
let d1 = sys.duration_since(UNIX_EPOCH).map_err(|_| BlockError::TimestampOverflow)?;
|
||||
let total_time = d1.checked_add(d2).ok_or(BlockError::TimestampOverflow)?;
|
||||
|
||||
if total_time.as_secs() <= i32::max_value() as u64 {
|
||||
Ok(sys + d2)
|
||||
} else {
|
||||
Err(BlockError::TimestampOverflow)
|
||||
}
|
||||
}
|
||||
#[cfg(not(time_checked_add))]
|
||||
use time_utils::CheckedSystemTime;
|
||||
|
||||
/// Preprocessed block data gathered in `verify_block_unordered` call
|
||||
pub struct PreverifiedBlock {
|
||||
@@ -323,9 +307,11 @@ pub fn verify_header_params(header: &Header, engine: &EthEngine, is_full: bool,
|
||||
|
||||
if is_full {
|
||||
const ACCEPTABLE_DRIFT: Duration = Duration::from_secs(15);
|
||||
// this will resist overflow until `year 2037`
|
||||
let max_time = SystemTime::now() + ACCEPTABLE_DRIFT;
|
||||
let invalid_threshold = max_time + ACCEPTABLE_DRIFT * 9;
|
||||
let timestamp = timestamp_checked_add(UNIX_EPOCH, Duration::from_secs(header.timestamp()))?;
|
||||
let timestamp = UNIX_EPOCH.checked_add(Duration::from_secs(header.timestamp()))
|
||||
.ok_or(BlockError::TimestampOverflow)?;
|
||||
|
||||
if timestamp > invalid_threshold {
|
||||
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: timestamp })))
|
||||
@@ -347,8 +333,11 @@ fn verify_parent(header: &Header, parent: &Header, engine: &EthEngine) -> Result
|
||||
let gas_limit_divisor = engine.params().gas_limit_bound_divisor;
|
||||
|
||||
if !engine.is_timestamp_valid(header.timestamp(), parent.timestamp()) {
|
||||
let min = timestamp_checked_add(SystemTime::now(), Duration::from_secs(parent.timestamp().saturating_add(1)))?;
|
||||
let found = timestamp_checked_add(SystemTime::now(), Duration::from_secs(header.timestamp()))?;
|
||||
let now = SystemTime::now();
|
||||
let min = now.checked_add(Duration::from_secs(parent.timestamp().saturating_add(1)))
|
||||
.ok_or(BlockError::TimestampOverflow)?;
|
||||
let found = now.checked_add(Duration::from_secs(header.timestamp()))
|
||||
.ok_or(BlockError::TimestampOverflow)?;
|
||||
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(min), found })))
|
||||
}
|
||||
if header.number() != parent.number() + 1 {
|
||||
@@ -835,11 +824,4 @@ mod tests {
|
||||
check_fail(unordered_test(&create_test_block_with_data(&header, &bad_transactions, &[]), &engine), TooManyTransactions(keypair.address()));
|
||||
unordered_test(&create_test_block_with_data(&header, &good_transactions, &[]), &engine).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checked_add_systime_dur() {
|
||||
assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 + 1, 0)).is_err());
|
||||
assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64, 0)).is_ok());
|
||||
assert!(timestamp_checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 - 1, 1_000_000_000)).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,7 +634,7 @@ impl<C: LightChainClient + 'static> LightDependencies<C> {
|
||||
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()),
|
||||
|
||||
@@ -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<RotatingLogger>) -> Result<RunningClient, String> {
|
||||
fn execute_light_impl<Cr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq: Cr) -> Result<RunningClient, String>
|
||||
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<RotatingLogger>) -> Result<Runnin
|
||||
service.add_notify(informant.clone());
|
||||
service.register_handler(informant.clone()).map_err(|_| "Unable to register informant handler".to_owned())?;
|
||||
|
||||
client.set_exit_handler(on_client_rq);
|
||||
|
||||
Ok(RunningClient {
|
||||
inner: RunningClientInner::Light {
|
||||
rpc: rpc_direct,
|
||||
@@ -930,7 +934,7 @@ pub fn execute<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>,
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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<String>) -> Error {
|
||||
@@ -125,6 +126,14 @@ pub fn account<T: fmt::Debug>(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.
|
||||
|
||||
@@ -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<VersionInfo> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
Ok(UpdaterVersionInfo::this().into())
|
||||
}
|
||||
|
||||
fn releases_info(&self) -> Result<Option<OperationsInfo>> {
|
||||
@@ -388,7 +389,7 @@ where
|
||||
}
|
||||
|
||||
fn logs_no_tx_hash(&self, filter: Filter) -> BoxFuture<Vec<Log>> {
|
||||
let filter = match filter.try_into() {
|
||||
let filter = match filter.try_into() {
|
||||
Ok(value) => value,
|
||||
Err(err) => return Box::new(future::err(err)),
|
||||
};
|
||||
|
||||
@@ -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<F> {
|
||||
client: Arc<LightChainClient>,
|
||||
net: Arc<ManageNetwork>,
|
||||
fetch: F,
|
||||
}
|
||||
|
||||
impl<F: Fetch> ParitySetClient<F> {
|
||||
/// Creates new `ParitySetClient` with given `Fetch`.
|
||||
pub fn new(net: Arc<ManageNetwork>, fetch: F) -> Self {
|
||||
pub fn new(client: Arc<LightChainClient>, net: Arc<ManageNetwork>, fetch: F) -> Self {
|
||||
ParitySetClient {
|
||||
client: client,
|
||||
net: net,
|
||||
fetch: fetch,
|
||||
}
|
||||
@@ -117,8 +120,8 @@ impl<F: Fetch> ParitySet for ParitySetClient<F> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn set_spec_name(&self, _spec_name: String) -> Result<bool> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
fn set_spec_name(&self, spec_name: String) -> Result<bool> {
|
||||
self.client.set_spec_name(spec_name).map(|_| true).map_err(|()| errors::cannot_restart())
|
||||
}
|
||||
|
||||
fn hash_content(&self, url: String) -> BoxFuture<H256> {
|
||||
|
||||
@@ -212,8 +212,7 @@ impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
|
||||
}
|
||||
|
||||
fn set_spec_name(&self, spec_name: String) -> Result<bool> {
|
||||
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<H256> {
|
||||
@@ -241,7 +240,7 @@ impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> 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()))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
17
scripts/gitlab/test-cpp.sh
Executable file
17
scripts/gitlab/test-cpp.sh
Executable file
@@ -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
|
||||
12
scripts/gitlab/test-linux.sh
Executable file
12
scripts/gitlab/test-linux.sh
Executable file
@@ -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
|
||||
@@ -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
|
||||
79
test.sh
79
test.sh
@@ -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
|
||||
9
util/time-utils/Cargo.toml
Normal file
9
util/time-utils/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "time-utils"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
description = "Time utilities for checked arithmetic"
|
||||
license = "GPL3"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
50
util/time-utils/src/lib.rs
Normal file
50
util/time-utils/src/lib.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
/// Temporary trait for `checked operations` on SystemTime until these are available in standard library
|
||||
pub trait CheckedSystemTime {
|
||||
/// Returns `Some<SystemTime>` when the result less or equal to `i32::max_value` to prevent `SystemTime` to panic because
|
||||
/// it is platform specific, possible representations are i32, i64, u64 and Duration. `None` otherwise
|
||||
fn checked_add(self, _d: Duration) -> Option<SystemTime>;
|
||||
/// Returns `Some<SystemTime>` when the result is successful and `None` when it is not
|
||||
fn checked_sub(self, _d: Duration) -> Option<SystemTime>;
|
||||
}
|
||||
|
||||
impl CheckedSystemTime for SystemTime {
|
||||
fn checked_add(self, dur: Duration) -> Option<SystemTime> {
|
||||
let this_dur = self.duration_since(UNIX_EPOCH).ok()?;
|
||||
let total_time = this_dur.checked_add(dur)?;
|
||||
|
||||
if total_time.as_secs() <= i32::max_value() as u64 {
|
||||
Some(self + dur)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn checked_sub(self, dur: Duration) -> Option<SystemTime> {
|
||||
let this_dur = self.duration_since(UNIX_EPOCH).ok()?;
|
||||
let total_time = this_dur.checked_sub(dur)?;
|
||||
|
||||
if total_time.as_secs() <= i32::max_value() as u64 {
|
||||
Some(self - dur)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
use super::CheckedSystemTime;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 + 1, 0)).is_none());
|
||||
assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64, 0)).is_some());
|
||||
assert!(CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::new(i32::max_value() as u64 - 1, 1_000_000_000)).is_some());
|
||||
|
||||
assert!(CheckedSystemTime::checked_sub(UNIX_EPOCH, Duration::from_secs(120)).is_none());
|
||||
assert!(CheckedSystemTime::checked_sub(SystemTime::now(), Duration::from_secs(1000)).is_some());
|
||||
}
|
||||
}
|
||||
@@ -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.3"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ serde_json = "1.0"
|
||||
slab = "0.3"
|
||||
smallvec = "0.6"
|
||||
tiny-keccak = "1.4"
|
||||
time-utils = { path = "../util/time-utils" }
|
||||
|
||||
jsonrpc-core = "10.0.1"
|
||||
jsonrpc-derive = "10.0.2"
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
//! Whisper P2P messaging system as a DevP2P subprotocol, with RPC and Rust
|
||||
//! interface.
|
||||
|
||||
#![cfg_attr(feature = "time_checked_add", feature(time_checked_add))]
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate parity_crypto as crypto;
|
||||
extern crate ethcore_network as network;
|
||||
@@ -46,6 +48,9 @@ extern crate log;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[cfg(not(time_checked_add))]
|
||||
extern crate time_utils;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate serde_json;
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ use rlp::{self, DecoderError, RlpStream, Rlp};
|
||||
use smallvec::SmallVec;
|
||||
use tiny_keccak::{keccak256, Keccak};
|
||||
|
||||
#[cfg(not(time_checked_add))]
|
||||
use time_utils::CheckedSystemTime;
|
||||
|
||||
/// Work-factor proved. Takes 3 parameters: size of message, time to live,
|
||||
/// and hash.
|
||||
///
|
||||
@@ -117,6 +120,7 @@ pub enum Error {
|
||||
EmptyTopics,
|
||||
LivesTooLong,
|
||||
IssuedInFuture,
|
||||
TimestampOverflow,
|
||||
ZeroTTL,
|
||||
}
|
||||
|
||||
@@ -133,6 +137,7 @@ impl fmt::Display for Error {
|
||||
Error::LivesTooLong => write!(f, "Message claims to be issued before the unix epoch."),
|
||||
Error::IssuedInFuture => write!(f, "Message issued in future."),
|
||||
Error::ZeroTTL => write!(f, "Message live for zero time."),
|
||||
Error::TimestampOverflow => write!(f, "Timestamp overflow"),
|
||||
Error::EmptyTopics => write!(f, "Message has no topics."),
|
||||
}
|
||||
}
|
||||
@@ -226,10 +231,6 @@ impl rlp::Decodable for Envelope {
|
||||
}
|
||||
}
|
||||
|
||||
/// Error indicating no topics.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct EmptyTopics;
|
||||
|
||||
/// Message creation parameters.
|
||||
/// Pass this to `Message::create` to make a message.
|
||||
pub struct CreateParams {
|
||||
@@ -255,11 +256,11 @@ pub struct Message {
|
||||
impl Message {
|
||||
/// Create a message from creation parameters.
|
||||
/// Panics if TTL is 0.
|
||||
pub fn create(params: CreateParams) -> Result<Self, EmptyTopics> {
|
||||
pub fn create(params: CreateParams) -> Result<Self, Error> {
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use rand::{Rng, SeedableRng, XorShiftRng};
|
||||
|
||||
if params.topics.is_empty() { return Err(EmptyTopics) }
|
||||
if params.topics.is_empty() { return Err(Error::EmptyTopics) }
|
||||
|
||||
let mut rng = {
|
||||
let mut thread_rng = ::rand::thread_rng();
|
||||
@@ -270,7 +271,8 @@ impl Message {
|
||||
assert!(params.ttl > 0);
|
||||
|
||||
let expiry = {
|
||||
let after_mining = SystemTime::now() + Duration::from_millis(params.work);
|
||||
let after_mining = SystemTime::now().checked_sub(Duration::from_millis(params.work))
|
||||
.ok_or(Error::TimestampOverflow)?;
|
||||
let since_epoch = after_mining.duration_since(time::UNIX_EPOCH)
|
||||
.expect("time after now is after unix epoch; qed");
|
||||
|
||||
@@ -357,7 +359,10 @@ impl Message {
|
||||
(envelope.expiry - envelope.ttl).saturating_sub(LEEWAY_SECONDS)
|
||||
);
|
||||
|
||||
if time::UNIX_EPOCH + issue_time_adjusted > now {
|
||||
let issue_time_adjusted = time::UNIX_EPOCH.checked_add(issue_time_adjusted)
|
||||
.ok_or(Error::TimestampOverflow)?;
|
||||
|
||||
if issue_time_adjusted > now {
|
||||
return Err(Error::IssuedInFuture);
|
||||
}
|
||||
|
||||
@@ -400,8 +405,8 @@ impl Message {
|
||||
}
|
||||
|
||||
/// Get the expiry time.
|
||||
pub fn expiry(&self) -> SystemTime {
|
||||
time::UNIX_EPOCH + Duration::from_secs(self.envelope.expiry)
|
||||
pub fn expiry(&self) -> Option<SystemTime> {
|
||||
time::UNIX_EPOCH.checked_add(Duration::from_secs(self.envelope.expiry))
|
||||
}
|
||||
|
||||
/// Get the topics.
|
||||
|
||||
@@ -223,7 +223,10 @@ impl Messages {
|
||||
}
|
||||
}
|
||||
|
||||
let expiry = message.expiry();
|
||||
let expiry = match message.expiry() {
|
||||
Some(time) => time,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
self.cumulative_size += message.encoded_size();
|
||||
|
||||
@@ -232,8 +235,8 @@ impl Messages {
|
||||
|
||||
let sorted_entry = SortedEntry {
|
||||
slab_id: id,
|
||||
work_proved: work_proved,
|
||||
expiry: expiry,
|
||||
work_proved,
|
||||
expiry,
|
||||
};
|
||||
|
||||
match self.sorted.binary_search(&sorted_entry) {
|
||||
|
||||
Reference in New Issue
Block a user