Skip to content

fix(bridge): prevent ignoring data requests #2389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions bridges/centralized-ethereum/src/actors/dr_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ pub struct DrInfoBridge {
}

/// Data request state
#[derive(Serialize, Deserialize, Clone)]
#[derive(Clone, Default, Serialize, Deserialize)]
pub enum DrState {
/// New: the data request has just been posted to the smart contract.
#[default]
New,
/// Pending: the data request has been created and broadcast to witnet, but it has not been
/// included in a witnet block yet.
Expand All @@ -77,12 +78,6 @@ impl fmt::Display for DrState {
}
}

impl Default for DrState {
fn default() -> Self {
Self::New
}
}

/// Data request states in Witnet Request Board contract
#[derive(Serialize, Deserialize, Clone)]
pub enum WitnetQueryStatus {
Expand Down
46 changes: 31 additions & 15 deletions bridges/centralized-ethereum/src/actors/eth_poller.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
actors::dr_database::{
DrDatabase, DrInfoBridge, DrState, GetLastDrId, SetDrInfoBridge, WitnetQueryStatus,
DrDatabase, DrInfoBridge, GetLastDrId, SetDrInfoBridge, WitnetQueryStatus,
},
config::Config,
};
Expand Down Expand Up @@ -127,18 +127,22 @@ impl EthPoller {
}
WitnetQueryStatus::Posted => {
log::info!("[{}] new dr in wrb", i);
if let Some(set_dr_info_bridge) =
if let Ok(set_dr_info_bridge) =
process_posted_request(i.into(), &wrb_contract).await
{
dr_database_addr.do_send(set_dr_info_bridge);
} else {
break;
}
}
WitnetQueryStatus::Reported => {
log::debug!("[{}] already reported", i);
if let Some(set_dr_info_bridge) =
if let Ok(set_dr_info_bridge) =
process_posted_request(i.into(), &wrb_contract).await
{
dr_database_addr.do_send(set_dr_info_bridge);
} else {
break;
}
}
WitnetQueryStatus::Deleted => {
Expand Down Expand Up @@ -175,7 +179,7 @@ impl EthPoller {
async fn process_posted_request(
query_id: U256,
wrb_contract: &Contract<web3::transports::Http>,
) -> Option<SetDrInfoBridge> {
) -> Result<SetDrInfoBridge, web3::contract::Error> {
let dr_bytes: Result<Bytes, web3::contract::Error> = wrb_contract
.query(
"readRequestBytecode",
Expand All @@ -186,20 +190,32 @@ async fn process_posted_request(
)
.await;

// Re-route some errors as success (explanation below)
match dr_bytes {
Ok(dr_bytes) => Some(SetDrInfoBridge(
query_id,
DrInfoBridge {
dr_bytes,
dr_state: DrState::New,
dr_tx_hash: None,
dr_tx_creation_timestamp: None,
},
)),
Ok(dr_bytes) => Ok(dr_bytes),
Err(err) => {
log::error!("Fail to read dr bytes from contract: {}", err.to_string());

None
// In some versions of the bridge contracts (those based on
// `WitnetRequestBoardTrustableBase`), we may get a revert when trying to fetch the dr
// bytes for a deleted query.
// If that's the case, we can return a success here, with empty bytes, so that the
// request can locally marked as complete, and we can move on.
if err.to_string().contains("WitnetRequestBoardTrustableBase") {
log::error!("Wait! This is an instance of `WitnetRequestBoardTrustableBase`. Let's assume we got a revert because the dr bytes were deleted, and simply move on.");

Ok(Default::default())
// Otherwise, handle the error normally
} else {
Err(err)
}
}
}
// Wrap the dr bytes in a `SetDrInfoBridge` structure
}.map(|dr_bytes| SetDrInfoBridge(
query_id,
DrInfoBridge {
dr_bytes,
..Default::default()
},
))
}