Map to query results.
(ret: FvmQueryRet, block_height: BlockHeight)
| 241 | |
| 242 | /// Map to query results. |
| 243 | pub fn to_query(ret: FvmQueryRet, block_height: BlockHeight) -> anyhow::Result<response::Query> { |
| 244 | let exit_code = match ret { |
| 245 | FvmQueryRet::Ipld(None) | FvmQueryRet::ActorState(None) => ExitCode::USR_NOT_FOUND, |
| 246 | FvmQueryRet::Ipld(_) | FvmQueryRet::ActorState(_) => ExitCode::OK, |
| 247 | // For calls and estimates, the caller needs to look into the `value` field to see the real exit code; |
| 248 | // the query itself is successful, even if the value represents a failure. |
| 249 | FvmQueryRet::Call(_) | FvmQueryRet::EstimateGas(_) => ExitCode::OK, |
| 250 | FvmQueryRet::StateParams(_) => ExitCode::OK, |
| 251 | FvmQueryRet::BuiltinActors(_) => ExitCode::OK, |
| 252 | }; |
| 253 | |
| 254 | // The return value has a `key` field which is supposed to be set to the data matched. |
| 255 | // Although at this point I don't have access to the input like the CID looked up, |
| 256 | // but I assume the query sender has. Rather than repeat everything, I'll add the key |
| 257 | // where it gives some extra information, like the actor ID, just to keep this option visible. |
| 258 | let (key, value) = match ret { |
| 259 | FvmQueryRet::Ipld(None) | FvmQueryRet::ActorState(None) => (Vec::new(), Vec::new()), |
| 260 | FvmQueryRet::Ipld(Some(bz)) => (Vec::new(), bz), |
| 261 | FvmQueryRet::ActorState(Some(x)) => { |
| 262 | let (id, st) = *x; |
| 263 | let k = ipld_encode!(id); |
| 264 | let v = ipld_encode!(st); |
| 265 | (k, v) |
| 266 | } |
| 267 | FvmQueryRet::Call(ret) => { |
| 268 | // Send back an entire Tendermint deliver_tx response, encoded as IPLD. |
| 269 | // This is so there is a single representation of a call result, instead |
| 270 | // of a normal delivery being one way and a query exposing `FvmApplyRet`. |
| 271 | let dtx = to_exec_tx_result(ret, None, None); |
| 272 | let dtx = tendermint_proto::abci::ExecTxResult::from(dtx); |
| 273 | let mut buf = bytes::BytesMut::new(); |
| 274 | dtx.encode(&mut buf)?; |
| 275 | let bz = buf.to_vec(); |
| 276 | // So the value is an IPLD encoded Protobuf byte vector. |
| 277 | let v = ipld_encode!(bz); |
| 278 | (Vec::new(), v) |
| 279 | } |
| 280 | FvmQueryRet::EstimateGas(est) => { |
| 281 | let v = ipld_encode!(est); |
| 282 | (Vec::new(), v) |
| 283 | } |
| 284 | FvmQueryRet::StateParams(sp) => { |
| 285 | let v = ipld_encode!(sp); |
| 286 | (Vec::new(), v) |
| 287 | } |
| 288 | FvmQueryRet::BuiltinActors(ba) => { |
| 289 | let v = ipld_encode!(ba); |
| 290 | (Vec::new(), v) |
| 291 | } |
| 292 | }; |
| 293 | |
| 294 | // The height here is the height of the block that was committed, not in which the app hash appeared. |
| 295 | let height = tendermint::block::Height::try_from(block_height).context("height too big")?; |
| 296 | |
| 297 | let res = response::Query { |
| 298 | code: to_code(exit_code), |
| 299 | info: to_error_msg(exit_code).to_owned(), |
| 300 | key: key.into(), |
no test coverage detected