Skip to content

Commit f549299

Browse files
authored
Merge pull request #3738 from dusk-network/refactor_state_transition_part2
Refactor State Transition (Part 2)
2 parents e60cec9 + 1100cc5 commit f549299

14 files changed

Lines changed: 410 additions & 502 deletions

File tree

consensus/src/errors.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ impl From<BlsSigError> for ConsensusError {
6969

7070
#[derive(Debug, Error)]
7171
pub enum OperationError {
72-
#[error("VST failed: {0}")]
73-
FailedVST(StateTransitionError),
74-
#[error("EST failed: {0}")]
75-
FailedEST(StateTransitionError),
72+
#[error("State transition creation failed: {0}")]
73+
FailedTransitionCreation(StateTransitionError),
74+
#[error("State transition verification failed: {0}")]
75+
FailedTransitionVerification(StateTransitionError),
7676
#[error("Invalid header: {0}")]
7777
InvalidHeader(HeaderError),
7878
#[error("Unable to update metrics: {0}")]
@@ -111,19 +111,6 @@ pub enum HeaderError {
111111
#[error("Invalid Failed Iterations: {0}")]
112112
InvalidFailedIterations(FailedIterationError),
113113

114-
#[error(
115-
"mismatch, event_bloom: {}, candidate_event_bloom: {}",
116-
hex::encode(.0.as_ref()),
117-
hex::encode(.1.as_ref())
118-
)]
119-
EventBloomMismatch(Box<[u8; 256]>, Box<[u8; 256]>),
120-
#[error(
121-
"mismatch, state_hash: {}, candidate_state_hash: {}",
122-
hex::encode(.0),
123-
hex::encode(.1)
124-
)]
125-
StateRootMismatch([u8; 32], [u8; 32]),
126-
127114
#[error("Generic error in header verification: {0}")]
128115
Generic(&'static str),
129116

@@ -139,17 +126,33 @@ pub enum StateTransitionError {
139126
InvalidSlash(io::Error),
140127
#[error("Invalid generator: {0:?}")]
141128
InvalidGenerator(dusk_bytes::Error),
129+
#[error("Session instantiation failed: {0}")]
130+
SessionError(String),
142131
#[error("Execution failed: {0}")]
143132
ExecutionError(String),
144-
#[error("Verification failed: {0}")]
145-
VerificationError(String),
133+
#[error(
134+
"State root mismatch. transition result: {}, block header: {}",
135+
hex::encode(.0),
136+
hex::encode(.1)
137+
)]
138+
StateRootMismatch([u8; 32], [u8; 32]),
139+
#[error(
140+
"Event bloom mismatch. transition result: {}, block header: {}",
141+
hex::encode(.0.as_ref()),
142+
hex::encode(.1.as_ref())
143+
)]
144+
EventBloomMismatch(Box<[u8; 256]>, Box<[u8; 256]>),
145+
#[error("Failed to persist state: {0}")]
146+
PersistenceError(String),
146147
}
147148

148149
impl OperationError {
149150
pub fn must_vote(&self) -> bool {
150151
match self {
151152
Self::InvalidHeader(e) => e.must_vote(),
152-
Self::FailedVST(StateTransitionError::TipChanged) => false,
153+
Self::FailedTransitionVerification(
154+
StateTransitionError::TipChanged,
155+
) => false,
153156
_ => true,
154157
}
155158
}
@@ -171,8 +174,6 @@ impl HeaderError {
171174
HeaderError::InvalidSeed(_) => true,
172175
HeaderError::InvalidAttestation(_) => true,
173176
HeaderError::InvalidFailedIterations(_) => true,
174-
HeaderError::EventBloomMismatch(_, _) => true,
175-
HeaderError::StateRootMismatch(_, _) => true,
176177

177178
HeaderError::Generic(..) => false,
178179
}

consensus/src/operations.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ use std::fmt;
88
use std::time::Duration;
99

1010
use node_data::bls::{PublicKey, PublicKeyBytes};
11-
use node_data::ledger::{
12-
Block, Fault, Header, Slash, SpentTransaction, Transaction,
13-
};
11+
use node_data::ledger::{Block, Fault, Header, Slash, SpentTransaction};
1412
use node_data::StepName;
1513

1614
use crate::errors::*;
@@ -61,7 +59,7 @@ pub trait Operations: Send + Sync {
6159
&self,
6260
candidate_header: &Header,
6361
expected_generator: &PublicKeyBytes,
64-
) -> Result<(u8, Vec<Voter>, Vec<Voter>), HeaderError>;
62+
) -> Result<Vec<Voter>, HeaderError>;
6563

6664
async fn validate_faults(
6765
&self,
@@ -74,19 +72,12 @@ pub trait Operations: Send + Sync {
7472
prev_state: StateRoot,
7573
blk: &Block,
7674
cert_voters: &[Voter],
77-
) -> Result<StateTransitionResult, OperationError>;
75+
) -> Result<(), OperationError>;
7876

79-
async fn new_state_transition(
77+
async fn generate_state_transition(
8078
&self,
8179
transition_data: StateTransitionData,
82-
) -> Result<
83-
(
84-
Vec<SpentTransaction>,
85-
StateTransitionResult,
86-
Vec<Transaction>,
87-
),
88-
OperationError,
89-
>;
80+
) -> Result<(Vec<SpentTransaction>, StateTransitionResult), OperationError>;
9081

9182
async fn add_step_elapsed_time(
9283
&self,

consensus/src/proposal/block_generator.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,10 @@ impl<T: Operations> Generator<T> {
117117
};
118118

119119
// Compute a valid state transition for the block
120-
let (executed_txs, transition_result, _) =
121-
self.executor.new_state_transition(transition_data).await?;
120+
let (executed_txs, transition_result) = self
121+
.executor
122+
.generate_state_transition(transition_data)
123+
.await?;
122124

123125
blk_header.state_hash = transition_result.state_root;
124126
blk_header.event_bloom = transition_result.event_bloom;

consensus/src/proposal/step.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl<T: Operations + 'static, D: Database> ProposalStep<T, D> {
113113
}
114114

115115
Err(err) => match err {
116-
OperationError::FailedEST(
116+
OperationError::FailedTransitionCreation(
117117
StateTransitionError::TipChanged,
118118
) => {
119119
warn!(

consensus/src/validation/step.rs

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use std::sync::Arc;
88

99
use node_data::bls::PublicKeyBytes;
10-
use node_data::ledger::{to_str, Block, Header};
10+
use node_data::ledger::{to_str, Block};
1111
use node_data::message::payload::{Validation, Vote};
1212
use node_data::message::{
1313
AsyncQueue, ConsensusHeader, Message, Payload, SignInfo, SignedStepMessage,
@@ -18,10 +18,10 @@ use tracing::{debug, error, info, warn, Instrument};
1818

1919
use crate::commons::{Database, RoundUpdate};
2020
use crate::config::is_emergency_iter;
21-
use crate::errors::{HeaderError, OperationError};
21+
use crate::errors::OperationError;
2222
use crate::execution_ctx::ExecutionCtx;
2323
use crate::msg_handler::StepOutcome;
24-
use crate::operations::{Operations, StateRoot, StateTransitionResult};
24+
use crate::operations::{Operations, StateRoot};
2525
use crate::validation::handler;
2626

2727
pub struct ValidationStep<T, D: Database> {
@@ -89,7 +89,7 @@ impl<T: Operations + 'static, D: Database> ValidationStep<T, D> {
8989
let header = candidate.header();
9090
let candidate_hash = header.hash;
9191

92-
let vote = match Self::verify_candidate(
92+
let vote = match Self::validate_candidate(
9393
candidate,
9494
ru.state_root(),
9595
executor,
@@ -119,32 +119,29 @@ impl<T: Operations + 'static, D: Database> ValidationStep<T, D> {
119119
Self::cast_vote(vote, ru, iteration, outbound, inbound).await;
120120
}
121121

122-
async fn verify_candidate(
122+
async fn validate_candidate(
123123
candidate: &Block,
124124
prev_state: StateRoot,
125125
executor: Arc<T>,
126126
expected_generator: PublicKeyBytes,
127127
) -> Result<(), OperationError> {
128128
let header = candidate.header();
129129

130-
// Verify faults
130+
// Validate faults
131131
executor
132132
.validate_faults(header.height, candidate.faults())
133133
.await?;
134134

135-
// Verify candidate header
136-
let (_, cert_voters, _) = executor
135+
// Validate candidate header
136+
let cert_voters = executor
137137
.validate_block_header(header, &expected_generator)
138138
.await?;
139139

140-
// Verify state transition
141-
let transition_result = executor
140+
// Validate state transition
141+
executor
142142
.validate_state_transition(prev_state, candidate, &cert_voters)
143143
.await?;
144144

145-
// Verify header against state transition output
146-
Self::check_header_vst(header, &transition_result)?;
147-
148145
Ok(())
149146
}
150147

@@ -177,28 +174,6 @@ impl<T: Operations + 'static, D: Database> ValidationStep<T, D> {
177174
inbound.try_send(msg);
178175
}
179176
}
180-
181-
fn check_header_vst(
182-
header: &Header,
183-
transition_result: &StateTransitionResult,
184-
) -> Result<(), HeaderError> {
185-
// Check the header against `event_bloom` and `state_root` from VST
186-
if transition_result.event_bloom != header.event_bloom {
187-
return Err(HeaderError::EventBloomMismatch(
188-
Box::new(transition_result.event_bloom),
189-
Box::new(header.event_bloom),
190-
));
191-
}
192-
193-
if transition_result.state_root != header.state_hash {
194-
return Err(HeaderError::StateRootMismatch(
195-
transition_result.state_root,
196-
header.state_hash,
197-
));
198-
}
199-
200-
Ok(())
201-
}
202177
}
203178

204179
pub fn build_validation_payload(

node/src/chain/acceptor.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -718,12 +718,12 @@ impl<DB: database::DB, VM: vm::VMExecution, N: Network> Acceptor<N, DB, VM> {
718718
///
719719
/// * blk: the block to accept as successor of the tip
720720
/// * restart_consensus: `true` if the consensus loop has to be restarted
721-
/// after accepting a block, false otherwise.
721+
/// after accepting a block.
722722
///
723723
/// # Returns
724724
///
725725
/// * `true` if the accepted block triggered rolling finality on a previous
726-
/// block; `false` otherwise.
726+
/// block.
727727
pub(crate) async fn accept_block(
728728
&mut self,
729729
blk: &Block,
@@ -740,6 +740,8 @@ impl<DB: database::DB, VM: vm::VMExecution, N: Network> Acceptor<N, DB, VM> {
740740

741741
let header_verification_start = std::time::Instant::now();
742742
// Verify Block Header
743+
// `cert_voters` and `att_voters` are the voters of the previous-block
744+
// Certificate and the `blk` Attestation, respectively
743745
let (pni, cert_voters, att_voters) = verify_block_header(
744746
self.db.clone(),
745747
&prev_header,
@@ -767,34 +769,36 @@ impl<DB: database::DB, VM: vm::VMExecution, N: Network> Acceptor<N, DB, VM> {
767769
let (contract_events, finality) =
768770
self.db.read().await.update(|db| {
769771
// Execute, verify, and persist the state_transition
770-
let (txs, transition_result, contract_events) = vm
771-
.do_accept_state_transition(
772+
let (spent_txs, contract_events) = vm
773+
.accept_state_transition(
772774
prev_header.state_hash,
773775
blk,
774776
&cert_voters[..],
775777
)?;
776778

777-
for spent_tx in txs.iter() {
779+
// Add spent txs to event list
780+
for spent_tx in spent_txs.iter() {
778781
events
779782
.push(TransactionEvent::Executed(spent_tx).into());
780783
}
781-
est_elapsed_time = start.elapsed();
782784

783-
assert_eq!(header.state_hash, transition_result.state_root);
784-
assert_eq!(
785-
header.event_bloom,
786-
transition_result.event_bloom
787-
);
785+
// Stop elapsed time
786+
est_elapsed_time = start.elapsed();
788787

789-
// Check if the new block triggers rolling finality
788+
// Check finality for previous blocks and the Consensus
789+
// State label for the accepted block
790790
let finality =
791791
self.rolling_finality::<DB>(pni, blk, db, &mut events)?;
792-
793792
let label = finality.0;
793+
794794
// Store block with spent transactions info (including
795795
// GasSpent and Errors), faults, and consensus status label
796-
block_size_on_disk =
797-
db.store_block(header, &txs, blk.faults(), label)?;
796+
block_size_on_disk = db.store_block(
797+
header,
798+
&spent_txs,
799+
blk.faults(),
800+
label,
801+
)?;
798802

799803
Ok((contract_events, finality))
800804
})?;
@@ -1531,10 +1535,13 @@ async fn broadcast<N: Network>(network: &Arc<RwLock<N>>, msg: &Message) {
15311535
});
15321536
}
15331537

1534-
/// Performs full verification of block header against prev_block header where
1535-
/// prev_block is usually the blockchain tip
1538+
/// Verifies a block header against its previous block
1539+
///
1540+
/// # Returns
15361541
///
1537-
/// Returns the number of Previous Non-Attested Iterations (PNI).
1542+
/// * The number of Previous Non-Attested Iterations (PNI)
1543+
/// * The list of voters in the previous-block Certificate
1544+
/// * The list of voters in the current-block Attestation
15381545
pub(crate) async fn verify_block_header<DB: database::DB>(
15391546
db: Arc<RwLock<DB>>,
15401547
prev_header: &ledger::Header,
@@ -1565,6 +1572,6 @@ pub(crate) async fn verify_block_header<DB: database::DB>(
15651572
// Verify header validity
15661573
let validator = Validator::new(db, prev_header, provisioners);
15671574
validator
1568-
.execute_checks(header, &expected_generator, check_att)
1575+
.verify_block_header_fields(header, &expected_generator, check_att)
15691576
.await
15701577
}

0 commit comments

Comments
 (0)