Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

FM-196: Implement ProposalInterpreter::process for BottomUp #202

Merged
merged 1 commit into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 3 additions & 6 deletions fendermint/app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,7 @@ where
Genesis = Vec<u8>,
Output = FvmGenesisOutput,
>,
I: ProposalInterpreter<
State = (), // TODO
Message = Vec<u8>,
>,
I: ProposalInterpreter<State = CheckpointPool, Message = Vec<u8>>,
I: ExecInterpreter<
State = (CheckpointPool, FvmExecState<SS>),
Message = Vec<u8>,
Expand Down Expand Up @@ -517,7 +514,7 @@ where

let txs = self
.interpreter
.prepare((), txs)
.prepare(self.resolve_pool.clone(), txs)
.await
.context("failed to prepare proposal")?;

Expand All @@ -536,7 +533,7 @@ where

let accept = self
.interpreter
.process((), txs)
.process(self.resolve_pool.clone(), txs)
.await
.context("failed to process proposal")?;

Expand Down
34 changes: 24 additions & 10 deletions fendermint/vm/interpreter/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ impl<I> ProposalInterpreter for ChainMessageInterpreter<I>
where
I: Sync + Send,
{
// TODO: The state can include the IPLD Resolver mempool, for example by using STM
// to implement a shared memory space.
type State = ();
type State = CheckpointPool;
type Message = ChainMessage;

/// Check whether there are any "ready" messages in the IPLD resolution mempool which can be appended to the proposal.
Expand All @@ -83,17 +81,33 @@ where
_state: Self::State,
msgs: Vec<Self::Message>,
) -> anyhow::Result<Vec<Self::Message>> {
// For now this is just a placeholder.
// TODO #195: Collect resolved CIDs ready to be proposed from the pool.
Ok(msgs)
}

/// Perform finality checks on top-down transactions and availability checks on bottom-up transactions.
async fn process(
&self,
_state: Self::State,
_msgs: Vec<Self::Message>,
) -> anyhow::Result<bool> {
// For now this is just a placeholder.
async fn process(&self, state: Self::State, msgs: Vec<Self::Message>) -> anyhow::Result<bool> {
let pool = state;
for msg in msgs {
if let ChainMessage::Ipc(IpcMessage::BottomUpExec(msg)) = msg {
let item = CheckpointPoolItem::BottomUp(msg);

// We can just look in memory because when we start the application, we should retrieve any
// pending checkpoints (relayed but not executed) from the ledger, so they should be there.
// We don't have to validate the checkpoint here, because
// 1) we validated it when it was relayed, and
// 2) if a validator proposes something invalid, we can make them pay during execution.
let is_resolved = atomically(|| match pool.get_status(&item)? {
None => Ok(false),
Some(status) => status.is_resolved(),
})
.await;

if !is_resolved {
return Ok(false);
}
}
}
Ok(true)
}
}
Expand Down