Skip to content

Commit 8c3a9b0

Browse files
authored
Merge pull request #1904 from input-output-hk/jpraynaud/1903-handle-multiple-merkle-tree-storage-backend
Optimize memory usage of signer for Cardano transactions
2 parents 3d75d3f + a897e21 commit 8c3a9b0

File tree

26 files changed

+631
-214
lines changed

26 files changed

+631
-214
lines changed

CHANGELOG.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ As a minor extension, we have adopted a slightly different versioning convention
99

1010
## Mithril Distribution [XXXX] - UNRELEASED
1111

12-
- Support for Mithril nodes footprint support in Prometheus monitoring in infrastructure
13-
- Add support for custom HTTP headers in Mithril client WASM library
14-
- Support `file://` URLs for snapshot locations
12+
- Support for Mithril nodes footprint support in Prometheus monitoring in infrastructure.
13+
14+
- Add support for custom HTTP headers in Mithril client WASM library.
15+
16+
- Support `file://` URLs for snapshot locations in Mithril client.
17+
18+
- Support for Mithril signer memory optimization when signing Cardano transactions with multiple Merkle tree storage backends.
1519

1620
- **UNSTABLE** Cardano stake distribution certification:
1721

@@ -102,13 +106,9 @@ As a minor extension, we have adopted a slightly different versioning convention
102106
- **UNSTABLE** Cardano transactions certification:
103107

104108
- Support computation of the Cardano Transactions signature and proving with the pre-computed Block Range Merkle Roots retrieved from the database.
105-
106109
- Prune Cardano Transactions from the signer database after the Block Range Merkle Roots have been computed.
107-
108110
- Implement a Chain Reader which retrieves blocks from the Cardano chain with Pallas through the `chainsync` mini-protocol.
109-
110111
- Implement a Resource Pool and use it for caching Block Range Merkle maps used by the Cardano transactions prover and improving the throughput.
111-
112112
- Change the beacon of the Cardano Transactions to a block number instead of an immutable file number.
113113

114114
- Crates versions:

Cargo.lock

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/mithril-persistence/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-persistence"
3-
version = "0.2.23"
3+
version = "0.2.24"
44
description = "Common types, interfaces, and utilities to persist data for Mithril nodes."
55
authors = { workspace = true }
66
edition = { workspace = true }

internal/mithril-persistence/src/database/repository/cardano_transaction_repository.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::sync::Arc;
44
use anyhow::Context;
55
use async_trait::async_trait;
66

7-
use mithril_common::crypto_helper::MKTreeNode;
7+
use mithril_common::crypto_helper::{MKTreeNode, MKTreeStorer};
88
use mithril_common::entities::{
99
BlockHash, BlockNumber, BlockRange, CardanoTransaction, ChainPoint, SlotNumber, TransactionHash,
1010
};
@@ -296,7 +296,7 @@ impl CardanoTransactionRepository {
296296
}
297297

298298
#[async_trait]
299-
impl BlockRangeRootRetriever for CardanoTransactionRepository {
299+
impl<S: MKTreeStorer> BlockRangeRootRetriever<S> for CardanoTransactionRepository {
300300
async fn retrieve_block_range_roots<'a>(
301301
&'a self,
302302
up_to_beacon: BlockNumber,

mithril-aggregator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.5.55"
3+
version = "0.5.56"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-aggregator/src/dependency_injection/builder.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ use mithril_common::{
2121
chain_observer::{CardanoCliRunner, ChainObserver, ChainObserverBuilder, FakeObserver},
2222
chain_reader::{ChainBlockReader, PallasChainReader},
2323
crypto_helper::{
24-
ProtocolGenesisSigner, ProtocolGenesisVerificationKey, ProtocolGenesisVerifier,
24+
MKTreeStoreInMemory, ProtocolGenesisSigner, ProtocolGenesisVerificationKey,
25+
ProtocolGenesisVerifier,
2526
},
2627
digesters::{
2728
cache::{ImmutableFileDigestCacheProvider, JsonImmutableFileDigestCacheProviderBuilder},
@@ -1085,7 +1086,9 @@ impl DependenciesBuilder {
10851086
));
10861087
let transactions_importer = self.get_transactions_importer().await?;
10871088
let block_range_root_retriever = self.get_transaction_repository().await?;
1088-
let cardano_transactions_builder = Arc::new(CardanoTransactionsSignableBuilder::new(
1089+
let cardano_transactions_builder = Arc::new(CardanoTransactionsSignableBuilder::<
1090+
MKTreeStoreInMemory,
1091+
>::new(
10891092
transactions_importer,
10901093
block_range_root_retriever,
10911094
self.get_logger()?,
@@ -1487,7 +1490,7 @@ impl DependenciesBuilder {
14871490
let transaction_retriever = self.get_transaction_repository().await?;
14881491
let block_range_root_retriever = self.get_transaction_repository().await?;
14891492
let logger = self.get_logger()?;
1490-
let prover_service = MithrilProverService::new(
1493+
let prover_service = MithrilProverService::<MKTreeStoreInMemory>::new(
14911494
transaction_retriever,
14921495
block_range_root_retriever,
14931496
mk_map_pool_size,

mithril-aggregator/src/services/cardano_transactions_importer.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use slog::{debug, Logger};
88
use tokio::{runtime::Handle, task};
99

1010
use mithril_common::cardano_block_scanner::{BlockScanner, ChainScannedBlocks};
11-
use mithril_common::crypto_helper::{MKTree, MKTreeNode};
11+
use mithril_common::crypto_helper::{MKTree, MKTreeNode, MKTreeStoreInMemory};
1212
use mithril_common::entities::{
1313
BlockNumber, BlockRange, CardanoTransaction, ChainPoint, SlotNumber,
1414
};
@@ -152,7 +152,7 @@ impl CardanoTransactionsImporter {
152152
continue;
153153
}
154154

155-
let merkle_root = MKTree::new(&transactions)?.compute_root()?;
155+
let merkle_root = MKTree::<MKTreeStoreInMemory>::new(&transactions)?.compute_root()?;
156156
block_ranges_with_merkle_root.push((block_range, merkle_root));
157157

158158
if block_ranges_with_merkle_root.len() >= 100 {
@@ -256,7 +256,10 @@ mod tests {
256256
.iter()
257257
.flat_map(|br| br.clone().into_transactions())
258258
.collect();
259-
MKTree::new(&tx).unwrap().compute_root().unwrap()
259+
MKTree::<MKTreeStoreInMemory>::new(&tx)
260+
.unwrap()
261+
.compute_root()
262+
.unwrap()
260263
}
261264

262265
#[tokio::test]

mithril-aggregator/src/services/prover.rs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{
88
};
99

1010
use mithril_common::{
11-
crypto_helper::{MKMap, MKMapNode, MKTree},
11+
crypto_helper::{MKMap, MKMapNode, MKTree, MKTreeStorer},
1212
entities::{
1313
BlockNumber, BlockRange, CardanoTransaction, CardanoTransactionsSetProof, TransactionHash,
1414
},
@@ -51,18 +51,18 @@ pub trait TransactionsRetriever: Sync + Send {
5151
}
5252

5353
/// Mithril prover
54-
pub struct MithrilProverService {
54+
pub struct MithrilProverService<S: MKTreeStorer> {
5555
transaction_retriever: Arc<dyn TransactionsRetriever>,
56-
block_range_root_retriever: Arc<dyn BlockRangeRootRetriever>,
57-
mk_map_pool: ResourcePool<MKMap<BlockRange, MKMapNode<BlockRange>>>,
56+
block_range_root_retriever: Arc<dyn BlockRangeRootRetriever<S>>,
57+
mk_map_pool: ResourcePool<MKMap<BlockRange, MKMapNode<BlockRange, S>, S>>,
5858
logger: Logger,
5959
}
6060

61-
impl MithrilProverService {
61+
impl<S: MKTreeStorer> MithrilProverService<S> {
6262
/// Create a new Mithril prover
6363
pub fn new(
6464
transaction_retriever: Arc<dyn TransactionsRetriever>,
65-
block_range_root_retriever: Arc<dyn BlockRangeRootRetriever>,
65+
block_range_root_retriever: Arc<dyn BlockRangeRootRetriever<S>>,
6666
mk_map_pool_size: usize,
6767
logger: Logger,
6868
) -> Self {
@@ -113,7 +113,7 @@ impl MithrilProverService {
113113
}
114114

115115
#[async_trait]
116-
impl ProverService for MithrilProverService {
116+
impl<S: MKTreeStorer> ProverService for MithrilProverService<S> {
117117
async fn compute_transactions_proofs(
118118
&self,
119119
up_to: BlockNumber,
@@ -126,7 +126,7 @@ impl ProverService for MithrilProverService {
126126
.await?;
127127

128128
// 2 - Compute block ranges sub Merkle trees
129-
let mk_trees: StdResult<Vec<(BlockRange, MKTree)>> = block_range_transactions
129+
let mk_trees: StdResult<Vec<(BlockRange, MKTree<S>)>> = block_range_transactions
130130
.into_iter()
131131
.map(|(block_range, transactions)| {
132132
let mk_tree = MKTree::new(&transactions)?;
@@ -183,7 +183,7 @@ impl ProverService for MithrilProverService {
183183
);
184184
mk_map_cache.clone()
185185
})
186-
.collect::<Vec<MKMap<_, _>>>();
186+
.collect::<Vec<MKMap<_, _, _>>>();
187187
debug!(self.logger, "Prover is draining the Merkle map pool");
188188
let discriminant_new = self.mk_map_pool.discriminant()? + 1;
189189
self.mk_map_pool.set_discriminant(discriminant_new)?;
@@ -211,7 +211,9 @@ impl ProverService for MithrilProverService {
211211
#[cfg(test)]
212212
mod tests {
213213
use anyhow::anyhow;
214-
use mithril_common::crypto_helper::{MKMap, MKMapNode, MKTreeNode};
214+
use mithril_common::crypto_helper::{
215+
MKMap, MKMapNode, MKTreeNode, MKTreeStoreInMemory, MKTreeStorer,
216+
};
215217
use mithril_common::entities::CardanoTransaction;
216218
use mithril_common::test_utils::CardanoTransactionsBuilder;
217219
use mockall::mock;
@@ -220,10 +222,10 @@ mod tests {
220222
use super::*;
221223

222224
mock! {
223-
pub BlockRangeRootRetrieverImpl { }
225+
pub BlockRangeRootRetrieverImpl<S: MKTreeStorer> { }
224226

225227
#[async_trait]
226-
impl BlockRangeRootRetriever for BlockRangeRootRetrieverImpl {
228+
impl<S: MKTreeStorer> BlockRangeRootRetriever<S> for BlockRangeRootRetrieverImpl<S> {
227229
async fn retrieve_block_range_roots<'a>(
228230
&'a self,
229231
up_to_beacon: BlockNumber,
@@ -232,11 +234,13 @@ mod tests {
232234
async fn compute_merkle_map_from_block_range_roots(
233235
&self,
234236
up_to_beacon: BlockNumber,
235-
) -> StdResult<MKMap<BlockRange, MKMapNode<BlockRange>>>;
237+
) -> StdResult<MKMap<BlockRange, MKMapNode<BlockRange, S>, S>>;
236238
}
237239
}
238240

239241
mod test_data {
242+
use mithril_common::crypto_helper::MKTreeStoreInMemory;
243+
240244
use super::*;
241245

242246
pub fn filter_transactions_for_indices(
@@ -287,15 +291,16 @@ mod tests {
287291

288292
pub fn compute_mk_map_from_block_ranges_map(
289293
block_ranges_map: BTreeMap<BlockRange, Vec<CardanoTransaction>>,
290-
) -> MKMap<BlockRange, MKMapNode<BlockRange>> {
294+
) -> MKMap<BlockRange, MKMapNode<BlockRange, MKTreeStoreInMemory>, MKTreeStoreInMemory>
295+
{
291296
MKMap::new_from_iter(
292297
block_ranges_map
293298
.into_iter()
294299
.map(|(block_range, transactions)| {
295300
(
296301
block_range,
297302
MKMapNode::TreeNode(
298-
MKTree::new(&transactions)
303+
MKTree::<MKTreeStoreInMemory>::new(&transactions)
299304
.unwrap()
300305
.compute_root()
301306
.unwrap()
@@ -348,13 +353,13 @@ mod tests {
348353
}
349354
}
350355

351-
fn build_prover<F, G>(
356+
fn build_prover<F, G, S: MKTreeStorer + 'static>(
352357
transaction_retriever_mock_config: F,
353358
block_range_root_retriever_mock_config: G,
354-
) -> MithrilProverService
359+
) -> MithrilProverService<S>
355360
where
356361
F: FnOnce(&mut MockTransactionsRetriever),
357-
G: FnOnce(&mut MockBlockRangeRootRetrieverImpl),
362+
G: FnOnce(&mut MockBlockRangeRootRetrieverImpl<S>),
358363
{
359364
let mut transaction_retriever = MockTransactionsRetriever::new();
360365
transaction_retriever_mock_config(&mut transaction_retriever);
@@ -581,7 +586,7 @@ mod tests {
581586
let transactions_to_prove =
582587
test_data::filter_transactions_for_indices(&[1, 2, 4], &transactions);
583588
let test_data = test_data::build_test_data(&transactions_to_prove, &transactions);
584-
let prover = build_prover(
589+
let prover = build_prover::<_, _, MKTreeStoreInMemory>(
585590
|transaction_retriever_mock| {
586591
transaction_retriever_mock
587592
.expect_get_by_hashes()
@@ -610,7 +615,7 @@ mod tests {
610615
let transactions_to_prove =
611616
test_data::filter_transactions_for_indices(&[1, 2, 4], &transactions);
612617
let test_data = test_data::build_test_data(&transactions_to_prove, &transactions);
613-
let prover = build_prover(
618+
let prover = build_prover::<_, _, MKTreeStoreInMemory>(
614619
|transaction_retriever_mock| {
615620
let transactions_to_prove = transactions_to_prove.clone();
616621
transaction_retriever_mock

mithril-common/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-common"
3-
version = "0.4.45"
3+
version = "0.4.46"
44
description = "Common types, interfaces, and utilities for Mithril nodes."
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-common/benches/merkle_map.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
22
use mithril_common::{
3-
crypto_helper::{MKMap, MKMapNode, MKMapValue, MKTree, MKTreeNode},
3+
crypto_helper::{MKMap, MKMapNode, MKMapValue, MKTree, MKTreeNode, MKTreeStoreInMemory},
44
entities::BlockRange,
55
};
66

@@ -29,7 +29,7 @@ fn generate_block_ranges_nodes_iterator(
2929
total_transactions_per_block: u64,
3030
block_range_length: u64,
3131
max_uncompressed_block_ranges: u64,
32-
) -> impl Iterator<Item = (BlockRange, MKMapNode<BlockRange>)> {
32+
) -> impl Iterator<Item = (BlockRange, MKMapNode<BlockRange, MKTreeStoreInMemory>)> {
3333
let total_transactions_per_block_range = total_transactions_per_block * block_range_length;
3434
let total_block_ranges = total_transactions / total_transactions_per_block_range;
3535
assert!(
@@ -56,8 +56,10 @@ fn generate_block_ranges_nodes_iterator(
5656
}
5757

5858
fn generate_merkle_map_compressed(
59-
block_ranges_nodes_iterator: impl Iterator<Item = (BlockRange, MKMapNode<BlockRange>)>,
60-
) -> MKMap<BlockRange, MKMapNode<BlockRange>> {
59+
block_ranges_nodes_iterator: impl Iterator<
60+
Item = (BlockRange, MKMapNode<BlockRange, MKTreeStoreInMemory>),
61+
>,
62+
) -> MKMap<BlockRange, MKMapNode<BlockRange, MKTreeStoreInMemory>, MKTreeStoreInMemory> {
6163
let mut mk_map = MKMap::new(&[]).unwrap();
6264
for (block_range, mk_map_node) in block_ranges_nodes_iterator {
6365
mk_map
@@ -68,10 +70,19 @@ fn generate_merkle_map_compressed(
6870
}
6971

7072
fn generate_merkle_map(
71-
block_ranges_nodes_iterator: impl Iterator<Item = (BlockRange, MKMapNode<BlockRange>)>,
72-
mk_map_compressed: &MKMap<BlockRange, MKMapNode<BlockRange>>,
73+
block_ranges_nodes_iterator: impl Iterator<
74+
Item = (BlockRange, MKMapNode<BlockRange, MKTreeStoreInMemory>),
75+
>,
76+
mk_map_compressed: &MKMap<
77+
BlockRange,
78+
MKMapNode<BlockRange, MKTreeStoreInMemory>,
79+
MKTreeStoreInMemory,
80+
>,
7381
total_proofs: u64,
74-
) -> (MKMap<BlockRange, MKMapNode<BlockRange>>, Vec<MKTreeNode>) {
82+
) -> (
83+
MKMap<BlockRange, MKMapNode<BlockRange, MKTreeStoreInMemory>, MKTreeStoreInMemory>,
84+
Vec<MKTreeNode>,
85+
) {
7586
let mut leaves_to_prove_all: Vec<MKTreeNode> = vec![];
7687
let mut mk_map = mk_map_compressed.clone();
7788
for (mk_map_key_to_prove, mk_map_node_to_prove) in &block_ranges_nodes_iterator

0 commit comments

Comments
 (0)