github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/src/scheduler/execution_result_ffi.rs (about)

     1  /*
     2   * Copyright 2018 Intel Corporation
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   * ------------------------------------------------------------------------------
    16   */
    17  
    18  use cpython;
    19  use cpython::FromPyObject;
    20  use cpython::ObjectProtocol;
    21  
    22  use proto::events::Event;
    23  use proto::transaction_receipt::StateChange;
    24  
    25  use scheduler::TxnExecutionResult;
    26  
    27  #[derive(Clone)]
    28  pub struct BatchResult {
    29      pub state_hash: Option<String>,
    30  }
    31  
    32  /// TransactionResult is a Rust struct that mirrors
    33  /// what is passed from a Python Scheduler's get_transaction_execution_results
    34  /// method.
    35  pub struct TransactionResult {
    36      pub signature: String,
    37      pub is_valid: bool,
    38      pub state_hash: Option<String>,
    39      pub state_changes: Vec<StateChange>,
    40      pub events: Vec<Event>,
    41      pub data: Vec<(String, Vec<u8>)>,
    42      pub error_message: String,
    43      pub error_data: Vec<u8>,
    44  }
    45  
    46  impl<'source> FromPyObject<'source> for BatchResult {
    47      fn extract(py: cpython::Python, obj: &'source cpython::PyObject) -> cpython::PyResult<Self> {
    48          let state_hash = obj.getattr(py, "state_hash").unwrap();
    49  
    50          let sh: Option<String> = state_hash.extract(py)?;
    51  
    52          Ok(BatchResult { state_hash: sh })
    53      }
    54  }
    55  
    56  impl<'source> FromPyObject<'source> for TransactionResult {
    57      fn extract(py: cpython::Python, obj: &'source cpython::PyObject) -> cpython::PyResult<Self> {
    58          Ok(try_pyobj_to_transaction_result(py, obj)?)
    59      }
    60  }
    61  
    62  impl<'source> FromPyObject<'source> for TxnExecutionResult {
    63      fn extract(py: cpython::Python, obj: &'source cpython::PyObject) -> cpython::PyResult<Self> {
    64          Ok(TxnExecutionResult::from(try_pyobj_to_transaction_result(
    65              py, obj,
    66          )?))
    67      }
    68  }
    69  
    70  impl From<TransactionResult> for TxnExecutionResult {
    71      fn from(other: TransactionResult) -> Self {
    72          TxnExecutionResult {
    73              signature: other.signature,
    74              is_valid: other.is_valid,
    75              state_changes: other.state_changes,
    76              events: other.events,
    77              data: other.data,
    78              error_message: other.error_message,
    79              error_data: other.error_data,
    80          }
    81      }
    82  }
    83  
    84  fn try_pyobj_to_transaction_result(
    85      py: cpython::Python,
    86      pyobj: &cpython::PyObject,
    87  ) -> Result<TransactionResult, cpython::PyErr> {
    88      let signature = return_string_from_pyobj(pyobj, py, "signature")?;
    89      let is_valid = return_bool_from_pyobj(pyobj, py, "is_valid")?;
    90      let beginning_state_hash = return_string_from_pyobj(pyobj, py, "state_hash").ok();
    91      let state_changes = return_statechanges_from_pyobj(pyobj, py, "state_changes")?;
    92      let events = return_events_from_pyobj(pyobj, py, "events")?;
    93      let data = return_data_from_pyobj(pyobj, py, "data")?;
    94      let error_message = return_string_from_pyobj(pyobj, py, "error_message")?;
    95      let error_data = return_owned_bytes_from_pyobj(pyobj, py, "error_data")?;
    96  
    97      Ok(TransactionResult {
    98          signature,
    99          is_valid,
   100          state_hash: beginning_state_hash,
   101          state_changes,
   102          events,
   103          data,
   104          error_message,
   105          error_data,
   106      })
   107  }
   108  
   109  fn return_string_from_pyobj(
   110      pydict: &cpython::PyObject,
   111      py: cpython::Python,
   112      item_name: &str,
   113  ) -> Result<String, cpython::PyErr> {
   114      Ok(pydict
   115          .getattr(py, item_name)
   116          .unwrap()
   117          .extract::<String>(py)?)
   118  }
   119  
   120  fn return_bool_from_pyobj(
   121      pydict: &cpython::PyObject,
   122      py: cpython::Python,
   123      item_name: &str,
   124  ) -> Result<bool, cpython::PyErr> {
   125      Ok(pydict.getattr(py, item_name).unwrap().extract::<bool>(py)?)
   126  }
   127  
   128  fn return_statechanges_from_pyobj(
   129      pydict: &cpython::PyObject,
   130      py: cpython::Python,
   131      item_name: &str,
   132  ) -> Result<Vec<StateChange>, cpython::PyErr> {
   133      pydict
   134          .getattr(py, item_name)?
   135          .extract::<cpython::PyList>(py)
   136          .unwrap()
   137          .iter(py)
   138          .map(|b| {
   139              let state_change_bytes = b.call_method(py, "SerializeToString", cpython::NoArgs, None)
   140                  .unwrap()
   141                  .extract::<Vec<u8>>(py)?;
   142              let state_change: StateChange =
   143                  ::protobuf::parse_from_bytes(state_change_bytes.as_slice()).unwrap();
   144              Ok(state_change)
   145          })
   146          .collect::<Result<Vec<StateChange>, cpython::PyErr>>()
   147  }
   148  
   149  fn return_events_from_pyobj(
   150      pydict: &cpython::PyObject,
   151      py: cpython::Python,
   152      item_name: &str,
   153  ) -> Result<Vec<Event>, cpython::PyErr> {
   154      pydict
   155          .getattr(py, item_name)?
   156          .extract::<cpython::PyList>(py)?
   157          .iter(py)
   158          .map(|e| {
   159              let event_bytes = e.call_method(py, "SerializeToString", cpython::NoArgs, None)
   160                  .unwrap()
   161                  .extract::<Vec<u8>>(py)?;
   162              let event: Event = ::protobuf::parse_from_bytes(event_bytes.as_slice()).unwrap();
   163              Ok(event)
   164          })
   165          .collect::<Result<Vec<Event>, cpython::PyErr>>()
   166  }
   167  
   168  fn return_data_from_pyobj(
   169      pydict: &cpython::PyObject,
   170      py: cpython::Python,
   171      item_name: &str,
   172  ) -> Result<Vec<(String, Vec<u8>)>, cpython::PyErr> {
   173      pydict
   174          .getattr(py, item_name)
   175          .unwrap()
   176          .extract::<cpython::PyList>(py)?
   177          .iter(py)
   178          .map(|b| {
   179              let py_data = b.extract::<cpython::PyTuple>(py)?;
   180              Ok((
   181                  py_data.get_item(py, 0).extract::<String>(py)?,
   182                  py_data.get_item(py, 1).extract::<Vec<u8>>(py)?,
   183              ))
   184          })
   185          .collect::<Result<Vec<(String, Vec<u8>)>, cpython::PyErr>>()
   186  }
   187  
   188  fn return_owned_bytes_from_pyobj(
   189      pydict: &cpython::PyObject,
   190      py: cpython::Python,
   191      item_name: &str,
   192  ) -> Result<Vec<u8>, cpython::PyErr> {
   193      Ok(pydict
   194          .getattr(py, item_name)
   195          .unwrap()
   196          .extract::<cpython::PyBytes>(py)?
   197          .data(py)
   198          .to_owned())
   199  }