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 }