diff --git a/Cargo.lock b/Cargo.lock index a768e7451..a99f94a31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -596,6 +596,7 @@ dependencies = [ name = "ethcore-rpc" version = "1.7.0" dependencies = [ + "cid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.7.0", "ethcore 1.7.0", @@ -616,12 +617,14 @@ dependencies = [ "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "multihash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", "parity-updater 1.7.0", "rlp 0.1.0", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index cbfecf366..8b694b765 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -18,6 +18,9 @@ serde_derive = "0.9" serde_json = "0.9" time = "0.1" transient-hashmap = "0.4" +cid = "0.2.1" +multihash = "0.5" +rust-crypto = "0.2.36" jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 247edd8f7..1d3f4285d 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -27,6 +27,9 @@ extern crate serde; extern crate serde_json; extern crate time; extern crate transient_hashmap; +extern crate cid; +extern crate multihash; +extern crate crypto as rust_crypto; extern crate jsonrpc_core; extern crate jsonrpc_http_server as http; diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 7a7e940b8..75e92bcdc 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -44,6 +44,7 @@ mod codes { pub const REQUEST_REJECTED_LIMIT: i64 = -32041; pub const REQUEST_NOT_FOUND: i64 = -32042; pub const ENCRYPTION_ERROR: i64 = -32055; + pub const ENCODING_ERROR: i64 = -32058; pub const FETCH_ERROR: i64 = -32060; pub const NO_LIGHT_PEERS: i64 = -32065; pub const DEPRECATED: i64 = -32070; @@ -224,6 +225,14 @@ pub fn encryption_error(error: T) -> Error { } } +pub fn encoding_error(error: T) -> Error { + Error { + code: ErrorCode::ServerError(codes::ENCODING_ERROR), + message: "Encoding error.".into(), + data: Some(Value::String(format!("{:?}", error))), + } +} + pub fn database_error(error: T) -> Error { Error { code: ErrorCode::ServerError(codes::DATABASE_ERROR), diff --git a/rpc/src/v1/helpers/ipfs.rs b/rpc/src/v1/helpers/ipfs.rs new file mode 100644 index 000000000..53aa4be35 --- /dev/null +++ b/rpc/src/v1/helpers/ipfs.rs @@ -0,0 +1,38 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! IPFS utility functions + +use multihash; +use cid::{Cid, Codec, Version}; +use rust_crypto::sha2::Sha256; +use rust_crypto::digest::Digest; +use jsonrpc_core::Error; +use v1::types::Bytes; +use super::errors; + +/// Compute CIDv0 from protobuf encoded bytes. +pub fn cid(content: Bytes) -> Result { + let mut hasher = Sha256::new(); + hasher.input(&content.0); + let len = hasher.output_bytes(); + let mut buf = Vec::with_capacity(len); + buf.resize(len, 0); + hasher.result(&mut buf); + let mh = multihash::encode(multihash::Hash::SHA2256, &buf).map_err(errors::encoding_error)?; + let cid = Cid::new(Codec::DagProtobuf, Version::V0, &mh); + Ok(cid.to_string().into()) +} diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index 9d2064aa8..e43dfaa49 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -23,6 +23,7 @@ pub mod dispatch; pub mod fake_sign; pub mod informant; pub mod oneshot; +pub mod ipfs; mod network_settings; mod poll_manager; diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 569398193..8f654c652 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -30,7 +30,7 @@ use ethcore::account_provider::AccountProvider; use jsonrpc_core::Error; use jsonrpc_macros::Trailing; -use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings}; +use v1::helpers::{errors, ipfs, SigningQueue, SignerService, NetworkSettings}; use v1::helpers::dispatch::{LightDispatcher, DEFAULT_MAC}; use v1::metadata::Metadata; use v1::traits::Parity; @@ -342,4 +342,8 @@ impl Parity for ParityClient { capability: Capability::Light, }) } + + fn ipfs_cid(&self, content: Bytes) -> Result { + ipfs::cid(content) + } } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 83e0a505d..cb785daad 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -36,7 +36,7 @@ use updater::{Service as UpdateService}; use jsonrpc_core::Error; use jsonrpc_macros::Trailing; -use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings}; +use v1::helpers::{errors, ipfs, SigningQueue, SignerService, NetworkSettings}; use v1::helpers::accounts::unwrap_provider; use v1::helpers::dispatch::DEFAULT_MAC; use v1::metadata::Metadata; @@ -393,4 +393,8 @@ impl Parity for ParityClient where capability: Capability::Full, }) } + + fn ipfs_cid(&self, content: Bytes) -> Result { + ipfs::cid(content) + } } diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 8de64c25c..23b68e853 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -510,3 +510,14 @@ fn rpc_parity_node_kind() { assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } + +#[test] +fn rpc_parity_cid() { + let deps = Dependencies::new(); + let io = deps.default_client(); + + let request = r#"{"jsonrpc": "2.0", "method": "parity_cidV0", "params":["0x414243"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":"QmSF59MAENc8ZhM4aM1thuAE8w5gDmyfzkAvNoyPea7aDz","id":1}"#; + + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); +} diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index 8a15addae..ad910abd5 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -198,5 +198,9 @@ build_rpc_trait! { /// Get node kind info. #[rpc(name = "parity_nodeKind")] fn node_kind(&self) -> Result<::v1::types::NodeKind, Error>; + + /// Get IPFS CIDv0 given protobuf encoded bytes. + #[rpc(name = "parity_cidV0")] + fn ipfs_cid(&self, Bytes) -> Result; } }