Skip to content

Commit 0b3e3a1

Browse files
committed
feat(fortuna): use requestV2 event, parse revealed event from tx logs, add gas and callback fields to history API
1 parent e235218 commit 0b3e3a1

File tree

6 files changed

+95
-4
lines changed

6 files changed

+95
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Remove callback_failed, callback_return_value, and callback_gas_used from the requests table.
2+
ALTER TABLE request DROP COLUMN callback_failed;
3+
ALTER TABLE request DROP COLUMN callback_return_value;
4+
ALTER TABLE request DROP COLUMN callback_gas_used;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Add callback_failed, callback_return_value, and callback_gas_used to the requests table.
2+
ALTER TABLE request ADD COLUMN callback_failed INTEGER;
3+
ALTER TABLE request ADD COLUMN callback_return_value VARCHAR;
4+
ALTER TABLE request ADD COLUMN callback_gas_used VARCHAR(100);

apps/fortuna/src/eth_utils/utils.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use {
22
crate::{
3-
chain::ethereum::InstrumentedSignablePythContract, eth_utils::nonce_manager::NonceManaged,
3+
chain::ethereum::{InstrumentedSignablePythContract, PythRandomEvents, Revealed2Filter},
4+
eth_utils::nonce_manager::NonceManaged,
45
},
56
anyhow::{anyhow, Result},
67
backoff::ExponentialBackoff,
78
ethabi::ethereum_types::U64,
89
ethers::{
9-
contract::{ContractCall, ContractError},
10+
contract::{ContractCall, ContractError, EthLogDecode},
1011
middleware::Middleware,
1112
providers::{MiddlewareError, ProviderError},
1213
signers::Signer,
@@ -30,6 +31,7 @@ pub struct SubmitTxResult {
3031
pub fee_multiplier: u64,
3132
pub duration: Duration,
3233
pub receipt: TransactionReceipt,
34+
pub revealed_event: Revealed2Filter,
3335
}
3436

3537
#[derive(Clone, Debug)]
@@ -186,11 +188,26 @@ pub async fn submit_tx_with_backoff<T: Middleware + NonceManaged + 'static>(
186188
let duration = start_time.elapsed();
187189
let num_retries = num_retries.load(std::sync::atomic::Ordering::Relaxed);
188190

191+
let revealed_event: Revealed2Filter = {
192+
let mut found_event = None;
193+
for log in &success.logs {
194+
if let Ok(PythRandomEvents::Revealed2Filter(decoded_event)) =
195+
PythRandomEvents::decode_log(&log.clone().into())
196+
{
197+
found_event = Some(decoded_event);
198+
break;
199+
}
200+
}
201+
// A successful reveal will always emit a Revealed v2 event, so theoretically we should never get here.
202+
found_event.ok_or_else(|| SubmitTxError::ReceiptError(call.tx.clone(), success.clone()))?
203+
};
204+
189205
Ok(SubmitTxResult {
190206
num_retries,
191207
fee_multiplier: escalation_policy.get_fee_multiplier_pct(num_retries),
192208
duration,
193209
receipt: success,
210+
revealed_event,
194211
})
195212
}
196213

apps/fortuna/src/history.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use {
55
ethers::{
66
core::utils::hex::ToHex,
77
prelude::TxHash,
8-
types::{Address, U256},
8+
types::{Address, Bytes, U256},
99
utils::keccak256,
1010
},
1111
serde::Serialize,
@@ -45,6 +45,17 @@ pub enum RequestEntryState {
4545
#[schema(example = "a905ab56567d31a7fda38ed819d97bc257f3ebe385fc5c72ce226d3bb855f0fe")]
4646
#[serde_as(as = "serde_with::hex::Hex")]
4747
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,
4859
},
4960
Failed {
5061
reason: String,
@@ -120,6 +131,9 @@ struct RequestRow {
120131
provider_random_number: Option<String>,
121132
gas_used: Option<String>,
122133
info: Option<String>,
134+
callback_failed: Option<i64>,
135+
callback_return_value: Option<String>,
136+
callback_gas_used: Option<String>,
123137
}
124138

125139
impl TryFrom<RequestRow> for RequestStatus {
@@ -174,6 +188,18 @@ impl TryFrom<RequestRow> for RequestStatus {
174188
&user_random_number,
175189
&provider_random_number,
176190
),
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"))?,
177203
}
178204
}
179205
"Failed" => RequestEntryState::Failed {
@@ -313,18 +339,29 @@ impl History {
313339
provider_random_number,
314340
gas_used,
315341
combined_random_number: _,
342+
callback_failed,
343+
callback_return_value,
344+
callback_gas_used,
316345
} => {
317346
let reveal_block_number = reveal_block_number as i64;
318347
let reveal_tx_hash: String = reveal_tx_hash.encode_hex();
319348
let provider_random_number: String = provider_random_number.encode_hex();
320349
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")
322356
.bind("Completed")
323357
.bind(new_status.last_updated_at.timestamp())
324358
.bind(reveal_block_number)
325359
.bind(reveal_tx_hash)
326360
.bind(provider_random_number)
327361
.bind(gas_used)
362+
.bind(callback_failed)
363+
.bind(callback_return_value)
364+
.bind(callback_gas_used)
328365
.bind(network_id)
329366
.bind(sequence)
330367
.bind(provider.clone())
@@ -666,6 +703,9 @@ mod test {
666703
&status.user_random_number,
667704
&[40; 32],
668705
),
706+
callback_failed: false,
707+
callback_return_value: Default::default(),
708+
callback_gas_used: 100_000,
669709
};
670710
History::update_request_status(&history.pool, status.clone()).await;
671711

@@ -877,6 +917,9 @@ mod test {
877917
&status.user_random_number,
878918
&[40; 32],
879919
),
920+
callback_failed: false,
921+
callback_return_value: Default::default(),
922+
callback_gas_used: 0,
880923
};
881924
History::update_request_status(&history.pool, status.clone()).await;
882925
let mut failed_status = status.clone();

apps/fortuna/src/keeper/process_event.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ pub async fn process_event_with_backoff(
192192
&event.user_random_number,
193193
&provider_revelation,
194194
),
195+
callback_failed: result.revealed_event.callback_failed,
196+
callback_return_value: result.revealed_event.callback_return_value,
197+
callback_gas_used: result.revealed_event.callback_gas_used,
195198
};
196199
history.add(&status);
197200
tracing::info!(

apps/fortuna/src/serde.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,23 @@ pub mod u256 {
1919
U256::from_dec_str(s.as_str()).map_err(|err| D::Error::custom(err.to_string()))
2020
}
2121
}
22+
23+
pub mod u32 {
24+
use serde::{de::Error, Deserialize, Deserializer, Serializer};
25+
26+
pub fn serialize<S>(n: &u32, s: S) -> Result<S::Ok, S::Error>
27+
where
28+
S: Serializer,
29+
{
30+
s.serialize_str(&n.to_string())
31+
}
32+
33+
pub fn deserialize<'de, D>(d: D) -> Result<u32, D::Error>
34+
where
35+
D: Deserializer<'de>,
36+
{
37+
let s: String = Deserialize::deserialize(d)?;
38+
s.parse::<u32>()
39+
.map_err(|err| D::Error::custom(err.to_string()))
40+
}
41+
}

0 commit comments

Comments
 (0)