diff --git a/node/src/chain/acceptor.rs b/node/src/chain/acceptor.rs index ec2ff74416..b955eece12 100644 --- a/node/src/chain/acceptor.rs +++ b/node/src/chain/acceptor.rs @@ -25,8 +25,9 @@ use crate::chain::header_validation::Validator; #[allow(dead_code)] pub(crate) enum RevertTarget { - LastFinalizedState = 0, - LastEpoch = 1, + Commit([u8; 32]), + LastFinalizedState, + LastEpoch, } /// Implements block acceptance procedure. This includes block header, @@ -407,17 +408,32 @@ impl Acceptor { let target_state_hash = match target { RevertTarget::LastFinalizedState => { - info!(event = "vm_revert to last finalized state"); - let state_hash = self.vm.read().await.revert()?; + let vm = self.vm.read().await; + let base_root = vm.get_base_state_root()?; + let state_hash = vm.revert(base_root)?; info!( event = "vm reverted", - state_root = hex::encode(state_hash) + state_root = hex::encode(state_hash), + is_final = "true", ); anyhow::Ok(state_hash) } - _ => unimplemented!(), + RevertTarget::Commit(state_hash) => { + let vm = self.vm.read().await; + let state_hash = vm.revert(state_hash)?; + let is_final = vm.get_base_state_root()? == state_hash; + + info!( + event = "vm reverted", + state_root = hex::encode(state_hash), + is_final, + ); + + anyhow::Ok(state_hash) + } + RevertTarget::LastEpoch => unimplemented!(), }?; // Delete any block until we reach the target_state_hash, the diff --git a/node/src/chain/fsm.rs b/node/src/chain/fsm.rs index d566a3ba7c..126ee0ee54 100644 --- a/node/src/chain/fsm.rs +++ b/node/src/chain/fsm.rs @@ -299,7 +299,7 @@ impl InSyncImpl { // R_B.Iteration < L_B.Iteration // // Then we fallback to N_B.PrevBlock and accept N_B - let local_header = acc.db.read().await.view(|t| { + let result = acc.db.read().await.view(|t| { if let Some((prev_header, _)) = t.fetch_block_header(&remote_blk.header().prev_block_hash)? { @@ -308,7 +308,10 @@ impl InSyncImpl { if remote_blk.header().iteration < l_b.header().iteration { - return Ok(Some(l_b.header().clone())); + return Ok(Some(( + l_b.header().clone(), + prev_header.state_hash, + ))); } } } @@ -316,12 +319,12 @@ impl InSyncImpl { anyhow::Ok(None) })?; - if let Some(local_header) = local_header { + if let Some((local_header, state_hash)) = result { match fallback::WithContext::new(acc.deref()) .try_revert( &local_header, remote_blk.header(), - RevertTarget::LastFinalizedState, + RevertTarget::Commit(state_hash), ) .await { diff --git a/node/src/vm.rs b/node/src/vm.rs index 308b8cea86..637fb79554 100644 --- a/node/src/vm.rs +++ b/node/src/vm.rs @@ -47,6 +47,7 @@ pub trait VMExecution: Send + Sync + 'static { ) -> anyhow::Result; fn get_state_root(&self) -> anyhow::Result<[u8; 32]>; + fn get_base_state_root(&self) -> anyhow::Result<[u8; 32]>; - fn revert(&self) -> anyhow::Result<[u8; 32]>; + fn revert(&self, state_hash: [u8; 32]) -> anyhow::Result<[u8; 32]>; } diff --git a/node/testbed.sh b/node/testbed.sh index c7199c705b..9883539410 100755 --- a/node/testbed.sh +++ b/node/testbed.sh @@ -51,7 +51,7 @@ RUSK_STATE_PATH=${RUSK_STATE_PATH} cargo r --release -p rusk -- recovery-state --init $GENESIS_PATH echo "starting node $ID ..." echo "${KEYS_PATH}/node_$ID.keys" - RUSK_STATE_PATH=${RUSK_STATE_PATH} ./target/release/rusk --kadcast-bootstrap "$BOOTSTRAP_ADDR" --kadcast-public-address "$PUBLIC_ADDR" --log-level="$LOG_LEVEL" --log-filter="dusk_consensus=debug" --consensus-keys-path="${KEYS_PATH}/node_$ID.keys" --db-path="$NODE_FOLDER" --http-listen-addr "$WS_LISTEN_ADDR" --delay-on-resp-msg=10 > "${TEMPD}/node_${ID}.log" & + RUSK_STATE_PATH=${RUSK_STATE_PATH} ./target/release/rusk --kadcast-bootstrap "$BOOTSTRAP_ADDR" --kadcast-public-address "$PUBLIC_ADDR" --log-type="json" --log-level="$LOG_LEVEL" --log-filter="dusk_consensus=debug" --consensus-keys-path="${KEYS_PATH}/node_$ID.keys" --db-path="$NODE_FOLDER" --http-listen-addr "$WS_LISTEN_ADDR" --delay-on-resp-msg=10 > "${TEMPD}/node_${ID}.log" & } ## Use ~/.cargo/bin/tokio-console --retain-for 0s http://127.0.0.1:10000 to connect console to first node