Skip to content

Commit

Permalink
Merge branch 'fix/svm-dependencies' into feat/swap-program-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
guibescos committed Dec 21, 2024
2 parents f43e817 + 94758a3 commit 180623a
Show file tree
Hide file tree
Showing 22 changed files with 4,025 additions and 2,504 deletions.
2,505 changes: 1,542 additions & 963 deletions Cargo.lock

Large diffs are not rendered by default.

18 changes: 6 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ serde = "1.0"
serde_json = "1.0"
serde_with = "3.9.0"
ethers = "2.0.14"
solana-sdk = "2.0.13"
solana-rpc-client = "2.0.13"
solana-transaction-status = "2.0.13"
solana-client = "2.0.13"
solana-sdk = "2.1.0"
solana-rpc-client = "=2.1.0"
solana-transaction-status = "=2.1.0"
solana-client = "=2.1.0"
email_address = "0.2.4"
anyhow = "1.0.75"
strum = "0.26.3"
Expand All @@ -38,11 +38,5 @@ async-stream = "0.3.5"
serde_yaml = "0.9.25"
url = "2.5.4"
rand = "0.8.5"

# The curve25519-dalek crate is a dependency of solana-sdk.
# This crate relies on a specific version of zeroize that is incompatible with many other packages.
# You can find more details in this issue https://github.com/solana-labs/solana/issues/26688
# Solana Labs has provided a solution for some of these package incompatibilities, which can be found here https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/Cargo.toml#L514
[patch.crates-io.curve25519-dalek]
git = "https://github.com/solana-labs/curve25519-dalek.git"
rev = "b500cdc2a920cd5bff9e2dd974d7b97349d61464"
anchor-lang = { git = "https://github.com/coral-xyz/anchor", rev = "6df05aa" }
litesvm = { git = "https://github.com/LiteSVM/litesvm", rev = "5346e86" }
4 changes: 2 additions & 2 deletions auction-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ solana-sdk = { workspace = true }
solana-client = { workspace = true }
bincode = { workspace = true }
serde_with = { workspace = true, features = ["base64"] }
anchor-lang = "0.30.1"
anchor-lang = { workspace = true }
express-relay = { path = "../contracts/svm/programs/express_relay" }
solana-rpc-client ={ workspace = true }
solana-transaction-status = { workspace = true }
borsh = "1.5.1"
litesvm = "0.3.0"
litesvm = { workspace = true }
express-relay-api-types = { path = "api-types" }
5 changes: 5 additions & 0 deletions auction-server/api-types/src/bid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use {
DisplayFromStr,
},
solana_sdk::{
clock::Slot,
signature::Signature,
transaction::VersionedTransaction,
},
Expand Down Expand Up @@ -258,6 +259,10 @@ pub struct BidCreateSvm {
#[schema(example = "SGVsbG8sIFdvcmxkIQ==", value_type = String)]
#[serde(with = "crate::serde::transaction_svm")]
pub transaction: VersionedTransaction,
/// The minimum slot required for the bid to be executed successfully
/// None if the bid can be executed at any recent slot
#[schema(example = 293106477, value_type = Option<u64>)]
pub slot: Option<Slot>,
}

#[derive(Serialize, Deserialize, ToSchema, Debug, Clone)]
Expand Down
1 change: 1 addition & 0 deletions auction-server/src/auction/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ impl ApiTrait<Svm> for Svm {
initiation_time: OffsetDateTime::now_utc(),
chain_data: entities::BidChainDataCreateSvm {
transaction: bid_create_svm.transaction.clone(),
slot: bid_create_svm.slot,
},
})
}
Expand Down
2 changes: 2 additions & 0 deletions auction-server/src/auction/entities/bid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use {
},
express_relay_api_types::bid as api,
solana_sdk::{
clock::Slot,
pubkey::Pubkey,
signature::Signature,
transaction::VersionedTransaction,
Expand Down Expand Up @@ -239,6 +240,7 @@ pub struct BidCreate<T: ChainTrait> {
#[derive(Clone, Debug)]
pub struct BidChainDataCreateSvm {
pub transaction: VersionedTransaction,
pub slot: Option<Slot>,
}

#[derive(Clone, Debug)]
Expand Down
13 changes: 10 additions & 3 deletions auction-server/src/auction/service/simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use {
client_error,
rpc_response::{
Response,
RpcResponseContext,
RpcResult,
},
},
Expand Down Expand Up @@ -166,12 +167,14 @@ impl Simulator {
Ok(result.value)
}

/// Fetches multiple accounts from the RPC in chunks
/// There is no guarantee that all the accounts will be fetched with the same slot
async fn get_multiple_accounts_chunked(
&self,
keys: &[Pubkey],
) -> RpcResult<Vec<Option<Account>>> {
let mut result = vec![];
let mut last_context = None;
let mut context_with_min_slot: Option<RpcResponseContext> = None;
const MAX_RPC_ACCOUNT_LIMIT: usize = 100;
// Ensure at least one call is made, even if keys is empty
let key_chunks = if keys.is_empty() {
Expand All @@ -189,11 +192,15 @@ impl Simulator {
for chunk_result in chunk_results {
let chunk_result = chunk_result?;
result.extend(chunk_result.value);
last_context = Some(chunk_result.context);
if context_with_min_slot.is_none()
|| context_with_min_slot.as_ref().unwrap().slot > chunk_result.context.slot
{
context_with_min_slot = Some(chunk_result.context);
}
}
Ok(Response {
value: result,
context: last_context.unwrap(), // Safe because we ensured at least one call was made
context: context_with_min_slot.unwrap(), // Safe because we ensured at least one call was made
})
}

Expand Down
74 changes: 54 additions & 20 deletions auction-server/src/auction/service/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ use {
U256,
},
},
litesvm::types::FailedTransactionMetadata,
solana_sdk::{
address_lookup_table::state::AddressLookupTable,
clock::Slot,
commitment_config::CommitmentConfig,
compute_budget,
instruction::CompiledInstruction,
Expand Down Expand Up @@ -389,7 +391,7 @@ impl Service<Svm> {
pub fn extract_submit_bid_data(
instruction: &CompiledInstruction,
) -> Result<express_relay_svm::SubmitBidArgs, RestError> {
let discriminator = express_relay_svm::instruction::SubmitBid::discriminator();
let discriminator = express_relay_svm::instruction::SubmitBid::DISCRIMINATOR;
express_relay_svm::SubmitBidArgs::try_from_slice(
&instruction.data.as_slice()[discriminator.len()..],
)
Expand All @@ -415,7 +417,7 @@ impl Service<Svm> {

instruction
.data
.starts_with(&express_relay_svm::instruction::SubmitBid::discriminator())
.starts_with(express_relay_svm::instruction::SubmitBid::DISCRIMINATOR)
})
.cloned()
.collect();
Expand Down Expand Up @@ -578,25 +580,57 @@ impl Service<Svm> {
}

pub async fn simulate_bid(&self, bid: &entities::BidCreate<Svm>) -> Result<(), RestError> {
let response = self
.config
.chain_config
.simulator
.simulate_transaction(&bid.chain_data.transaction)
.await;
let result = response.map_err(|e| {
tracing::error!("Error while simulating bid: {:?}", e);
RestError::TemporarilyUnavailable
})?;
match result.value {
Err(err) => {
let msgs = err.meta.logs;
Err(RestError::SimulationError {
result: Default::default(),
reason: msgs.join("\n"),
})
const RETRY_LIMIT: usize = 5;
const RETRY_DELAY: Duration = Duration::from_millis(100);
let mut retry_count = 0;
let bid_slot = bid.chain_data.slot.unwrap_or_default();

let should_retry = |result_slot: Slot,
retry_count: usize,
err: &FailedTransactionMetadata|
-> bool {
if result_slot < bid_slot && retry_count < RETRY_LIMIT {
tracing::warn!(
"Simulation failed with stale slot. Simulation slot: {}, Bid Slot: {}, Retry count: {}, Error: {:?}",
result_slot,
bid_slot,
retry_count,
err
);
true
} else {
false
}
Ok(_) => Ok(()),
};

loop {
let response = self
.config
.chain_config
.simulator
.simulate_transaction(&bid.chain_data.transaction)
.await;
let result = response.map_err(|e| {
tracing::error!("Error while simulating bid: {:?}", e);
RestError::TemporarilyUnavailable
})?;
return match result.value {
Err(err) => {
if should_retry(result.context.slot, retry_count, &err) {
tokio::time::sleep(RETRY_DELAY).await;
retry_count += 1;
continue;
}
let msgs = err.meta.logs;
Err(RestError::SimulationError {
result: Default::default(),
reason: msgs.join("\n"),
})
}
// Not important to check if bid slot is less than simulation slot if simulation is successful
// since we want to fix incorrect verifications due to stale slot
Ok(_) => Ok(()),
};
}
}

Expand Down
Loading

0 comments on commit 180623a

Please sign in to comment.