Skip to content

Commit

Permalink
Misc fixes (exonum#1740)
Browse files Browse the repository at this point in the history
  • Loading branch information
slowli authored and Oleksandr Anyshchenko committed Jan 27, 2020
1 parent bb29959 commit 8876837
Show file tree
Hide file tree
Showing 77 changed files with 507 additions and 459 deletions.
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,16 @@ jobs:
- pip3 install -e .venv/exonum-launcher
# Install integration tests.
- pip3 install -e $TRAVIS_BUILD_DIR/test-suite/exonum-py-tests --no-binary=protobuf protobuf
- nvm install 8 && nvm use 8
- nvm install 10 && nvm use 10
- cd $TRAVIS_BUILD_DIR/test-suite/testkit/server && npm install && cd $TRAVIS_BUILD_DIR
- cargo build -p exonum-testkit-server
- cargo install --path $TRAVIS_BUILD_DIR/examples/cryptocurrency-advanced/backend --force
- cargo build --manifest-path $TRAVIS_BUILD_DIR/examples/cryptocurrency/Cargo.toml --example demo
- cargo build -p exonum-cryptocurrency --example demo
script:
- python3 -m exonum_tests -v
- cd $TRAVIS_BUILD_DIR/examples/cryptocurrency/examples && ./test.sh
- cd $TRAVIS_BUILD_DIR/examples/cryptocurrency/examples && ./test.ps1
- cd $TRAVIS_BUILD_DIR/test-suite/testkit/server && npm run test:unix
- cd $TRAVIS_BUILD_DIR
after_script:
- deactivate
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,13 @@ Indexes iterators names has been shortened to `Iter`, `Keys` and `Values`. (#162
### exonum-testkit

- The following public APIs were removed/made private: (#1629)

- `compare` module;
- `txvec` macro;
- `TestKit::probe_all` and `TestKit::probe` methods.

- `TestKitBuilder::create` method was renamed to `build`. (#1740)

### exonum-time

- Modules were made private, crate now provides re-exports of necessary types
Expand Down Expand Up @@ -241,6 +244,9 @@ Indexes iterators names has been shortened to `Iter`, `Keys` and `Values`. (#162

- It is now possible to iterate over keys of the indexes within a group. (#1662)

- Unsafe optimizations / experimental features are now behind a `yolo` feature,
which is off by default. (#1740)

#### exonum-node

- Node logic (including P2P networking and consensus algorithm) was moved
Expand Down
1 change: 1 addition & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ use exonum_cryptocurrency_advanced as cryptocurrency;
fn main() -> Result<(), failure::Error> {
exonum::helpers::init_logger().unwrap();
NodeBuilder::new()
.with_service(cryptocurrency::CryptocurrencyService)
.run()
}
```
Expand Down
1 change: 0 additions & 1 deletion components/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

`exonum-api` crate provides an extensible interface for building backend-agnostic
HTTP APIs.

Within Exonum, this crate is used by [Rust services][rust-runtime] and in
plugins for the Exonum node.

Expand Down
8 changes: 2 additions & 6 deletions components/build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ There are several predefined sets of protobuf sources available for use.
Currently presented sets:

- Crypto sources: all the necessary crypto types used in services
and system proto-files. These types are Hash, PublicKey and Signature.
and system proto-files. These types are `Hash`, `PublicKey` and `Signature`.
- Exonum sources: types used in core and in system services such
as `Supervisor`.
as the supervisor.
- Common sources: types that can be used by various parts of Exonum.
- MerkleDB sources: types representing proofs of existence of element
in database.
Expand All @@ -29,12 +29,8 @@ Sample `build.rs` using `exonum-build`:

```rust
use exonum_build::ProtobufGenerator;
use std::env;

fn main() {
let current_dir = env::current_dir().expect("Failed to get current dir.");
let protos = current_dir.join("src/proto");

ProtobufGenerator::with_mod_name("protobuf_mod.rs")
.with_input_dir("src/proto")
.with_crypto()
Expand Down
41 changes: 17 additions & 24 deletions components/crypto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ Capabilities of `exonum-crypto` include:
- Generating key pairs for work with digital signatures;
- Creating and verifying of digital signatures.

The main backend for `exonum-crypto` is `sodiumoxide`, and used algorithms are:
The main backend for `exonum-crypto` is `sodiumoxide`, and the used algorithms are:

- `SHA256` for hashing.
- `Ed25519` for digital signatures.
- SHA-256 for hashing.
- Ed25519 for digital signatures.

Consult [the crate docs](https://docs.rs/exonum-crypto) for more details.

Expand All @@ -24,40 +24,33 @@ Consult [the crate docs](https://docs.rs/exonum-crypto) for more details.
Signing data and verifying the signature:

```rust
fn main() {
exonum_crypto::init();
let (public_key, secret_key) = exonum_crypto::gen_keypair();
let data = [1, 2, 3];
let signature = exonum_crypto::sign(&data, &secret_key);
assert!(exonum_crypto::verify(&signature, &data, &public_key));
}
exonum_crypto::init();
let (public_key, secret_key) = exonum_crypto::gen_keypair();
let data = [1, 2, 3];
let signature = exonum_crypto::sign(&data, &secret_key);
assert!(exonum_crypto::verify(&signature, &data, &public_key));
```

Hashing fixed amount of data:

```rust
fn main() {
exonum_crypto::init();
let data = [1, 2, 3];
let hash = exonum_crypto::hash(&data);
}
exonum_crypto::init();
let data = [1, 2, 3];
let hash = exonum_crypto::hash(&data);
```

Hashing data by chunks:

```rust
use exonum_crypto::HashStream;

fn main() {
exonum_crypto::init();

let data: Vec<[u8; 5]> = vec![[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]];
let mut hash_stream = HashStream::new();
for chunk in data {
hash_stream = hash_stream.update(&chunk);
}
let _ = hash_stream.hash();
exonum_crypto::init();
let data: Vec<[u8; 5]> = vec![[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]];
let mut hash_stream = HashStream::new();
for chunk in data {
hash_stream = hash_stream.update(&chunk);
}
let _ = hash_stream.hash();
```

## Usage
Expand Down
4 changes: 2 additions & 2 deletions components/derive/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ This crate provides several procedural macros for Exonum core and Exonum service
Overview of presented macros:

- `BinaryValue`: derive macro for `BinaryValue` trait of MerkleDB.
Depending on codec, implementation may use `ProtobufConvert` (default)
trait as base, or `serde` traits using `bincode`.
Depending on codec, the implementation may use `ProtobufConvert`
trait as base (default), or `serde` traits using `bincode`.
- `ObjectHash`: derive macro for `ObjectHash` trait of MerkleDB.
It can be used for any type that implements `BinaryValue` trait.
- `FromAccess`: derive macro for `FromAccess` trait for schemas of
Expand Down
2 changes: 1 addition & 1 deletion components/keys/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Exonum keys management
# Exonum Key Management

[![Travis Build Status](https://img.shields.io/travis/exonum/exonum/master.svg?label=Linux%20Build)](https://travis-ci.com/exonum/exonum)
[![License: Apache-2.0](https://img.shields.io/github/license/exonum/exonum.svg)](https://github.com/exonum/exonum/blob/master/LICENSE)
Expand Down
34 changes: 21 additions & 13 deletions components/merkledb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,38 @@ categories = ["cryptography", "database", "data-structures"]
description = "Persistent storage implementation based on RocksDB which provides APIs to work with Merkelized data structures."

[dependencies]
bincode = "1.1"
exonum-crypto = { path = "../crypto", version = "0.13.0-rc.2", features = ["with-serde"]}
exonum-proto = { path = "../proto", version = "0.13.0-rc.2", optional = true }

byteorder = "1.3"
chrono = "0.4.6"
crossbeam = "0.7.3"
enum-primitive-derive = "0.1"
exonum-crypto = { path = "../crypto", version = "0.13.0-rc.2", features = ["with-serde"]}
exonum-proto = { path = "../proto", version = "0.13.0-rc.2", optional = true }
failure = "0.1"
hex = "0.4"
leb128 = "0.2"
num-traits = "0.2"
protobuf = { version = "2.8.1", features = ["with-serde"], optional = true }
rocksdb = { version = "0.13", default-features = false }
rust_decimal = "1.0, <1.1.0" # The 1.1.0 version requires Rust 1.39+
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
smallvec = "1.0"
tempfile = "3.0"
uuid = { version="0.8", features = ["v4"] }
rand = "0.7"
protobuf = { version = "2.8.1", features = ["with-serde"], optional = true }
uuid = { version = "0.8", features = ["v4"] }

[dev-dependencies]
exonum-derive = { version = "0.13.0-rc.2", path = "../derive" }

assert_matches = "1.3.0"
bincode = "1.1"
criterion = "0.3"
exonum-derive = { version = "0.13.0-rc.2", path = "../derive" }
rand = "0.7"
rand_xorshift = "0.2.0"
proptest = "0.9"
hex = "0.4"
modifier = "0.1"
proptest = "0.9"
pretty_assertions = "0.6"
rand = "0.7"
rand_xorshift = "0.2.0"
serde_json = "1.0"
url = "2.0.0"

[[bench]]
Expand All @@ -55,14 +56,21 @@ harness = false

[features]
default = ["rocksdb_snappy", "with-protobuf"]
long_benchmarks = []
with-protobuf = ["with-serde", "protobuf", "exonum-proto"]
with-serde = []

# Compression options passed to RocksDB backend.
rocksdb_snappy = ["rocksdb/snappy"]
rocksdb_lz4 = ["rocksdb/lz4"]
rocksdb_zlib = ["rocksdb/zlib"]
rocksdb_zstd = ["rocksdb/zstd"]
rocksdb_bzip2 = ["rocksdb/bzip2"]

# Enables long benchmarks; does not influence main crate code.
long_benchmarks = []
# Enables `unsafe` optimizations / experimental features.
# Strongly discouraged for use in production.
yolo = []

[build-dependencies]
exonum-build = { version = "0.13.0-rc.2", path = "../build" }
4 changes: 1 addition & 3 deletions components/merkledb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ let list: ProofListIndex<_, u8> = ProofListIndex::new(list_name, &snapshot);
// Mutable list
let fork = db.fork();
let mut list: ProofListIndex<_, u8> = ProofListIndex::new(list_name, &fork);

```

After adding elements to the object you can obtain cryptographic proofs for their
Expand All @@ -70,13 +69,12 @@ assert_eq!(ListProof::Leaf(1), list.get_proof(0));
if let ListProof::Absent(_proof) = list.get_proof(1) {
println!("Element with index 1 is absent")
}

```

## Further Reading

- [Blockchain example](examples/blockchain.rs)
- [MerkleDB description in Exonum docs](https://exonum.com/doc/version/latest/architecture/storage/)
- [MerkleDB description in Exonum docs](https://exonum.com/doc/version/latest/architecture/merkledb/)

## License

Expand Down
4 changes: 2 additions & 2 deletions components/merkledb/benches/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,12 +315,12 @@ fn proof_list_index_verify_proofs(b: &mut Bencher<'_>, len: usize) {
for item in &data {
table.push(item.clone());
}
let table_root_hash = table.object_hash();
let table_hash = table.object_hash();
let proofs: Vec<_> = (0..len).map(|i| table.get_proof(i as u64)).collect();

b.iter(|| {
for proof in &proofs {
let items = proof.check_against_hash(table_root_hash).unwrap();
let items = proof.check_against_hash(table_hash).unwrap();
assert_eq!(items.entries().len(), 1);
}
});
Expand Down
38 changes: 23 additions & 15 deletions components/merkledb/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,23 @@
// 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.

use byteorder::{ByteOrder, LittleEndian};
use exonum_crypto::{hash, Hash, HashStream};
use exonum_crypto::{hash, Hash, HashStream, HASH_SIZE};
use failure::Fail;
use hex::FromHex;

use crate::{proof_map::ProofPath, BinaryValue};

const EMPTY_LIST_HASH: &str = "c6c0aa07f27493d2f2e5cff56c890a353a20086d6c25ec825128e12ae752b2d9";
const EMPTY_MAP_HASH: &str = "7324b5c72b51bb5d4c180f1109cfd347b60473882145841c39f3e584576296f9";
// "c6c0aa07f27493d2f2e5cff56c890a353a20086d6c25ec825128e12ae752b2d9" in hex.
const EMPTY_LIST_HASH: [u8; HASH_SIZE] = [
198, 192, 170, 7, 242, 116, 147, 210, 242, 229, 207, 245, 108, 137, 10, 53, 58, 32, 8, 109,
108, 37, 236, 130, 81, 40, 225, 42, 231, 82, 178, 217,
];
// "7324b5c72b51bb5d4c180f1109cfd347b60473882145841c39f3e584576296f9" in hex.
const EMPTY_MAP_HASH: [u8; HASH_SIZE] = [
115, 36, 181, 199, 43, 81, 187, 93, 76, 24, 15, 17, 9, 207, 211, 71, 182, 4, 115, 136, 33, 69,
132, 28, 57, 243, 229, 132, 87, 98, 150, 249,
];

/// Prefixes for different types of objects stored in the database. These prefixes are necessary
/// to provide domain separation among hashed objects of different types.
Expand Down Expand Up @@ -94,7 +102,7 @@ impl HashTag {
/// the hash of the root node of the Merkle tree corresponding to the list.
///
/// ```text
/// h = sha-256( HashTag::ListNode || len as u64 || merkle_root )
/// h = sha256( HashTag::ListNode || len as u64 || merkle_root )
/// ```
pub fn hash_list_node(len: u64, root: Hash) -> Hash {
let mut len_bytes = [0; 8];
Expand All @@ -107,25 +115,25 @@ impl HashTag {
.hash()
}

/// Hash of an empty Merkelized list.
/// Obtains hash of an empty Merkelized list.
///
/// ```text
/// h = sha-256( HashTag::ListNode || 0 || Hash::zero() )
/// h = sha256( HashTag::ListNode || 0 || Hash::zero() )
/// ```
pub fn empty_list_hash() -> Hash {
Hash::from_hex(EMPTY_LIST_HASH).unwrap()
Hash::new(EMPTY_LIST_HASH)
}

/// Computes the hash for a Merkelized list containing the given values.
pub fn hash_list<V: BinaryValue + ?Sized>(values: &[V]) -> Hash {
Self::hash_list_node(values.len() as u64, root_hash(values))
}

/// Hash of a Merkelized map with at least 2 entries. `root` is the recursively defined
/// Obtains hash of a Merkelized map. `root` is the recursively defined
/// hash of the root node of the binary Patricia Merkle tree corresponding to the map.
///
/// ```text
/// h = sha-256( HashTag::MapNode || merkle_root )
/// h = sha256( HashTag::MapNode || merkle_root )
/// ```
pub fn hash_map_node(root: Hash) -> Hash {
HashStream::new()
Expand All @@ -138,7 +146,7 @@ impl HashTag {
/// of the node.
///
/// ```text
/// h = sha-256(HashTag::MapBranchNode || <branch_node>)
/// h = sha256( HashTag::MapBranchNode || branch_node )
/// ```
///
/// See [`ProofMapIndex`] for details how branch nodes are serialized.
Expand All @@ -154,7 +162,7 @@ impl HashTag {
/// Hash of a Merkelized map with a single entry.
///
/// ``` text
/// h = sha-256( HashTag::MapBranchNode || <path> || <child_hash> )
/// h = sha256( HashTag::MapBranchNode || path || child_hash )
/// ```
pub fn hash_single_entry_map(path: &ProofPath, child_hash: &Hash) -> Hash {
HashStream::new()
Expand All @@ -168,10 +176,10 @@ impl HashTag {
///
/// Empty map hash:
/// ```text
/// sha-256( HashTag::MapNode || Hash::default() )
/// sha256( HashTag::MapNode || Hash::default() )
/// ```
pub fn empty_map_hash() -> Hash {
Hash::from_hex(EMPTY_MAP_HASH).unwrap()
Hash::new(EMPTY_MAP_HASH)
}
}

Expand Down Expand Up @@ -269,7 +277,7 @@ pub enum ValidationError<E: Fail> {
mod tests {
use exonum_crypto::{Hash, HashStream};

use super::HashTag;
use super::*;

#[test]
fn empty_list_hash() {
Expand Down
Loading

0 comments on commit 8876837

Please sign in to comment.