Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compute chain MMR root #71

Merged
merged 174 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from 169 commits
Commits
Show all changes
174 commits
Select commit Hold shift + click to select a range
35ca86a
DefautBlockBuilder scaffold
plafer Oct 30, 2023
d81ae71
build_block: non-header fields
plafer Oct 30, 2023
b1e574f
build_block() scaffold
plafer Oct 30, 2023
2149014
Store::get_block_inputs
plafer Oct 31, 2023
b338780
get_block_inputs: use iterators
plafer Oct 31, 2023
ea4f766
DefaultBlockBuilder: remove some state
plafer Oct 31, 2023
4d66033
clippy
plafer Oct 31, 2023
88858cd
account program scaffold
plafer Oct 31, 2023
5ac3971
nullifier scaffold
plafer Oct 31, 2023
db4335f
create host
plafer Oct 31, 2023
c99a894
Merge branch 'main' into plafer-block-builder
plafer Nov 6, 2023
98ad2ce
account root: set up MerkleStore
plafer Nov 6, 2023
3a6ed99
write account root update masm
plafer Nov 6, 2023
90c3e7f
compute_new_account_root() done
plafer Nov 6, 2023
3441faf
rename module
plafer Nov 6, 2023
2fd5549
fix build
plafer Nov 7, 2023
70f5414
clippy
plafer Nov 7, 2023
98c649c
AccountInputRecord conversion
plafer Nov 7, 2023
c1d7540
NullifierInputRecord conversion
plafer Nov 7, 2023
cc6f0cb
BlockInputs conversion
plafer Nov 7, 2023
71052f3
add TODO
plafer Nov 7, 2023
90275ce
call `compute_new_account_root()`
plafer Nov 7, 2023
07fae62
fmt
plafer Nov 7, 2023
9617303
compile account program only once
plafer Nov 7, 2023
84c16dc
remove useless vars before `Vec::extend()`
plafer Nov 7, 2023
dc96d69
tests mod
plafer Nov 7, 2023
0f11c9d
AccountRootUpdateError
plafer Nov 7, 2023
7b5a462
account root update error
plafer Nov 7, 2023
b40dbbb
remove empty comment
plafer Nov 8, 2023
5988095
add separation
plafer Nov 8, 2023
37b5013
use OLD_ACCOUNT_ROOT
plafer Nov 8, 2023
8d4ee51
compute_block_header
plafer Nov 8, 2023
b61b0c0
Merge branch 'main' into plafer-block-builder
plafer Nov 8, 2023
b589665
conversion: use utilities
plafer Nov 8, 2023
eea8581
Move domain types to `miden-node-proto`
plafer Nov 8, 2023
b9adce5
BlockHeaderWitness
plafer Nov 8, 2023
8a9d23f
Rename to kernel terminology
plafer Nov 8, 2023
dcb3197
BlockKernel
plafer Nov 8, 2023
3669e59
BlockHeaderWitness: validate_inputs
plafer Nov 8, 2023
9bb256b
validate_account_states
plafer Nov 9, 2023
4733d4e
BlockHeaderWitness -> BlockWitness
plafer Nov 9, 2023
c45f9be
fmt
plafer Nov 9, 2023
1464728
Remove comment
plafer Nov 9, 2023
7719b25
comment
plafer Nov 9, 2023
9ae7319
errors module
plafer Nov 9, 2023
c3c20e2
change names
plafer Nov 9, 2023
dcf644c
rename module: kernel -> prover
plafer Nov 9, 2023
f50688b
Use `AccountUpdate` in `BlockWitness`
plafer Nov 9, 2023
8ae7d85
rename error
plafer Nov 9, 2023
8af7e94
tests comment
plafer Nov 9, 2023
33efedd
prover-only test file
plafer Nov 9, 2023
50246bc
derive Clone,Debug for `BlockInputs`
plafer Nov 9, 2023
50a6e2e
test_block_witness_validation_inconsistent_account_ids
plafer Nov 9, 2023
0e99f95
use error equality in tests
plafer Nov 9, 2023
37b2c97
test_block_witness_validation_inconsistent_account_hashes()
plafer Nov 9, 2023
9053a69
test_compute_account_root_success
plafer Nov 9, 2023
8ca84b7
comments
plafer Nov 9, 2023
bce42f9
error: use #[from]
plafer Nov 10, 2023
f87f4d7
GetBlockInputs error
plafer Nov 10, 2023
8c2888a
ApplyBlockError
plafer Nov 10, 2023
2996277
test_utils: proven_tx module
plafer Nov 10, 2023
3392c7e
move test structs to test_utils
plafer Nov 10, 2023
f222ca1
change MockStoreSuccess::new
plafer Nov 10, 2023
36cc196
Use SimpleSmt in MockStoreSuccess
plafer Nov 10, 2023
397e070
implement MockStoreSuccess::get_block_inputs
plafer Nov 10, 2023
708ebb2
MockStoreSuccess: update_accounts
plafer Nov 10, 2023
ca4fedb
Use `MockStoreSuccess` in prover test
plafer Nov 10, 2023
1a1f227
test_apply_block_called_empty_batches
plafer Nov 10, 2023
094b272
test_compute_account_root_empty_batches
plafer Nov 10, 2023
60de9ac
kernel: check if we should enter loop
plafer Nov 10, 2023
2b835e6
fix test
plafer Nov 10, 2023
a04bc2b
test_build_block_failure
plafer Nov 10, 2023
82826b8
test_compute_account_root_empty_batches
plafer Nov 10, 2023
74864c4
use `Felt::from(u64)`
plafer Nov 13, 2023
67f2b30
remove commented out fields
plafer Nov 13, 2023
d0acbd1
block kernel masm: move account root computation to proc
plafer Nov 14, 2023
98c0856
main proc
plafer Nov 14, 2023
5cb6bbc
proc.compute_note_root
plafer Nov 14, 2023
a1e544f
call compute_note_root from main
plafer Nov 14, 2023
ad4d5c1
Retrieve note root from program
plafer Nov 14, 2023
320f975
TransactionBatch: process on `new()`
plafer Nov 14, 2023
b1f0421
TransactionBatch: created_notes_root
plafer Nov 14, 2023
d76ac6c
BuildBatchError::TooManyNotes
plafer Nov 14, 2023
5f2ea04
TransactionBatch::new returns Result
plafer Nov 14, 2023
4528e68
remove expect()
plafer Nov 14, 2023
50be10e
test_compute_note_root_success
plafer Nov 14, 2023
34a3c6d
add arg to tx_gen
plafer Nov 14, 2023
28da2f9
fix BlockWitness
plafer Nov 14, 2023
8256842
rename error
plafer Nov 14, 2023
4f41159
test: empty notes
plafer Nov 16, 2023
5825441
comment
plafer Nov 16, 2023
007ec56
test note root for empty batches
plafer Nov 16, 2023
372a611
test_compute_note_root_empty_notes_success
plafer Nov 16, 2023
582d8ca
constants
plafer Nov 16, 2023
7206d68
adjust tests to reflect new tree design
plafer Nov 16, 2023
779c611
only send non-empty created notes roots
plafer Nov 16, 2023
6985a12
fix block_kernel masm given previous changes
plafer Nov 16, 2023
a982a53
fix test_compute_note_root_success
plafer Nov 16, 2023
25de729
fix `into_parts()`
plafer Nov 16, 2023
5180a2f
build_batch: remove `unwrap`
plafer Nov 16, 2023
afb3568
validate not too many batches in block
plafer Nov 16, 2023
e871a79
remove unsafe
plafer Nov 21, 2023
1ea87e7
remove capital letter
plafer Nov 21, 2023
f3b5604
remove script roots from transaction batch
plafer Nov 21, 2023
7bbef20
Use BTreeMap for account updates in TransactionBatch
plafer Nov 21, 2023
b7d2e09
inline mtree_8_set function
plafer Nov 22, 2023
2d37e71
remove whitespace
plafer Nov 22, 2023
1206d30
compute_chain_mmr_root routine
plafer Nov 22, 2023
8d03172
call chain mmr root routine from main
plafer Nov 22, 2023
b6ad0a3
Merge branch 'main' into plafer-note-root
plafer Nov 27, 2023
b5bee39
Merge branch 'plafer-note-root' into plafer-chain-mmr-root
plafer Nov 27, 2023
6b35113
use new StackOutputs API
plafer Nov 27, 2023
25f933f
add explanation to `compute_note_root`
plafer Nov 27, 2023
d393c04
Merge branch 'plafer-note-root' into plafer-chain-mmr-root
plafer Nov 27, 2023
71bf52d
convert `as u64` to try_into
plafer Nov 28, 2023
d01f13a
fix created notes smt: depth 13 instead of 12
plafer Nov 28, 2023
959d883
fix test
plafer Nov 28, 2023
d4b8793
clippy tests
plafer Nov 28, 2023
980f921
fix masm comments
plafer Nov 28, 2023
d542e6c
Merge branch 'plafer-note-root' into plafer-chain-mmr-root
plafer Nov 28, 2023
4aeb7d1
fix compute_chain_mmr_root
plafer Nov 28, 2023
1d769de
fix comment
plafer Nov 28, 2023
a1be343
chain MMR stack inputs
plafer Nov 28, 2023
894b2ef
remove now-useless collect()
plafer Nov 28, 2023
0986a94
advice provider inputs
plafer Nov 28, 2023
246c12b
fill out advice inputs
plafer Nov 28, 2023
40e573b
update after hash_peak change
plafer Nov 28, 2023
a500a34
Merge branch 'main' into plafer-chain-mmr-root
plafer Nov 29, 2023
3324734
remove main proc
plafer Nov 29, 2023
238e155
move BlockWitness in new mod
plafer Nov 29, 2023
3ed5ac8
rename error variant
plafer Nov 29, 2023
5f7dc8c
remove old comment
plafer Nov 29, 2023
c924479
tests pass
plafer Nov 29, 2023
3e241b3
simplify padding peaks logic
plafer Nov 29, 2023
c157205
prove: pull out chain MMR root from stack outputs
plafer Nov 29, 2023
c191e8e
chain mmr root tests comment
plafer Nov 29, 2023
8e294ea
MockStoreSuccessBuilder
plafer Nov 29, 2023
b7e3672
use MockStoreSuccessBuilder
plafer Nov 29, 2023
3e59bab
add MMR to `MockStoreSuccess`
plafer Nov 29, 2023
d3cd970
Merge branch 'main' into plafer-chain-mmr-root
plafer Nov 30, 2023
12f7a97
MockStoreSuccessBuilder: use chain_mmr
plafer Nov 30, 2023
aa57f4d
MockStoreSuccess: last_block_header
plafer Nov 30, 2023
6c1c0f2
MockStore: create proper head at build
plafer Nov 30, 2023
ad45c33
create MockBlockBuilder
plafer Nov 30, 2023
7e79aea
remove update_accounts() method
plafer Nov 30, 2023
d8c8ddb
remove get_dummy_block()
plafer Nov 30, 2023
0538578
prove: compute proper block num
plafer Nov 30, 2023
2920a57
test_compute_chain_mmr_root_empty_mmr
plafer Nov 30, 2023
4e24eb4
fix block prev hash
plafer Nov 30, 2023
707a566
fixme
plafer Nov 30, 2023
5e0e68f
add comment
plafer Nov 30, 2023
4f36d4a
use ONE and ZERO
plafer Dec 1, 2023
c269dd7
add sections
plafer Dec 1, 2023
bd2a09e
into_program_inputs
plafer Dec 1, 2023
b8f2265
use to_advice_inputs
plafer Dec 1, 2023
9f1e01c
MockPrivateAccount: support u32 indices
plafer Dec 1, 2023
7f681fb
MockProvenTxBuilder
plafer Dec 1, 2023
7c8f245
batch mod
plafer Dec 1, 2023
5f233f8
TransactionBatchConstructor
plafer Dec 1, 2023
3e660ce
build_expected_block()
plafer Dec 1, 2023
97a18ba
build_actual_block_header
plafer Dec 1, 2023
c1d2875
build_expected_block_header
plafer Dec 1, 2023
5df94af
test_compute_chain_mmr_root_empty_mmr
plafer Dec 1, 2023
96d180e
test_compute_chain_mmr_root_mmr_1_peak
plafer Dec 1, 2023
08349d4
fix store mmr
plafer Dec 1, 2023
087917b
test_compute_chain_mmr_root_mmr_17_peaks
plafer Dec 1, 2023
7f5ba30
test_compute_chain_mmr_root_mmr_1_peak_with_batches
plafer Dec 1, 2023
5b5e32b
remove test
plafer Dec 1, 2023
f4da6f6
add comment
plafer Dec 1, 2023
12d2cbf
add period
plafer Dec 4, 2023
b501961
MAX_BATCHES_PER_BLOCK constant
plafer Dec 4, 2023
945a98b
fix comment in masm
plafer Dec 4, 2023
7df7ed2
use BTreeMap instead of Vec
plafer Dec 4, 2023
eee1d0a
clippy test
plafer Dec 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions block-producer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ edition = "2021"
rust-version = "1.73"

[dev-dependencies]
miden-crypto = { workspace = true }
miden-mock = { package = "miden-mock", git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "main", default-features = false }
once_cell = { version = "1.18" }
winterfell = "0.7"

[dependencies]
anyhow = { version = "1.0" }
async-trait = { version = "0.1" }
clap = { version = "4.3" , features = ["derive"] }
clap = { version = "4.3", features = ["derive"] }
figment = { version = "0.10", features = ["toml", "env"] }
itertools = { version = "0.12" }
miden-air = { package = "miden-air", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false }
Expand All @@ -25,10 +27,10 @@ miden-node-utils = { path = "../utils" }
miden_objects = { workspace = true }
miden_stdlib = { package = "miden-stdlib", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false }
miden_vm = { package = "miden-vm", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false }
serde = { version = "1.0" , features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
thiserror = { workspace = true }
tokio = { version = "1.29", features = ["rt-multi-thread", "net", "macros", "sync", "time"] }
toml = { version = "0.8" }
tonic = { version = "0.10" }
tracing = { version = "0.1" }
tracing-subscriber = { version = "0.3" , features = ["fmt"] }
tracing-subscriber = { version = "0.3", features = ["fmt"] }
9 changes: 3 additions & 6 deletions block-producer/src/batch_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,9 @@ impl TransactionBatch {

SimpleSmt::with_contiguous_leaves(
CREATED_NOTES_SMT_DEPTH,
created_notes
.into_iter()
.flat_map(|note_envelope| {
[note_envelope.note_hash().into(), note_envelope.metadata().into()]
})
.collect::<Vec<_>>(),
created_notes.into_iter().flat_map(|note_envelope| {
[note_envelope.note_hash().into(), note_envelope.metadata().into()]
}),
)?
};

Expand Down
7 changes: 4 additions & 3 deletions block-producer/src/block_builder/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use thiserror::Error;

use crate::store::{ApplyBlockError, BlockInputsError};

use super::prover::CREATED_NOTES_TREE_INSERTION_DEPTH;
use super::prover::block_witness::CREATED_NOTES_TREE_INSERTION_DEPTH;

#[derive(Debug, Error, PartialEq, Eq)]
pub enum BuildBlockError {
#[error("failed to update account root: {0}")]
AccountRootUpdateFailed(#[from] BlockProverError),
#[error("failed to compute new block: {0}")]
BlockProverFailed(#[from] BlockProverError),
#[error("failed to apply block: {0}")]
ApplyBlockFailed(#[from] ApplyBlockError),
#[error("failed to get block inputs from store: {0}")]
Expand Down
4 changes: 2 additions & 2 deletions block-producer/src/block_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use crate::{block::Block, store::Store, SharedTxBatch};

pub mod errors;

mod prover;
pub(crate) mod prover;
use self::{
errors::BuildBlockError,
prover::{BlockProver, BlockWitness},
prover::{block_witness::BlockWitness, BlockProver},
};

#[cfg(test)]
Expand Down
256 changes: 256 additions & 0 deletions block-producer/src/block_builder/prover/block_witness.rs
bobbinth marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
use std::collections::{BTreeMap, BTreeSet};

use miden_node_proto::domain::BlockInputs;
use miden_objects::{
accounts::AccountId,
crypto::merkle::{EmptySubtreeRoots, MerkleStore, MmrPeaks},
BlockHeader, Digest, Felt, ToAdviceInputs,
};
use miden_vm::{crypto::MerklePath, AdviceInputs, StackInputs};

use crate::{
batch_builder,
block_builder::errors::{BlockProverError, BuildBlockError},
SharedTxBatch,
};

// CONSTANTS
// =================================================================================================

/// The depth at which we insert roots from the batches.
pub(crate) const CREATED_NOTES_TREE_INSERTION_DEPTH: u8 = 8;

/// The depth of the created notes tree in the block.
pub(crate) const CREATED_NOTES_TREE_DEPTH: u8 =
CREATED_NOTES_TREE_INSERTION_DEPTH + batch_builder::CREATED_NOTES_SMT_DEPTH;

// BLOCK WITNESS
// =================================================================================================

/// Provides inputs to the `BlockKernel` so that it can generate the new header
plafer marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Debug, PartialEq)]
pub struct BlockWitness {
pub(super) updated_accounts: BTreeMap<AccountId, AccountUpdate>,
/// (batch_index, created_notes_root) for batches that contain notes
pub(super) batch_created_notes_roots: Vec<(usize, Digest)>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a benefit to using Vec<(usize, Digest)> instead of BTreeMap<usize, Digest>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to BTreeMap to be consistent with updated_accounts, but I think Vec would be better (for both) than BTreeMap, since it's more cache efficient (everything's in the same chunk of memory as opposed to be more spread out with the BTreeMap), and we don't actually need any operations from the BTreeMap.

But this is a minor detail and BTreeMap is fine for now

pub(super) chain_peaks: MmrPeaks,
pub(super) prev_header: BlockHeader,
}

impl BlockWitness {
pub fn new(
block_inputs: BlockInputs,
batches: Vec<SharedTxBatch>,
) -> Result<Self, BuildBlockError> {
Self::validate_inputs(&block_inputs, &batches)?;

let updated_accounts = {
let mut account_initial_states: BTreeMap<AccountId, Digest> =
batches.iter().flat_map(|batch| batch.account_initial_states()).collect();

let mut account_merkle_proofs: BTreeMap<AccountId, MerklePath> = block_inputs
.account_states
.into_iter()
.map(|record| (record.account_id, record.proof))
.collect();

batches
.iter()
.flat_map(|batch| batch.updated_accounts())
.map(|(account_id, final_state_hash)| {
let initial_state_hash = account_initial_states
.remove(&account_id)
.expect("already validated that key exists");
let proof = account_merkle_proofs
.remove(&account_id)
.expect("already validated that key exists");

(
account_id,
AccountUpdate {
initial_state_hash,
final_state_hash,
proof,
},
)
})
.collect()
};

let batch_created_notes_roots = batches
.iter()
.enumerate()
.filter_map(|(batch_index, batch)| {
if batch.created_notes().next().is_none() {
None
} else {
Some((batch_index, batch.created_notes_root()))
}
})
.collect();

Ok(Self {
updated_accounts,
batch_created_notes_roots,
chain_peaks: block_inputs.chain_peaks,
prev_header: block_inputs.block_header,
})
}

pub(super) fn into_program_inputs(
self
) -> Result<(AdviceInputs, StackInputs), BlockProverError> {
let stack_inputs = {
// Note: `StackInputs::new()` reverses the input vector, so we need to construct the stack
// from the bottom to the top
let mut stack_inputs = Vec::new();

// Chain MMR stack inputs
{
stack_inputs.extend(self.prev_header.hash());
stack_inputs.extend(self.chain_peaks.hash_peaks());
}

// Notes stack inputs
{
let num_created_notes_roots = self.batch_created_notes_roots.len();
for (batch_index, batch_created_notes_root) in self.batch_created_notes_roots {
stack_inputs.extend(batch_created_notes_root);

let batch_index = u64::try_from(batch_index)
.expect("can't be more than 2^64 - 1 notes created");
stack_inputs.push(Felt::from(batch_index));
}

let empty_root = EmptySubtreeRoots::entry(CREATED_NOTES_TREE_DEPTH, 0);
stack_inputs.extend(*empty_root);
stack_inputs.push(Felt::from(
u64::try_from(num_created_notes_roots)
.expect("can't be more than 2^64 - 1 notes created"),
));
}

// Account stack inputs
let mut num_accounts_updated: u64 = 0;
for (idx, (&account_id, account_update)) in self.updated_accounts.iter().enumerate() {
stack_inputs.push(account_id.into());
stack_inputs.extend(account_update.final_state_hash);

let idx = u64::try_from(idx).expect("can't be more than 2^64 - 1 accounts");
num_accounts_updated = idx + 1;
}

// append initial account root
stack_inputs.extend(self.prev_header.account_root());

// append number of accounts updated
stack_inputs.push(num_accounts_updated.into());

StackInputs::new(stack_inputs)
};

let advice_inputs = {
let mut merkle_store = MerkleStore::default();
merkle_store
.add_merkle_paths(self.updated_accounts.into_iter().map(
|(
account_id,
AccountUpdate {
initial_state_hash,
final_state_hash: _,
proof,
},
)| { (u64::from(account_id), initial_state_hash, proof) },
))
.map_err(BlockProverError::InvalidMerklePaths)?;

let mut advice_inputs = AdviceInputs::default().with_merkle_store(merkle_store);
self.chain_peaks.to_advice_inputs(&mut advice_inputs);

advice_inputs
};

Ok((advice_inputs, stack_inputs))
}

// HELPERS
// ---------------------------------------------------------------------------------------------

fn validate_inputs(
block_inputs: &BlockInputs,
batches: &[SharedTxBatch],
) -> Result<(), BuildBlockError> {
// TODO:
// - Block height returned for each nullifier is 0.

// Validate that there aren't too many batches in the block.
if batches.len() > 2usize.pow(CREATED_NOTES_TREE_INSERTION_DEPTH.into()) {
plafer marked this conversation as resolved.
Show resolved Hide resolved
return Err(BuildBlockError::TooManyBatchesInBlock(batches.len()));
}

Self::validate_account_states(block_inputs, batches)?;

Ok(())
}

/// Validate that initial account states coming from the batches are the same as the account
/// states returned from the store
fn validate_account_states(
block_inputs: &BlockInputs,
batches: &[SharedTxBatch],
) -> Result<(), BuildBlockError> {
let batches_initial_states: BTreeMap<AccountId, Digest> =
batches.iter().flat_map(|batch| batch.account_initial_states()).collect();

let accounts_in_batches: BTreeSet<AccountId> =
batches_initial_states.keys().cloned().collect();
let accounts_in_store: BTreeSet<AccountId> = block_inputs
.account_states
.iter()
.map(|record| &record.account_id)
.cloned()
.collect();

if accounts_in_batches == accounts_in_store {
let accounts_with_different_hashes: Vec<AccountId> = block_inputs
.account_states
.iter()
.filter_map(|record| {
let hash_in_store = record.account_hash;
let hash_in_batches = batches_initial_states
.get(&record.account_id)
.expect("we already verified that account id is contained in batches");

if hash_in_store == *hash_in_batches {
None
} else {
Some(record.account_id)
}
})
.collect();

if accounts_with_different_hashes.is_empty() {
Ok(())
} else {
Err(BuildBlockError::InconsistentAccountStates(accounts_with_different_hashes))
}
} else {
// The batches and store don't modify the same set of accounts
let union: BTreeSet<AccountId> =
accounts_in_batches.union(&accounts_in_store).cloned().collect();
let intersection: BTreeSet<AccountId> =
accounts_in_batches.intersection(&accounts_in_store).cloned().collect();

let difference: Vec<AccountId> = union.difference(&intersection).cloned().collect();

Err(BuildBlockError::InconsistentAccountIds(difference))
}
}
}

#[derive(Debug, PartialEq, Eq)]
pub(super) struct AccountUpdate {
pub initial_state_hash: Digest,
pub final_state_hash: Digest,
pub proof: MerklePath,
}
Loading