Parse messages in the block, reject if unknown format. Pass the rest to the inner `ChainMessage` interpreter.
(&self, state: Self::State, msgs: Vec<Self::Message>)
| 127 | |
| 128 | /// Parse messages in the block, reject if unknown format. Pass the rest to the inner `ChainMessage` interpreter. |
| 129 | async fn process(&self, state: Self::State, msgs: Vec<Self::Message>) -> anyhow::Result<bool> { |
| 130 | if msgs.len() > self.max_msgs { |
| 131 | tracing::warn!( |
| 132 | block_msgs = msgs.len(), |
| 133 | "rejecting block: too many messages" |
| 134 | ); |
| 135 | return Ok(false); |
| 136 | } |
| 137 | |
| 138 | let mut chain_msgs = Vec::new(); |
| 139 | for msg in msgs { |
| 140 | match fvm_ipld_encoding::from_slice::<ChainMessage>(&msg) { |
| 141 | Err(e) => { |
| 142 | // If we cannot parse a message, then either: |
| 143 | // * The proposer is Byzantine - as an attack this isn't very effective as they could just not send a proposal and cause a timeout. |
| 144 | // * Our or the proposer node have different versions, or contain bugs |
| 145 | // We can either vote for it or not: |
| 146 | // * If we accept, we can punish the validator during block execution, and if it turns out we had a bug, we will have a consensus failure. |
| 147 | // * If we accept, then the serialization error will become visible in the transaction results through RPC. |
| 148 | // * If we reject, the majority can still accept the block, which indicates we had the bug (that way we might even panic during delivery, since we know it got voted on), |
| 149 | // but a buggy transaction format that fails for everyone would cause liveness issues. |
| 150 | // * If we reject, then the serialization error will only be visible in the logs (and potentially earlier check_tx results). |
| 151 | tracing::warn!( |
| 152 | error = e.to_string(), |
| 153 | "failed to decode message in proposal as ChainMessage" |
| 154 | ); |
| 155 | if self.reject_malformed_proposal { |
| 156 | return Ok(false); |
| 157 | } |
| 158 | } |
| 159 | Ok(msg) => chain_msgs.push(msg), |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | self.inner.process(state, chain_msgs).await |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | #[async_trait] |