Repository: input-output-hk/mithril
Pull request #474 (2022-09-01 16:29:54)

Update Blake dependency
This PR simply updates the Blake2 dependency. We use the new, more flexible design, of version 0.10.4 to use an output of 32 bytes instead of 64 bytes, making merkle paths half the size. 


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 5b306071b..2f5e88681 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -14,7 +14,7 @@ version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
 dependencies = [
- "getrandom 0.2.7",
+ "getrandom",
  "once_cell",
  "version_check",
 ]
@@ -294,13 +294,11 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "blake2"
-version = "0.9.2"
+version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174"
+checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388"
 dependencies = [
- "crypto-mac",
- "digest 0.9.0",
- "opaque-debug",
+ "digest 0.10.3",
 ]
 
 [[package]]
@@ -699,16 +697,6 @@ dependencies = [
  "typenum",
 ]
 
-[[package]]
-name = "crypto-mac"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
-dependencies = [
- "generic-array",
- "subtle",
-]
-
 [[package]]
 name = "csv"
 version = "1.1.6"
@@ -801,6 +789,7 @@ checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
 dependencies = [
  "block-buffer 0.10.2",
  "crypto-common",
+ "subtle",
 ]
 
 [[package]]
@@ -1101,17 +1090,6 @@ dependencies = [
  "version_check",
 ]
 
-[[package]]
-name = "getrandom"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
-]
-
 [[package]]
 name = "getrandom"
 version = "0.2.7"
@@ -1698,19 +1676,15 @@ dependencies = [
  "blake2",
  "blst",
  "criterion",
- "digest 0.9.0",
  "num-bigint 0.4.3",
  "num-rational 0.4.1",
  "num-traits",
  "proptest",
- "rand 0.7.3",
- "rand_chacha 0.3.1",
- "rand_core 0.6.3",
+ "rand_chacha",
+ "rand_core",
  "rayon",
  "rug",
  "serde",
- "serde_json",
- "sha2 0.9.9",
  "thiserror",
 ]
 
@@ -1719,7 +1693,6 @@ name = "mithril-aggregator"
 version = "0.1.0"
 dependencies = [
  "async-trait",
- "blake2",
  "chrono",
  "clap 3.2.17",
  "cloud-storage",
@@ -1752,7 +1725,6 @@ name = "mithril-client"
 version = "0.1.0"
 dependencies = [
  "async-trait",
- "blake2",
  "clap 3.2.17",
  "cli-table",
  "config",
@@ -1788,12 +1760,12 @@ dependencies = [
  "mithril",
  "mockall",
  "nom",
- "rand_chacha 0.3.1",
- "rand_core 0.6.3",
+ "rand_chacha",
+ "rand_core",
  "serde",
  "serde_json",
  "serde_yaml",
- "sha2 0.10.2",
+ "sha2",
  "slog",
  "slog-scope",
  "sqlite",
@@ -1830,7 +1802,6 @@ name = "mithril-signer"
 version = "0.1.0"
 dependencies = [
  "async-trait",
- "blake2",
  "clap 3.2.17",
  "config",
  "hex",
@@ -1838,8 +1809,8 @@ dependencies = [
  "mithril",
  "mithril-common",
  "mockall",
- "rand_chacha 0.3.1",
- "rand_core 0.6.3",
+ "rand_chacha",
+ "rand_core",
  "reqwest",
  "serde",
  "serde_json",
@@ -1857,13 +1828,12 @@ name = "mithrildemo"
 version = "0.1.0"
 dependencies = [
  "base64 0.13.0",
- "blake2",
  "clap 3.2.17",
  "hex",
  "log",
  "mithril-common",
- "rand_chacha 0.3.1",
- "rand_core 0.6.3",
+ "rand_chacha",
+ "rand_core",
  "serde",
  "serde_json",
 ]
@@ -1907,7 +1877,7 @@ dependencies = [
  "mime",
  "mime_guess",
  "quick-error 1.2.3",
- "rand 0.8.5",
+ "rand",
  "safemem",
  "tempfile",
  "twoway",
@@ -2444,8 +2414,8 @@ dependencies = [
  "lazy_static",
  "num-traits",
  "quick-error 2.0.1",
- "rand 0.8.5",
- "rand_chacha 0.3.1",
+ "rand",
+ "rand_chacha",
  "rand_xorshift",
  "regex-syntax",
  "rusty-fork",
@@ -2473,19 +2443,6 @@ dependencies = [
  "proc-macro2",
 ]
 
-[[package]]
-name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom 0.1.16",
- "libc",
- "rand_chacha 0.2.2",
- "rand_core 0.5.1",
- "rand_hc",
-]
-
 [[package]]
 name = "rand"
 version = "0.8.5"
@@ -2493,18 +2450,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
  "libc",
- "rand_chacha 0.3.1",
- "rand_core 0.6.3",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core 0.5.1",
+ "rand_chacha",
+ "rand_core",
 ]
 
 [[package]]
@@ -2514,16 +2461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
 dependencies = [
  "ppv-lite86",
- "rand_core 0.6.3",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
-dependencies = [
- "getrandom 0.1.16",
+ "rand_core",
 ]
 
 [[package]]
@@ -2532,16 +2470,7 @@ version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
 dependencies = [
- "getrandom 0.2.7",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
-dependencies = [
- "rand_core 0.5.1",
+ "getrandom",
 ]
 
 [[package]]
@@ -2550,7 +2479,7 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
 dependencies = [
- "rand_core 0.6.3",
+ "rand_core",
 ]
 
 [[package]]
@@ -2592,7 +2521,7 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
 dependencies = [
- "getrandom 0.2.7",
+ "getrandom",
  "redox_syscall",
  "thiserror",
 ]
@@ -2899,22 +2828,9 @@ dependencies = [
 
 [[package]]
 name = "sha2"
-version = "0.9.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
-dependencies = [
- "block-buffer 0.9.0",
- "cfg-if",
- "cpufeatures",
- "digest 0.9.0",
- "opaque-debug",
-]
-
-[[package]]
-name = "sha2"
-version = "0.10.2"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
+checksum = "899bf02746a2c92bf1053d9327dadb252b01af1f81f90cdb902411f518bc7215"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -3522,7 +3438,7 @@ dependencies = [
  "http",
  "httparse",
  "log",
- "rand 0.8.5",
+ "rand",
  "sha-1 0.9.8",
  "thiserror",
  "url",
@@ -3716,12 +3632,6 @@ dependencies = [
  "tracing",
 ]
 
-[[package]]
-name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
 [[package]]
 name = "wasi"
 version = "0.10.0+wasi-snapshot-preview1"
diff --git a/demo/protocol-demo/Cargo.toml b/demo/protocol-demo/Cargo.toml
index 07629d2d2..d4bc5a800 100644
--- a/demo/protocol-demo/Cargo.toml
+++ b/demo/protocol-demo/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2021"
 
 [dependencies]
 base64 = "0.13.0"
-blake2      = "0.9.2"
 clap = { version = "3.1.6", features = ["derive"] }
 hex = "0.4.3"
 log = "0.4.14"
diff --git a/mithril-aggregator/Cargo.toml b/mithril-aggregator/Cargo.toml
index 82be0235b..8acbedffc 100644
--- a/mithril-aggregator/Cargo.toml
+++ b/mithril-aggregator/Cargo.toml
@@ -7,7 +7,6 @@ description = "A Mithril Aggregator server"
 
 [dependencies]
 async-trait = "0.1.52"
-blake2      = "0.9.2"
 chrono = "0.4"
 clap = { version = "3.1.6", features = ["derive"] }
 cloud-storage = "0.11.0"
diff --git a/mithril-client/Cargo.toml b/mithril-client/Cargo.toml
index 2de6fdf46..bedcadb2e 100644
--- a/mithril-client/Cargo.toml
+++ b/mithril-client/Cargo.toml
@@ -7,7 +7,6 @@ description = "A Mithril Client"
 
 [dependencies]
 async-trait = "0.1.52"
-blake2      = "0.9.2"
 clap = { version = "3.1.6", features = ["derive"] }
 cli-table = "0.4"
 config = "0.13.1"
diff --git a/mithril-common/Cargo.toml b/mithril-common/Cargo.toml
index 7c504f387..8ef031920 100644
--- a/mithril-common/Cargo.toml
+++ b/mithril-common/Cargo.toml
@@ -9,7 +9,7 @@ crate-type = ["lib", "cdylib", "staticlib"]
 
 [dependencies]
 async-trait = "0.1.52"
-blake2 = "0.9.2"
+blake2 = "0.10.4"
 fixed = "1.15.0"
 glob = "0.3"
 hex = "0.4.3"
diff --git a/mithril-common/src/crypto_helper/types.rs b/mithril-common/src/crypto_helper/types.rs
index f8f30da48..ab233d073 100644
--- a/mithril-common/src/crypto_helper/types.rs
+++ b/mithril-common/src/crypto_helper/types.rs
@@ -1,14 +1,14 @@
+use blake2::{digest::consts::U32, Blake2b};
 use mithril::key_reg::KeyReg;
 use mithril::stm::{
     Index, Stake, StmAggrSig, StmAggrVerificationKey, StmClerk, StmInitializer, StmParameters,
     StmSig, StmSigner, StmVerificationKeyPoP,
 };
-
 /// A protocol version
 pub type ProtocolVersion<'a> = &'a str;
 
 // Protocol types alias
-type D = blake2::Blake2b;
+type D = Blake2b<U32>;
 /// The id of a mithril party.
 pub type ProtocolPartyId = String;
 /// Alias of [MithrilCore:Stake](https://mithril.network/mithril-core/doc/mithril/stm/type.Stake.html).
diff --git a/mithril-core/Cargo.toml b/mithril-core/Cargo.toml
index 3b8831935..aef7d0dc6 100644
--- a/mithril-core/Cargo.toml
+++ b/mithril-core/Cargo.toml
@@ -4,12 +4,11 @@ version = "0.1.0"
 edition = "2018"
 
 [dependencies]
-blake2      = "0.9.2"
+blake2      = "0.10.4"
 blst = { version = "0.3.10" }
-digest      = { version = "0.9.0", features = ["alloc"] }
-num-bigint  = {version = "0.4.0", optional = true }
-num-rational = {version = "0.4.0", optional = true }
-num-traits  = {version = "0.2.14", optional = true }
+num-bigint  = { version = "0.4.0", optional = true }
+num-rational = { version = "0.4.0", optional = true }
+num-traits  = { version = "0.2.14", optional = true }
 rand_core   = "0.6.3"
 rug = { version = "1.14", optional = true }
 serde = { version = "1", features = ["rc", "derive"] }
@@ -21,11 +20,8 @@ criterion   = { version = "0.3.5", features = ["html_reports"] }
 num-bigint  = "0.4.0"
 num-rational = "0.4.0"
 proptest    = "1.0.0"
-rand = "0.7"
 rand_chacha = "0.3.1"
 rayon       = "1.5.1"
-serde_json = "1"
-sha2 = "0.9"
 
 [[bench]]
 name = "stm"
diff --git a/mithril-core/benches/size_benches.rs b/mithril-core/benches/size_benches.rs
index 00d7a223d..7f380f426 100644
--- a/mithril-core/benches/size_benches.rs
+++ b/mithril-core/benches/size_benches.rs
@@ -1,14 +1,15 @@
-use blake2::Blake2b;
-use digest::{Digest, FixedOutput};
+use blake2::{
+    digest::consts::{U32, U64},
+    Blake2b, Digest,
+};
 use mithril::key_reg::KeyReg;
 use mithril::stm::{StmInitializer, StmParameters};
 use rand_chacha::ChaCha20Rng;
 use rand_core::{RngCore, SeedableRng};
-use sha2::Sha256;
 
 fn size<H>(k: u64, nparties: usize, hash_name: &str)
 where
-    H: Digest + Clone + FixedOutput + Sync + Send,
+    H: Digest + Clone + Sync + Send,
 {
     println!("+-------------------+");
     println!("| Hash: {} |", hash_name);
@@ -65,7 +66,7 @@ fn main() {
 
     let params: [(u64, usize); 2] = [(25, 300), (250, 2000)];
     for (k, nparties) in params {
-        size::<Blake2b>(k, nparties, "Blake2b 512");
-        size::<Sha256>(k, nparties, "   SHA256  ");
+        size::<Blake2b<U64>>(k, nparties, "Blake2b 512");
+        size::<Blake2b<U32>>(k, nparties, "Blake2b 256");
     }
 }
diff --git a/mithril-core/benches/stm.rs b/mithril-core/benches/stm.rs
index ea8820f3a..8749c2765 100644
--- a/mithril-core/benches/stm.rs
+++ b/mithril-core/benches/stm.rs
@@ -1,6 +1,6 @@
-use blake2::Blake2b;
+use blake2::digest::Digest;
+use blake2::{digest::consts::U32, Blake2b};
 use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
-use digest::{Digest, FixedOutput};
 use mithril::key_reg::KeyReg;
 use mithril::stm::{StmClerk, StmInitializer, StmParameters, StmSigner};
 use rand_chacha::ChaCha20Rng;
@@ -18,7 +18,7 @@ use std::fmt::Debug;
 
 fn stm_benches<H>(c: &mut Criterion, nr_parties: usize, params: StmParameters, hashing_alg: &str)
 where
-    H: Clone + Debug + Digest + FixedOutput + Send + Sync,
+    H: Clone + Debug + Digest + Send + Sync,
 {
     let mut group = c.benchmark_group(format!("STM/{}", hashing_alg));
     let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
@@ -82,7 +82,7 @@ where
 }
 
 fn stm_benches_blake_300(c: &mut Criterion) {
-    stm_benches::<Blake2b>(
+    stm_benches::<Blake2b<U32>>(
         c,
         300,
         StmParameters {
@@ -95,7 +95,7 @@ fn stm_benches_blake_300(c: &mut Criterion) {
 }
 
 fn stm_benches_blake_2000(c: &mut Criterion) {
-    stm_benches::<Blake2b>(
+    stm_benches::<Blake2b<U32>>(
         c,
         2000,
         StmParameters {
diff --git a/mithril-core/examples/key_registration.rs b/mithril-core/examples/key_registration.rs
index 50a8b8282..d270f0823 100644
--- a/mithril-core/examples/key_registration.rs
+++ b/mithril-core/examples/key_registration.rs
@@ -1,14 +1,14 @@
 //! This example shows how Key Registration is held. It is not held by a single central party,
 //! but instead by all the participants in the signature process. Contrarily to the full protocol
 //! run presented in `tests/integration.rs`, we explicitly treat each party individually.
-
+use blake2::{digest::consts::U32, Blake2b};
 use mithril::key_reg::{ClosedKeyReg, KeyReg};
 use mithril::stm::{Stake, StmClerk, StmInitializer, StmParameters, StmVerificationKeyPoP};
 
 use rand_chacha::ChaCha20Rng;
 use rand_core::{RngCore, SeedableRng};
 
-type H = blake2::Blake2b;
+type H = Blake2b<U32>;
 
 fn main() {
     let nparties = 4;
diff --git a/mithril-core/src/error.rs b/mithril-core/src/error.rs
index ec250b6c5..491d677c5 100644
--- a/mithril-core/src/error.rs
+++ b/mithril-core/src/error.rs
@@ -1,7 +1,7 @@
 //! Crate specific errors
 
 use crate::merkle_tree::Path;
-use digest::{Digest, FixedOutput};
+use blake2::digest::Digest;
 use {
     crate::multi_sig::{Signature, VerificationKey, VerificationKeyPoP},
     blst::BLST_ERROR,
@@ -29,7 +29,7 @@ pub enum MultiSignatureError {
 
 /// Errors which can be output by Mithril verification.
 #[derive(Debug, Clone, thiserror::Error)]
-pub enum StmSignatureError<D: Digest + FixedOutput> {
+pub enum StmSignatureError<D: Digest> {
     /// No quorum was found
     #[error("No Quorum was found.")]
     NoQuorum,
@@ -89,7 +89,7 @@ pub enum AggregationError {
 
 /// Error types related to merkle trees.
 #[derive(Debug, Clone, thiserror::Error)]
-pub enum MerkleTreeError<D: Digest + FixedOutput> {
+pub enum MerkleTreeError<D: Digest> {
     /// Serialization error
     #[error("Serialization of a merkle tree failed")]
     SerializationError,
@@ -119,7 +119,7 @@ pub enum RegisterError {
     UnregisteredInitializer,
 }
 
-impl<D: Digest + FixedOutput> From<RegisterError> for StmSignatureError<D> {
+impl<D: Digest> From<RegisterError> for StmSignatureError<D> {
     fn from(e: RegisterError) -> Self {
         match e {
             RegisterError::SerializationError => Self::SerializationError,
@@ -130,7 +130,7 @@ impl<D: Digest + FixedOutput> From<RegisterError> for StmSignatureError<D> {
     }
 }
 
-impl<D: Digest + FixedOutput> From<MerkleTreeError<D>> for StmSignatureError<D> {
+impl<D: Digest> From<MerkleTreeError<D>> for StmSignatureError<D> {
     fn from(e: MerkleTreeError<D>) -> Self {
         match e {
             MerkleTreeError::PathInvalid(e) => Self::PathInvalid(e),
@@ -139,7 +139,7 @@ impl<D: Digest + FixedOutput> From<MerkleTreeError<D>> for StmSignatureError<D>
     }
 }
 
-impl<D: Digest + FixedOutput> From<MultiSignatureError> for StmSignatureError<D> {
+impl<D: Digest> From<MultiSignatureError> for StmSignatureError<D> {
     fn from(e: MultiSignatureError) -> Self {
         match e {
             MultiSignatureError::SerializationError => Self::SerializationError,
diff --git a/mithril-core/src/key_reg.rs b/mithril-core/src/key_reg.rs
index c8a267807..bd83e61de 100644
--- a/mithril-core/src/key_reg.rs
+++ b/mithril-core/src/key_reg.rs
@@ -2,7 +2,7 @@
 
 use crate::error::RegisterError;
 use crate::multi_sig::{VerificationKey, VerificationKeyPoP};
-use digest::{Digest, FixedOutput};
+use blake2::digest::Digest;
 use std::collections::hash_map::Entry;
 use std::collections::HashMap;
 use std::sync::Arc;
@@ -23,7 +23,7 @@ pub struct KeyReg {
 /// Structure generated out of a closed registration containing the registered parties, total stake, and the merkle tree.
 /// One can only get a global `avk` out of a closed key registration.
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub struct ClosedKeyReg<D: Digest + FixedOutput> {
+pub struct ClosedKeyReg<D: Digest> {
     /// Ordered list of registered parties.
     pub reg_parties: Vec<RegParty>,
     /// Total stake of the registered parties.
@@ -57,7 +57,7 @@ impl KeyReg {
 
     /// Finalize the key registration.
     /// This function disables `KeyReg::register`, consumes the instance of `self`, and returns a `ClosedKeyReg`.
-    pub fn close<D: Digest + FixedOutput>(self) -> ClosedKeyReg<D> {
+    pub fn close<D: Digest>(self) -> ClosedKeyReg<D> {
         let mut total_stake: Stake = 0;
         let mut reg_parties = self
             .keys
@@ -85,7 +85,7 @@ impl KeyReg {
 mod tests {
     use super::*;
     use crate::multi_sig::SigningKey;
-    use blake2::Blake2b;
+    use blake2::{digest::consts::U32, Blake2b};
     use proptest::collection::vec;
     use proptest::prelude::*;
     use rand_chacha::ChaCha20Rng;
@@ -139,7 +139,7 @@ mod tests {
             }
 
             if !kr.keys.is_empty() {
-                let closed = kr.close::<Blake2b>();
+                let closed = kr.close::<Blake2b<U32>>();
                 let retrieved_keys = closed.reg_parties.iter().map(|r| (r.0, r.1)).collect::<HashMap<_,_>>();
                 assert!(retrieved_keys == keys);
             }
diff --git a/mithril-core/src/merkle_tree.rs b/mithril-core/src/merkle_tree.rs
index 73aeb0298..906ed87d0 100644
--- a/mithril-core/src/merkle_tree.rs
+++ b/mithril-core/src/merkle_tree.rs
@@ -2,7 +2,7 @@
 use crate::error::MerkleTreeError;
 use crate::multi_sig::VerificationKey;
 use crate::stm::Stake;
-use digest::{Digest, FixedOutput};
+use blake2::digest::Digest;
 use serde::{Deserialize, Serialize};
 use std::cmp::Ordering;
 use std::convert::TryFrom;
@@ -18,7 +18,7 @@ pub struct MTLeaf(pub VerificationKey, pub Stake);
 /// Contains all hashes on the path, and the index of the leaf.
 /// Used to verify that signatures come from eligible signers.
 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
-pub struct Path<D: Digest + FixedOutput> {
+pub struct Path<D: Digest> {
     pub(crate) values: Vec<Vec<u8>>,
     pub(crate) index: usize,
     hasher: PhantomData<D>,
@@ -28,7 +28,7 @@ pub struct Path<D: Digest + FixedOutput> {
 /// This structure differs from `MerkleTree` in that it does not contain all elements, which are not always necessary.
 /// Instead, it only contains the root of the tree.
 #[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct MerkleTreeCommitment<D: Digest + FixedOutput> {
+pub struct MerkleTreeCommitment<D: Digest> {
     /// Root of the merkle commitment.
     pub root: Vec<u8>,
     hasher: PhantomData<D>,
@@ -36,7 +36,7 @@ pub struct MerkleTreeCommitment<D: Digest + FixedOutput> {
 
 /// Tree of hashes, providing a commitment of data and its ordering.
 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
-pub struct MerkleTree<D: Digest + FixedOutput> {
+pub struct MerkleTree<D: Digest> {
     /// The nodes are stored in an array heap:
     /// * `nodes[0]` is the root,
     /// * the parent of `nodes[i]` is `nodes[(i-1)/2]`
@@ -78,7 +78,7 @@ impl Ord for MTLeaf {
     }
 }
 
-impl<D: Digest + Clone + FixedOutput> Path<D> {
+impl<D: Digest + Clone> Path<D> {
     /// Convert to bytes
     /// # Layout
     /// * Index representing the position in the Merkle Tree
@@ -108,7 +108,11 @@ impl<D: Digest + Clone + FixedOutput> Path<D> {
             .map_err(|_| MerkleTreeError::SerializationError)?;
         let mut values = Vec::with_capacity(len);
         for i in 0..len {
-            values.push(bytes[16 + i * D::output_size()..16 + (i + 1) * D::output_size()].to_vec());
+            values.push(
+                bytes[16 + i * <D as Digest>::output_size()
+                    ..16 + (i + 1) * <D as Digest>::output_size()]
+                    .to_vec(),
+            );
         }
 
         Ok(Path {
@@ -119,7 +123,7 @@ impl<D: Digest + Clone + FixedOutput> Path<D> {
     }
 }
 
-impl<D: Clone + Digest + FixedOutput> MerkleTreeCommitment<D> {
+impl<D: Clone + Digest> MerkleTreeCommitment<D> {
     /// Check an inclusion proof that `val` is part of the tree by traveling the whole path until the root.
     /// # Error
     /// If the merkle tree path is invalid, then the function fails.
@@ -129,9 +133,9 @@ impl<D: Clone + Digest + FixedOutput> MerkleTreeCommitment<D> {
         let mut h = D::digest(&val.to_bytes()).to_vec();
         for p in &proof.values {
             if (idx & 0b1) == 0 {
-                h = D::new().chain(h).chain(p).finalize().to_vec();
+                h = D::new().chain_update(h).chain_update(p).finalize().to_vec();
             } else {
-                h = D::new().chain(p).chain(h).finalize().to_vec();
+                h = D::new().chain_update(p).chain_update(h).finalize().to_vec();
             }
             idx >>= 1;
         }
@@ -146,7 +150,7 @@ impl<D: Clone + Digest + FixedOutput> MerkleTreeCommitment<D> {
     /// Outputs `msg || self` as a vector of bytes.
     pub fn concat_with_msg(&self, msg: &[u8]) -> Vec<u8>
     where
-        D: Digest + FixedOutput,
+        D: Digest,
     {
         let mut msgp = msg.to_vec();
         let mut bytes = self.root.clone();
@@ -156,7 +160,7 @@ impl<D: Clone + Digest + FixedOutput> MerkleTreeCommitment<D> {
     }
 }
 
-impl<D: Digest + FixedOutput> MerkleTree<D> {
+impl<D: Digest> MerkleTree<D> {
     /// Provided a non-empty list of leaves, `create` generates its corresponding `MerkleTree`.
     pub fn create(leaves: &[MTLeaf]) -> MerkleTree<D> {
         let n = leaves.len();
@@ -182,7 +186,11 @@ impl<D: Digest + FixedOutput> MerkleTree<D> {
             } else {
                 &z
             };
-            nodes[i] = D::new().chain(left).chain(right).finalize().to_vec();
+            nodes[i] = D::new()
+                .chain_update(left)
+                .chain_update(right)
+                .finalize()
+                .to_vec();
         }
 
         Self {
@@ -247,7 +255,7 @@ impl<D: Digest + FixedOutput> MerkleTree<D> {
     /// * Number of leaves committed in the Merkle Tree (as u64)
     /// * All nodes of the merkle tree (starting with the root)
     pub fn to_bytes(&self) -> Vec<u8> {
-        let mut result = Vec::with_capacity(8 + self.nodes.len() * D::output_size());
+        let mut result = Vec::with_capacity(8 + self.nodes.len() * <D as Digest>::output_size());
         result.extend_from_slice(&u64::try_from(self.n).unwrap().to_be_bytes());
         for node in self.nodes.iter() {
             result.extend_from_slice(node);
@@ -266,7 +274,11 @@ impl<D: Digest + FixedOutput> MerkleTree<D> {
         let num_nodes = n + n.next_power_of_two() - 1;
         let mut nodes = Vec::with_capacity(num_nodes);
         for i in 0..num_nodes {
-            nodes.push(bytes[8 + i * D::output_size()..8 + (i + 1) * D::output_size()].to_vec());
+            nodes.push(
+                bytes[8 + i * <D as Digest>::output_size()
+                    ..8 + (i + 1) * <D as Digest>::output_size()]
+                    .to_vec(),
+            );
         }
         Ok(Self {
             nodes,
@@ -313,16 +325,16 @@ fn sibling(i: usize) -> usize {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use blake2::Blake2b;
+    use blake2::{digest::consts::U32, Blake2b};
     use proptest::collection::vec;
     use proptest::prelude::*;
 
     prop_compose! {
         fn arb_tree(max_size: u32)
-                   (v in vec(any::<u64>(), 2..max_size as usize)) -> (MerkleTree<Blake2b>, Vec<MTLeaf>) {
+                   (v in vec(any::<u64>(), 2..max_size as usize)) -> (MerkleTree<Blake2b<U32>>, Vec<MTLeaf>) {
             let pks = vec![VerificationKey::default(); v.len()];
             let leaves = pks.into_iter().zip(v.into_iter()).map(|(key, stake)| MTLeaf(key, stake)).collect::<Vec<MTLeaf>>();
-             (MerkleTree::<Blake2b>::create(&leaves), leaves)
+             (MerkleTree::<Blake2b<U32>>::create(&leaves), leaves)
         }
     }
 
@@ -347,7 +359,7 @@ mod tests {
                 assert!(t.to_commitment().check(&values[i], &deserialised).is_ok());
 
                 let encoded = bincode::serialize(&pf).unwrap();
-                let decoded: Path<Blake2b> = bincode::deserialize(&encoded).unwrap();
+                let decoded: Path<Blake2b<U32>> = bincode::deserialize(&encoded).unwrap();
                 assert!(t.to_commitment().check(&values[i], &decoded).is_ok());
             })
         }
@@ -355,20 +367,20 @@ mod tests {
         #[test]
         fn test_bytes_tree((t, values) in arb_tree(5)) {
             let bytes = t.to_bytes();
-            let deserialised = MerkleTree::<Blake2b>::from_bytes(&bytes).unwrap();
-            let tree = MerkleTree::<Blake2b>::create(&values);
+            let deserialised = MerkleTree::<Blake2b<U32>>::from_bytes(&bytes).unwrap();
+            let tree = MerkleTree::<Blake2b<U32>>::create(&values);
             assert_eq!(tree.nodes, deserialised.nodes);
 
             let encoded = bincode::serialize(&t).unwrap();
-            let decoded: MerkleTree::<Blake2b> = bincode::deserialize(&encoded).unwrap();
+            let decoded: MerkleTree::<Blake2b<U32>> = bincode::deserialize(&encoded).unwrap();
             assert_eq!(tree.nodes, decoded.nodes);
         }
 
         #[test]
         fn test_bytes_tree_commitment((t, values) in arb_tree(5)) {
             let encoded = bincode::serialize(&t.to_commitment()).unwrap();
-            let decoded: MerkleTreeCommitment::<Blake2b> = bincode::deserialize(&encoded).unwrap();
-            let tree_commitment = MerkleTree::<Blake2b>::create(&values).to_commitment();
+            let decoded: MerkleTreeCommitment::<Blake2b<U32>> = bincode::deserialize(&encoded).unwrap();
+            let tree_commitment = MerkleTree::<Blake2b<U32>>::create(&values).to_commitment();
             assert_eq!(tree_commitment.root, decoded.root);
         }
     }
@@ -395,14 +407,14 @@ mod tests {
             i in any::<usize>(),
             (values, proof) in values_with_invalid_proof(10)
         ) {
-            let t = MerkleTree::<Blake2b>::create(&values[1..]);
+            let t = MerkleTree::<Blake2b<U32>>::create(&values[1..]);
             let index = i % (values.len() - 1);
             let path = Path{values: proof
                             .iter()
-                            .map(|x|  Blake2b::digest(x).to_vec())
+                            .map(|x|  Blake2b::<U32>::digest(x).to_vec())
                             .collect(),
                 index,
-                hasher: PhantomData::<Blake2b>::default()
+                hasher: PhantomData::<Blake2b<U32>>::default()
                 };
             assert!(t.to_commitment().check(&values[0], &path).is_err());
         }
diff --git a/mithril-core/src/multi_sig.rs b/mithril-core/src/multi_sig.rs
index 7b455cfe9..37043859a 100644
--- a/mithril-core/src/multi_sig.rs
+++ b/mithril-core/src/multi_sig.rs
@@ -7,7 +7,7 @@
 
 use crate::error::{blst_err_to_atms, MultiSignatureError};
 use crate::stm::Index;
-use blake2::{Blake2b, Digest};
+use blake2::{digest::consts::U16, Blake2b, Blake2b512, Digest};
 
 // We use `min_sig` resulting in signatures of 48 bytes and public keys of
 // 96. We can switch that around if desired by using `min_pk`.
@@ -357,11 +357,11 @@ impl Signature {
     /// for the lottery (i.e., we follow the VRF lottery mechanism as described in Section 16 of
     /// <https://hydra.iohk.io/build/8201171/download/1/ledger-spec.pdf>).
     pub fn eval(&self, msg: &[u8], index: Index) -> [u8; 64] {
-        let hasher = Blake2b::new()
-            .chain(b"map")
-            .chain(msg)
-            .chain(&index.to_le_bytes())
-            .chain(&self.to_bytes())
+        let hasher = Blake2b512::new()
+            .chain_update(b"map")
+            .chain_update(msg)
+            .chain_update(&index.to_le_bytes())
+            .chain_update(&self.to_bytes())
             .finalize();
 
         let mut output = [0u8; 64];
@@ -411,7 +411,7 @@ impl Signature {
         vks: &[VerificationKey],
         sigs: &[Signature],
     ) -> Result<(), MultiSignatureError> {
-        let mut hashed_sigs = Blake2b::new();
+        let mut hashed_sigs = Blake2b::<U16>::new();
         for sig in sigs {
             hashed_sigs.update(&sig.to_bytes());
         }
@@ -425,7 +425,7 @@ impl Signature {
             let mut hasher = hashed_sigs.clone();
             hasher.update(&index.to_be_bytes());
             signatures.push(&sig.0);
-            scalar_bytes[..16].copy_from_slice(&hasher.finalize().as_slice()[..16]);
+            scalar_bytes[..16].copy_from_slice(hasher.finalize().as_slice());
             scalars.push(blst_scalar { b: scalar_bytes });
             messages.push(msg); // todo: can we do this for the same message??
         }
diff --git a/mithril-core/src/stm.rs b/mithril-core/src/stm.rs
index 028c324d6..f6d84b305 100644
--- a/mithril-core/src/stm.rs
+++ b/mithril-core/src/stm.rs
@@ -6,6 +6,7 @@
 //!
 //! ```rust
 //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
+//! use blake2::{Blake2b, digest::consts::U32};
 //! use mithril::key_reg::KeyReg; // Import key registration functionality
 //! use mithril::stm::{StmClerk, StmInitializer, StmParameters, StmSig, StmSigner};
 //! use mithril::AggregationError;
@@ -15,7 +16,7 @@
 //! use rand_core::{RngCore, SeedableRng};
 //!
 //! let nparties = 4; // Use a small number of parties for this example
-//! type D = blake2::Blake2b; // Setting the hash function for convenience
+//! type D = Blake2b<U32>; // Setting the hash function for convenience
 //!
 //! let mut rng = ChaCha20Rng::from_seed([0u8; 32]); // create and initialize rng
 //! let mut msg = [0u8; 16]; // setting an arbitrary message
@@ -110,7 +111,7 @@ use crate::error::{AggregationError, RegisterError, StmSignatureError};
 use crate::key_reg::ClosedKeyReg;
 use crate::merkle_tree::{MTLeaf, MerkleTreeCommitment, Path};
 use crate::multi_sig::{Signature, SigningKey, VerificationKey, VerificationKeyPoP};
-use digest::{Digest, FixedOutput};
+use blake2::digest::Digest;
 use rand_core::{CryptoRng, RngCore};
 use serde::{Deserialize, Serialize};
 use std::collections::{BTreeMap, HashMap, HashSet};
@@ -166,7 +167,7 @@ pub struct StmInitializer {
 /// This instance can only be generated out of an `StmInitializer` and a `ClosedKeyReg`.
 /// This ensures that a `MerkleTree` root is not computed before all participants have registered.
 #[derive(Debug, Clone)]
-pub struct StmSigner<D: Digest + FixedOutput> {
+pub struct StmSigner<D: Digest> {
     mt_index: u64,
     stake: Stake,
     params: StmParameters,
@@ -179,7 +180,7 @@ pub struct StmSigner<D: Digest + FixedOutput> {
 /// Clerks can only be generated with the registration closed.
 /// This avoids that a Merkle Tree is computed before all parties have registered.
 #[derive(Debug, Clone)]
-pub struct StmClerk<D: Clone + Digest + FixedOutput> {
+pub struct StmClerk<D: Clone + Digest> {
     pub(crate) closed_reg: ClosedKeyReg<D>,
     pub(crate) params: StmParameters,
 }
@@ -190,7 +191,7 @@ pub struct StmClerk<D: Clone + Digest + FixedOutput> {
     serialize = "Path<D>: Serialize",
     deserialize = "Path<D>: Deserialize<'de>"
 ))]
-pub struct StmSig<D: Clone + Digest + FixedOutput> {
+pub struct StmSig<D: Clone + Digest> {
     /// The signature from the underlying MSP scheme.
     pub sigma: Signature,
     /// The Stm verification Key.
@@ -209,7 +210,7 @@ pub struct StmSig<D: Clone + Digest + FixedOutput> {
     serialize = "Path<D>: Serialize",
     deserialize = "Path<D>: Deserialize<'de>"
 ))]
-pub struct StmAggrVerificationKey<D: Clone + Digest + FixedOutput> {
+pub struct StmAggrVerificationKey<D: Clone + Digest> {
     mt_commitment: MerkleTreeCommitment<D>,
     total_stake: Stake,
 }
@@ -221,7 +222,7 @@ pub struct StmAggrVerificationKey<D: Clone + Digest + FixedOutput> {
     serialize = "Path<D>: Serialize",
     deserialize = "Path<D>: Deserialize<'de>"
 ))]
-pub struct StmAggrSig<D: Clone + Digest + FixedOutput> {
+pub struct StmAggrSig<D: Clone + Digest> {
     pub(crate) signatures: Vec<StmSig<D>>,
 }
 
@@ -288,9 +289,9 @@ impl StmInitializer {
     /// * this `StmSigner`'s parameter valuation
     /// * the `avk` as built from the current registered parties (according to the registration service)
     /// * the current total stake (according to the registration service)
-    /// Returns an error
-    /// If the initializer is not registered.
-    pub fn new_signer<D: Digest + FixedOutput + Clone>(
+    /// # Error
+    /// This function fails if the initializer is not registered.
+    pub fn new_signer<D: Digest + Clone>(
         self,
         closed_reg: ClosedKeyReg<D>,
     ) -> Result<StmSigner<D>, RegisterError> {
@@ -350,7 +351,7 @@ impl StmInitializer {
     }
 }
 
-impl<D: Clone + Digest + FixedOutput> StmSigner<D> {
+impl<D: Clone + Digest> StmSigner<D> {
     /// This function produces a signature following the description of Section 2.4.
     /// Once the signature is produced, this function checks whether any index in `[0,..,self.params.m]`
     /// wins the lottery by evaluating the dense mapping.
@@ -406,7 +407,7 @@ impl<D: Clone + Digest + FixedOutput> StmSigner<D> {
     /// # use mithril::stm::{Stake, StmInitializer, StmParameters, StmVerificationKeyPoP};
     /// # use rand_chacha::ChaCha20Rng;
     /// # use rand_core::{RngCore, SeedableRng};
-    /// # use blake2::{Blake2b, Digest};
+    /// # use blake2::{Blake2b, Digest, digest::consts::U32};
     ///
     /// # fn main() {
     ///     // Parameter. This information is broadcast (or known) to all
@@ -503,7 +504,7 @@ impl<D: Clone + Digest + FixedOutput> StmSigner<D> {
     ///     let _party_2_e2 = party_2_init_e2.new_signer(key_reg_e2_2);
     /// # }
     ///
-    /// # fn local_reg(stakes: &[u64], pks: &[StmVerificationKeyPoP]) -> ClosedKeyReg<Blake2b> {
+    /// # fn local_reg(stakes: &[u64], pks: &[StmVerificationKeyPoP]) -> ClosedKeyReg<Blake2b<U32>> {
     /// # let mut local_keyreg = KeyReg::init();
     /// #    for (&pk, stake) in pks.iter().zip(stakes.iter()) {
     /// #        local_keyreg.register(*stake, pk).unwrap();
@@ -532,7 +533,7 @@ impl<D: Clone + Digest + FixedOutput> StmSigner<D> {
     }
 }
 
-impl<D: Digest + FixedOutput + Clone> StmClerk<D> {
+impl<D: Digest + Clone> StmClerk<D> {
     /// Create a new `Clerk` from a closed registration instance.
     pub fn from_registration(params: &StmParameters, closed_reg: &ClosedKeyReg<D>) -> Self {
         Self {
@@ -652,7 +653,7 @@ impl<D: Digest + FixedOutput + Clone> StmClerk<D> {
     }
 }
 
-impl<D: Clone + Digest + FixedOutput> StmSig<D> {
+impl<D: Clone + Digest> StmSig<D> {
     /// Verify an stm signature by checking that the lottery was won, the merkle path is correct,
     /// the indexes are in the desired range and the underlying multi signature validates.
     pub fn verify(
@@ -741,21 +742,21 @@ impl<D: Clone + Digest + FixedOutput> StmSig<D> {
     }
 }
 
-impl<D: Clone + Digest + FixedOutput> Hash for StmSig<D> {
+impl<D: Clone + Digest> Hash for StmSig<D> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         Hash::hash_slice(&self.sigma.to_bytes(), state)
     }
 }
 
-impl<D: Clone + Digest + FixedOutput> PartialEq for StmSig<D> {
+impl<D: Clone + Digest> PartialEq for StmSig<D> {
     fn eq(&self, other: &Self) -> bool {
         self.sigma == other.sigma
     }
 }
 
-impl<D: Clone + Digest + FixedOutput> Eq for StmSig<D> {}
+impl<D: Clone + Digest> Eq for StmSig<D> {}
 
-impl<D: Clone + Digest + FixedOutput> From<&ClosedKeyReg<D>> for StmAggrVerificationKey<D> {
+impl<D: Clone + Digest> From<&ClosedKeyReg<D>> for StmAggrVerificationKey<D> {
     fn from(reg: &ClosedKeyReg<D>) -> Self {
         Self {
             mt_commitment: reg.merkle_tree.to_commitment(),
@@ -764,7 +765,7 @@ impl<D: Clone + Digest + FixedOutput> From<&ClosedKeyReg<D>> for StmAggrVerifica
     }
 }
 
-impl<D: Clone + Digest + FixedOutput> StmAggrSig<D> {
+impl<D: Clone + Digest> StmAggrSig<D> {
     /// Verify aggregate signature, by checking that
     /// * each signature contains only valid indices,
     /// * the lottery is indeed won by each one of them,
@@ -874,7 +875,7 @@ mod tests {
     use super::*;
     use crate::key_reg::*;
     use bincode;
-    use blake2::Blake2b;
+    use blake2::{digest::consts::U32, Blake2b};
     use proptest::collection::{hash_map, vec};
     use proptest::prelude::*;
     use proptest::test_runner::{RngAlgorithm::ChaCha, TestRng};
@@ -884,7 +885,7 @@ mod tests {
     use rand_core::SeedableRng;
 
     type Sig = StmAggrSig<D>;
-    type D = Blake2b;
+    type D = Blake2b<U32>;
 
     fn setup_equal_parties(params: StmParameters, nparties: usize) -> Vec<StmSigner<D>> {
         let stake = vec![1; nparties];
diff --git a/mithril-signer/Cargo.toml b/mithril-signer/Cargo.toml
index f20f20ade..c28e3435b 100644
--- a/mithril-signer/Cargo.toml
+++ b/mithril-signer/Cargo.toml
@@ -7,7 +7,6 @@ description = "A Mithril Signer"
 
 [dependencies]
 async-trait = "0.1.52"
-blake2      = "0.9.2"
 clap = { version = "3.1.6", features = ["derive"] }
 config = "0.13.1"
 hex = "0.4.3"
diff --git a/mithril-signer/src/single_signer.rs b/mithril-signer/src/single_signer.rs
index 0452fd6d3..0b633faa0 100644
--- a/mithril-signer/src/single_signer.rs
+++ b/mithril-signer/src/single_signer.rs
@@ -264,6 +264,6 @@ mod tests {
             .expect("compute aggregate verification signature should not fail")
             .expect("aggregate verification signature should not be empty");
 
-        assert_eq!("7b226d745f636f6d6d69746d656e74223a7b22726f6f74223a5b31362c3231352c3232312c332c3138372c3230342c39332c38372c36312c3232342c3234312c34362c3133332c3231362c34392c3136362c3234332c3130322c32302c38332c382c3130362c3134312c34302c31342c3232392c38372c39302c3136352c3230302c3134332c3136332c36382c3138322c3132372c3138332c3234382c3131302c33342c3130352c38352c3232332c34332c3231342c32362c3136352c38382c3138372c3138382c3137332c3234372c3230342c37312c3137322c3230372c3230372c37332c35322c39352c3137352c34342c3131332c3139352c3230315d2c22686173686572223a6e756c6c7d2c22746f74616c5f7374616b65223a323438367d", avk);
+        assert_eq!("7b226d745f636f6d6d69746d656e74223a7b22726f6f74223a5b3230362c3235312c39322c302c36382c3139302c3233382c3134302c3235332c3137362c31342c39302c3232302c3231342c3132372c382c3130392c3135332c3138302c39392c3232312c3131332c39362c32352c3231312c35302c34302c34392c3230352c34372c3138302c3139355d2c22686173686572223a6e756c6c7d2c22746f74616c5f7374616b65223a323438367d", avk);
     }
 }


Test patch:
diff --git a/mithril-core/tests/integration.rs b/mithril-core/tests/integration.rs
index 28cf4da02..b41b481a5 100644
--- a/mithril-core/tests/integration.rs
+++ b/mithril-core/tests/integration.rs
@@ -1,3 +1,5 @@
+use blake2::{digest::consts::U32, Blake2b};
+
 use mithril::key_reg::KeyReg;
 use mithril::stm::{StmClerk, StmInitializer, StmParameters, StmSig, StmSigner};
 use mithril::AggregationError;
@@ -7,7 +9,7 @@ use rayon::prelude::*;
 use rand_chacha::ChaCha20Rng;
 use rand_core::{RngCore, SeedableRng};
 
-type H = blake2::Blake2b;
+type H = Blake2b<U32>;
 
 #[test]
 fn test_full_protocol() {