|
5 | 5 | ethers::{ |
6 | 6 | core::utils::hex::ToHex, |
7 | 7 | prelude::TxHash, |
8 | | - types::{Address, U256}, |
| 8 | + types::{Address, Bytes, U256}, |
9 | 9 | utils::keccak256, |
10 | 10 | }, |
11 | 11 | serde::Serialize, |
@@ -45,6 +45,17 @@ pub enum RequestEntryState { |
45 | 45 | #[schema(example = "a905ab56567d31a7fda38ed819d97bc257f3ebe385fc5c72ce226d3bb855f0fe")] |
46 | 46 | #[serde_as(as = "serde_with::hex::Hex")] |
47 | 47 | combined_random_number: [u8; 32], |
| 48 | + /// Whether the callback to the caller failed. |
| 49 | + callback_failed: bool, |
| 50 | + /// Return value from the callback. If the callback failed, this field contains |
| 51 | + /// the error code and any additional returned data. Note that "" often indicates an out-of-gas error. |
| 52 | + /// If the callback returns more than 256 bytes, only the first 256 bytes of the callback return value are included. |
| 53 | + /// NOTE: This field is the raw bytes returned from the callback, not hex-decoded. The client should decode it as needed. |
| 54 | + callback_return_value: Bytes, |
| 55 | + /// How much gas the callback used. |
| 56 | + #[schema(example = "567890", value_type = String)] |
| 57 | + #[serde(with = "crate::serde::u32")] |
| 58 | + callback_gas_used: u32, |
48 | 59 | }, |
49 | 60 | Failed { |
50 | 61 | reason: String, |
@@ -120,6 +131,9 @@ struct RequestRow { |
120 | 131 | provider_random_number: Option<String>, |
121 | 132 | gas_used: Option<String>, |
122 | 133 | info: Option<String>, |
| 134 | + callback_failed: Option<i64>, |
| 135 | + callback_return_value: Option<String>, |
| 136 | + callback_gas_used: Option<String>, |
123 | 137 | } |
124 | 138 |
|
125 | 139 | impl TryFrom<RequestRow> for RequestStatus { |
@@ -174,6 +188,18 @@ impl TryFrom<RequestRow> for RequestStatus { |
174 | 188 | &user_random_number, |
175 | 189 | &provider_random_number, |
176 | 190 | ), |
| 191 | + // Sqlx::Any doesn't support boolean types, so we need to convert from integer |
| 192 | + // https://github.com/launchbadge/sqlx/issues/2778 |
| 193 | + callback_failed: row.callback_failed.unwrap_or(0) == 1, |
| 194 | + callback_return_value: row |
| 195 | + .callback_return_value |
| 196 | + .map(|s| s.parse::<Bytes>().unwrap_or_default()) |
| 197 | + .unwrap_or_default(), |
| 198 | + callback_gas_used: row |
| 199 | + .callback_gas_used |
| 200 | + .unwrap_or_default() |
| 201 | + .parse::<u32>() |
| 202 | + .map_err(|_| anyhow::anyhow!("Failed to parse callback_gas_used"))?, |
177 | 203 | } |
178 | 204 | } |
179 | 205 | "Failed" => RequestEntryState::Failed { |
@@ -313,18 +339,29 @@ impl History { |
313 | 339 | provider_random_number, |
314 | 340 | gas_used, |
315 | 341 | combined_random_number: _, |
| 342 | + callback_failed, |
| 343 | + callback_return_value, |
| 344 | + callback_gas_used, |
316 | 345 | } => { |
317 | 346 | let reveal_block_number = reveal_block_number as i64; |
318 | 347 | let reveal_tx_hash: String = reveal_tx_hash.encode_hex(); |
319 | 348 | let provider_random_number: String = provider_random_number.encode_hex(); |
320 | 349 | let gas_used: String = gas_used.to_string(); |
321 | | - let result = sqlx::query("UPDATE request SET state = $1, last_updated_at = $2, reveal_block_number = $3, reveal_tx_hash = $4, provider_random_number = $5, gas_used = $6 WHERE network_id = $7 AND sequence = $8 AND provider = $9 AND request_tx_hash = $10") |
| 350 | + // Sqlx::Any doesn't support boolean types, so we need to convert to integer |
| 351 | + // https://github.com/launchbadge/sqlx/issues/2778 |
| 352 | + let callback_failed: i64 = if callback_failed { 1 } else { 0 }; |
| 353 | + let callback_return_value: String = callback_return_value.encode_hex(); |
| 354 | + let callback_gas_used: String = callback_gas_used.to_string(); |
| 355 | + let result = sqlx::query("UPDATE request SET state = $1, last_updated_at = $2, reveal_block_number = $3, reveal_tx_hash = $4, provider_random_number = $5, gas_used = $6, callback_failed = $7, callback_return_value = $8, callback_gas_used = $9 WHERE network_id = $10 AND sequence = $11 AND provider = $12 AND request_tx_hash = $13") |
322 | 356 | .bind("Completed") |
323 | 357 | .bind(new_status.last_updated_at.timestamp()) |
324 | 358 | .bind(reveal_block_number) |
325 | 359 | .bind(reveal_tx_hash) |
326 | 360 | .bind(provider_random_number) |
327 | 361 | .bind(gas_used) |
| 362 | + .bind(callback_failed) |
| 363 | + .bind(callback_return_value) |
| 364 | + .bind(callback_gas_used) |
328 | 365 | .bind(network_id) |
329 | 366 | .bind(sequence) |
330 | 367 | .bind(provider.clone()) |
@@ -666,6 +703,9 @@ mod test { |
666 | 703 | &status.user_random_number, |
667 | 704 | &[40; 32], |
668 | 705 | ), |
| 706 | + callback_failed: false, |
| 707 | + callback_return_value: Default::default(), |
| 708 | + callback_gas_used: 100_000, |
669 | 709 | }; |
670 | 710 | History::update_request_status(&history.pool, status.clone()).await; |
671 | 711 |
|
@@ -877,6 +917,9 @@ mod test { |
877 | 917 | &status.user_random_number, |
878 | 918 | &[40; 32], |
879 | 919 | ), |
| 920 | + callback_failed: false, |
| 921 | + callback_return_value: Default::default(), |
| 922 | + callback_gas_used: 0, |
880 | 923 | }; |
881 | 924 | History::update_request_status(&history.pool, status.clone()).await; |
882 | 925 | let mut failed_status = status.clone(); |
|
0 commit comments