Skip to content

Commit

Permalink
Bugfix - fix retrieve revert reason (#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lohann authored Mar 21, 2024
1 parent 2a40d61 commit 4ed222d
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 24 deletions.
4 changes: 3 additions & 1 deletion chains/astar/server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ use subxt::{
/// dependencies to be explicitly added on the client side.
#[doc(hidden)]
pub mod ext {
pub use anyhow;
pub use rosetta_config_astar as astar_config;
pub use rosetta_config_ethereum as ethereum_config;
pub use rosetta_config_ethereum as astar_config;
pub use rosetta_core as core;
pub use subxt;
}

#[derive(Deserialize, Serialize)]
Expand Down
21 changes: 15 additions & 6 deletions chains/ethereum/server/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,21 +363,30 @@ where
Err(_) => anyhow::bail!("Invalid Transaction: failed to parse, must be a valid EIP1159, EIP-Eip2930 or Legacy"),
};

// Check if the transaction was already submitted
// Check if the transaction is already included in a block
if let Some(receipt) = self.backend.transaction_receipt(tx_hash).await? {
return Ok(self.backend.get_call_result(receipt, call_request).await);
}

// Send the transaction
let actual_hash = self.backend.send_raw_transaction(Bytes::from_iter(transaction)).await?;
if tx_hash != actual_hash {
anyhow::bail!("Transaction hash mismatch: expect {tx_hash}, got {actual_hash}");
// Check if the message is not peding
if self.backend.transaction_by_hash(tx_hash).await?.is_none() {
// Send the transaction
let actual_hash =
self.backend.send_raw_transaction(Bytes::from_iter(transaction)).await?;
if tx_hash != actual_hash {
anyhow::bail!("Transaction hash mismatch, expect {tx_hash}, got {actual_hash}");
}
}

// Wait for the transaction to be mined
// Wait for the transaction receipt
let Ok(receipt) = self.backend.wait_for_transaction_receipt(tx_hash).await else {
tracing::warn!("Transaction receipt timeout: {tx_hash:?}");
return Ok(SubmitResult::Timeout { tx_hash });
};
tracing::debug!(
"Transaction included in a block: {tx_hash:?}, status: {:?}",
receipt.status_code
);
Ok(self.backend.get_call_result(receipt, call_request).await)
}

Expand Down
6 changes: 5 additions & 1 deletion chains/ethereum/server/src/event_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,14 @@ where
// Skip if the finalized block is equal to the best finalized block
if let Some(best_finalized_block) = self.best_finalized_block.take() {
if block.header().hash() == best_finalized_block.header().hash() {
tracing::debug!("finalized block unchanged");
self.best_finalized_block = Some(best_finalized_block);
break Poll::Pending;
}
tracing::debug!(
"new finalized block {} {:?}",
block.header().number(),
block.header().hash()
);
}

// Cache the new best finalized block
Expand Down
1 change: 1 addition & 0 deletions chains/ethereum/server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub mod config {
/// dependencies to be explicitly added on the client side.
#[doc(hidden)]
pub mod ext {
pub use anyhow;
pub use rosetta_config_ethereum as config;
pub use rosetta_core as core;
pub use rosetta_ethereum_backend as backend;
Expand Down
55 changes: 39 additions & 16 deletions chains/ethereum/server/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,28 +207,51 @@ where
receipt: TransactionReceipt,
call_request: CallRequest,
) -> SubmitResult {
// Helper function used when we can't fetch the revert reason or call result
fn result_from_receipt(tx_hash: H256, receipt: TransactionReceipt) -> SubmitResult {
if receipt.status_code == Some(1) {
SubmitResult::Executed { tx_hash, result: CallResult::Success(Vec::new()), receipt }
} else {
SubmitResult::Executed { tx_hash, result: CallResult::Error, receipt }
}
}

let tx_hash = receipt.transaction_hash;

// Fetch the block to get the parent_hash
let block = match self.block(receipt.block_hash.into()).await {
Ok(Some(block)) => block,
Ok(None) => {
tracing::warn!("Block {:?} not found", receipt.block_hash);
return result_from_receipt(tx_hash, receipt);
},
Err(error) => {
tracing::warn!(
"Failed to retrieve block by hash {:?}: {error:?}",
receipt.block_hash
);
return result_from_receipt(tx_hash, receipt);
},
};

// Execute the call in the parent block_hash to get the transaction result
let exit_reason =
match self.call(&call_request, AtBlock::At(receipt.block_hash.into())).await {
match self.call(&call_request, AtBlock::At(block.header.parent_hash.into())).await {
Ok(exit_reason) => exit_reason,
Err(error) => {
tracing::error!("Failed to retrieve transaction result {tx_hash:?}: {error:?}");
if receipt.status_code == Some(1) {
return SubmitResult::Executed {
tx_hash,
result: CallResult::Success(Vec::new()),
receipt,
};
}
return SubmitResult::Executed { tx_hash, result: CallResult::Error, receipt };
tracing::warn!("Failed to retrieve transaction result {tx_hash:?}: {error:?}");
return result_from_receipt(tx_hash, receipt);
},
};
let result = match exit_reason {
ExitReason::Succeed(bytes) => CallResult::Success(bytes.to_vec()),
ExitReason::Revert(bytes) => CallResult::Revert(bytes.to_vec()),
ExitReason::Error(_) => CallResult::Error,
};
return SubmitResult::Executed { tx_hash, result, receipt };
SubmitResult::Executed {
tx_hash,
receipt,
result: match exit_reason {
ExitReason::Succeed(bytes) => CallResult::Success(bytes.to_vec()),
ExitReason::Revert(bytes) => CallResult::Revert(bytes.to_vec()),
ExitReason::Error(_) => CallResult::Error,
},
}
}

async fn estimate_eip1559_fees(&self) -> anyhow::Result<(U256, U256)> {
Expand Down
12 changes: 12 additions & 0 deletions rosetta-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ mod wallet;

pub use signer::Signer;

/// Re-exports libraries to not require any additional
/// dependencies to be explicitly added on the client side.
#[doc(hidden)]
pub mod ext {
pub use anyhow;
pub use fraction;
pub use rosetta_core as core;
pub use rosetta_server_astar as astar;
pub use rosetta_server_ethereum as ethereum;
pub use rosetta_server_polkadot as polkadot;
}

/// Supported chains.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Blockchain {
Expand Down

0 comments on commit 4ed222d

Please sign in to comment.