github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/src/batch_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  use cpython::PythonObject;
    22  use cpython::ToPyObject;
    23  use protobuf::Message;
    24  
    25  use batch::Batch;
    26  use proto;
    27  use transaction::Transaction;
    28  
    29  impl ToPyObject for Batch {
    30      type ObjectType = cpython::PyObject;
    31  
    32      fn to_py_object(&self, py: cpython::Python) -> Self::ObjectType {
    33          let mut rust_batch = proto::batch::Batch::new();
    34          rust_batch.set_header(self.header_bytes.clone());
    35          let proto_txns = self.transactions
    36              .iter()
    37              .map(|txn| {
    38                  let mut proto_txn = proto::transaction::Transaction::new();
    39                  proto_txn.set_header(txn.header_bytes.clone());
    40                  proto_txn.set_header_signature(txn.header_signature.clone());
    41                  proto_txn.set_payload(txn.payload.clone());
    42                  proto_txn
    43              })
    44              .collect::<Vec<_>>();
    45          rust_batch.set_transactions(::protobuf::RepeatedField::from_vec(proto_txns));
    46          rust_batch.set_trace(self.trace);
    47          rust_batch.set_header_signature(self.header_signature.clone());
    48  
    49          let batch_pb2 = py.import("sawtooth_validator.protobuf.batch_pb2")
    50              .expect("unable for python to import sawtooth_validator.protobuf.batch_pb2");
    51          let batch = batch_pb2
    52              .call(py, "Batch", cpython::NoArgs, None)
    53              .expect("No Batch in batch_pb2");
    54          batch
    55              .call_method(
    56                  py,
    57                  "ParseFromString",
    58                  cpython::PyTuple::new(
    59                      py,
    60                      &[
    61                          cpython::PyBytes::new(py, &rust_batch.write_to_bytes().unwrap())
    62                              .into_object(),
    63                      ],
    64                  ),
    65                  None,
    66              )
    67              .unwrap();
    68          batch
    69      }
    70  }
    71  
    72  impl<'source> FromPyObject<'source> for Batch {
    73      fn extract(py: cpython::Python, obj: &'source cpython::PyObject) -> cpython::PyResult<Self> {
    74          let batch_bytes = obj.call_method(py, "SerializeToString", cpython::NoArgs, None)
    75              .unwrap()
    76              .extract::<Vec<u8>>(py)
    77              .unwrap();
    78          let mut proto_batch: proto::batch::Batch =
    79              ::protobuf::parse_from_bytes(batch_bytes.as_slice()).unwrap();
    80          let mut proto_batch_header: proto::batch::BatchHeader =
    81              ::protobuf::parse_from_bytes(proto_batch.get_header()).unwrap();
    82          Ok(Batch {
    83              header_signature: proto_batch.take_header_signature(),
    84              header_bytes: proto_batch.take_header(),
    85              transactions: proto_batch
    86                  .transactions
    87                  .iter_mut()
    88                  .map(|t| {
    89                      let mut proto_header: proto::transaction::TransactionHeader =
    90                          ::protobuf::parse_from_bytes(t.get_header()).unwrap();
    91                      Ok(Transaction {
    92                          header_signature: t.take_header_signature(),
    93                          header_bytes: t.take_header(),
    94                          payload: t.take_payload(),
    95                          batcher_public_key: proto_header.take_batcher_public_key(),
    96                          dependencies: proto_header.take_dependencies().to_vec(),
    97                          family_name: proto_header.take_family_name(),
    98                          family_version: proto_header.take_family_version(),
    99                          inputs: proto_header.take_inputs().to_vec(),
   100                          outputs: proto_header.take_outputs().to_vec(),
   101                          nonce: proto_header.take_nonce(),
   102                          payload_sha512: proto_header.take_payload_sha512(),
   103                          signer_public_key: proto_header.take_signer_public_key(),
   104                      })
   105                  })
   106                  .collect::<cpython::PyResult<Vec<_>>>()?,
   107              signer_public_key: proto_batch_header.take_signer_public_key(),
   108              transaction_ids: proto_batch_header.take_transaction_ids().to_vec(),
   109              trace: proto_batch.get_trace(),
   110          })
   111      }
   112  }
   113  
   114  #[cfg(test)]
   115  mod tests {
   116  
   117      use super::Batch;
   118      use cpython;
   119      use cpython::ToPyObject;
   120      use proto;
   121      use protobuf::Message;
   122      use transaction::Transaction;
   123  
   124      fn create_batch() -> Batch {
   125          let mut batch_header = proto::batch::BatchHeader::new();
   126          batch_header.set_signer_public_key("C".into());
   127          batch_header.set_transaction_ids(::protobuf::RepeatedField::from_vec(vec!["B".into()]));
   128          Batch {
   129              header_signature: "A".into(),
   130              transactions: vec![create_txn()],
   131              signer_public_key: "C".into(),
   132              transaction_ids: vec!["B".into()],
   133              trace: true,
   134  
   135              header_bytes: batch_header.write_to_bytes().unwrap(),
   136          }
   137      }
   138  
   139      fn create_txn() -> Transaction {
   140          let mut txn_header = proto::transaction::TransactionHeader::new();
   141          txn_header.set_batcher_public_key("C".into());
   142          txn_header.set_dependencies(::protobuf::RepeatedField::from_vec(vec!["D".into()]));
   143          txn_header.set_family_name("test".into());
   144          txn_header.set_family_version("1.0".into());
   145          txn_header.set_inputs(::protobuf::RepeatedField::from_vec(vec!["P".into()]));
   146          txn_header.set_outputs(::protobuf::RepeatedField::from_vec(vec!["P".into()]));
   147          txn_header.set_nonce("N".into());
   148          txn_header.set_payload_sha512("E".into());
   149          txn_header.set_signer_public_key("T".into());
   150  
   151          Transaction {
   152              header_signature: "B".into(),
   153              payload: vec![1, 2, 3],
   154              batcher_public_key: "C".into(),
   155              dependencies: vec!["D".into()],
   156              family_name: "test".into(),
   157              family_version: "1.0".into(),
   158              inputs: vec!["P".into()],
   159              outputs: vec!["P".into()],
   160              nonce: "N".into(),
   161              payload_sha512: "E".into(),
   162              signer_public_key: "T".into(),
   163  
   164              header_bytes: txn_header.write_to_bytes().unwrap(),
   165          }
   166      }
   167  
   168      #[test]
   169      fn test_basic() {
   170          let gil = cpython::Python::acquire_gil();
   171          let py = gil.python();
   172  
   173          let batch = create_batch();
   174          let resulting_batch = batch.to_py_object(py).extract::<Batch>(py).unwrap();
   175          assert_eq!(batch, resulting_batch);
   176      }
   177  }