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 }