Skip to content

Commit 84024a6

Browse files
committed
fix: some details, better error handling
1 parent 6dfcc4d commit 84024a6

File tree

3 files changed

+76
-58
lines changed

3 files changed

+76
-58
lines changed

crates/dips/src/lib.rs

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ pub enum DipsError {
147147
AbiDecoding(String),
148148
#[error("agreement is cancelled")]
149149
AgreementCancelled,
150+
#[error("invalid voucher: {0}")]
151+
InvalidVoucher(String),
150152
}
151153

152154
// TODO: send back messages
@@ -275,41 +277,48 @@ pub async fn validate_and_create_agreement(
275277
allowed_payers: impl AsRef<[Address]>,
276278
voucher: Vec<u8>,
277279
) -> Result<Uuid, DipsError> {
278-
let voucher = SignedIndexingAgreementVoucher::abi_decode(voucher.as_ref(), true)
280+
let decoded_voucher = SignedIndexingAgreementVoucher::abi_decode(voucher.as_ref(), true)
279281
.map_err(|e| DipsError::AbiDecoding(e.to_string()))?;
280-
let metadata =
281-
SubgraphIndexingVoucherMetadata::abi_decode(voucher.voucher.metadata.as_ref(), true)
282-
.map_err(|e| DipsError::AbiDecoding(e.to_string()))?;
282+
let metadata = SubgraphIndexingVoucherMetadata::abi_decode(
283+
decoded_voucher.voucher.metadata.as_ref(),
284+
true,
285+
)
286+
.map_err(|e| DipsError::AbiDecoding(e.to_string()))?;
283287

284-
voucher.validate(domain, expected_payee, allowed_payers)?;
288+
decoded_voucher.validate(domain, expected_payee, allowed_payers)?;
285289

286-
store.create_agreement(voucher.clone(), metadata).await?;
290+
store
291+
.create_agreement(decoded_voucher.clone(), metadata)
292+
.await?;
287293

288-
Ok(Uuid::from_bytes(voucher.voucher.agreement_id.into()))
294+
Ok(Uuid::from_bytes(
295+
decoded_voucher.voucher.agreement_id.into(),
296+
))
289297
}
290298

291299
pub async fn validate_and_cancel_agreement(
292300
store: Arc<dyn AgreementStore>,
293301
domain: &Eip712Domain,
294302
cancellation_request: Vec<u8>,
295303
) -> Result<Uuid, DipsError> {
296-
let request = SignedCancellationRequest::abi_decode(cancellation_request.as_ref(), true)
297-
.map_err(|e| DipsError::AbiDecoding(e.to_string()))?;
304+
let decoded_request =
305+
SignedCancellationRequest::abi_decode(cancellation_request.as_ref(), true)
306+
.map_err(|e| DipsError::AbiDecoding(e.to_string()))?;
298307

299308
let result = store
300-
.get_by_id(Uuid::from_bytes(request.request.agreement_id.into()))
309+
.get_by_id(Uuid::from_bytes(
310+
decoded_request.request.agreement_id.into(),
311+
))
301312
.await?;
302-
let agreement_and_cancelled = result.ok_or(DipsError::AgreementNotFound)?;
303-
let agreement = agreement_and_cancelled.0;
304-
let cancelled = agreement_and_cancelled.1;
313+
let (agreement, cancelled) = result.ok_or(DipsError::AgreementNotFound)?;
305314
if cancelled {
306315
return Err(DipsError::AgreementCancelled);
307316
}
308317
let expected_signer = agreement.voucher.payer;
309-
let id = Uuid::from_bytes(request.request.agreement_id.into());
310-
request.validate(domain, &expected_signer)?;
318+
let id = Uuid::from_bytes(decoded_request.request.agreement_id.into());
319+
decoded_request.validate(domain, &expected_signer)?;
311320

312-
store.cancel_agreement(request).await?;
321+
store.cancel_agreement(decoded_request).await?;
313322

314323
Ok(id)
315324
}
@@ -384,9 +393,7 @@ mod test {
384393

385394
let actual = store.get_by_id(actual_id).await.unwrap();
386395

387-
let actual_voucher_and_cancelled = actual.unwrap();
388-
let actual_voucher = actual_voucher_and_cancelled.0;
389-
let actual_cancelled = actual_voucher_and_cancelled.1;
396+
let (actual_voucher, actual_cancelled) = actual.unwrap();
390397
assert_eq!(voucher, actual_voucher);
391398
assert!(!actual_cancelled);
392399
Ok(())
@@ -590,8 +597,7 @@ mod test {
590597

591598
// Verify agreement is cancelled
592599
let result = store.get_by_id(agreement_id).await?;
593-
let agreement_and_cancelled = result.ok_or(DipsError::AgreementNotFound)?;
594-
let cancelled = agreement_and_cancelled.1;
600+
let (_, cancelled) = result.ok_or(DipsError::AgreementNotFound)?;
595601
assert!(cancelled);
596602

597603
Ok(())

crates/dips/src/store.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ pub trait AgreementStore: Sync + Send + std::fmt::Debug {
1616
async fn get_by_id(
1717
&self,
1818
id: Uuid,
19-
) -> anyhow::Result<Option<(SignedIndexingAgreementVoucher, bool)>>;
19+
) -> Result<Option<(SignedIndexingAgreementVoucher, bool)>, DipsError>;
2020
async fn create_agreement(
2121
&self,
2222
agreement: SignedIndexingAgreementVoucher,
2323
metadata: SubgraphIndexingVoucherMetadata,
24-
) -> anyhow::Result<()>;
24+
) -> Result<(), DipsError>;
2525
async fn cancel_agreement(
2626
&self,
2727
signed_cancellation: SignedCancellationRequest,
@@ -38,18 +38,26 @@ impl AgreementStore for InMemoryAgreementStore {
3838
async fn get_by_id(
3939
&self,
4040
id: Uuid,
41-
) -> anyhow::Result<Option<(SignedIndexingAgreementVoucher, bool)>> {
42-
Ok(self.data.try_read()?.get(&id).cloned())
41+
) -> Result<Option<(SignedIndexingAgreementVoucher, bool)>, DipsError> {
42+
Ok(self
43+
.data
44+
.try_read()
45+
.map_err(|e| DipsError::UnknownError(e.into()))?
46+
.get(&id)
47+
.cloned())
4348
}
4449
async fn create_agreement(
4550
&self,
4651
agreement: SignedIndexingAgreementVoucher,
4752
_medatadata: SubgraphIndexingVoucherMetadata,
48-
) -> anyhow::Result<()> {
49-
self.data.try_write()?.insert(
50-
Uuid::from_bytes(agreement.voucher.agreement_id.into()),
51-
(agreement.clone(), false),
52-
);
53+
) -> Result<(), DipsError> {
54+
self.data
55+
.try_write()
56+
.map_err(|e| DipsError::UnknownError(e.into()))?
57+
.insert(
58+
Uuid::from_bytes(agreement.voucher.agreement_id.into()),
59+
(agreement.clone(), false),
60+
);
5361

5462
Ok(())
5563
}

crates/service/src/database/dips.rs

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
use std::str::FromStr;
55

6-
use anyhow::bail;
76
use axum::async_trait;
87
use build_info::chrono::{DateTime, Utc};
98
use indexer_dips::{
@@ -19,54 +18,59 @@ pub struct PsqlAgreementStore {
1918
pub pool: PgPool,
2019
}
2120

22-
// Utility to convert alloy::alloy_primitives::Uint<256, 4> into sqlx::BigDecimal
23-
fn uint256_to_bigdecimal(uint256: &uint256) -> BigDecimal {
24-
BigDecimal::from_str(&uint256.to_string()).unwrap()
25-
}
26-
27-
fn uint32_to_i64(uint32: u32) -> i64 {
28-
uint32.into()
21+
fn uint256_to_bigdecimal(value: &uint256, field: &str) -> Result<BigDecimal, DipsError> {
22+
BigDecimal::from_str(&value.to_string())
23+
.map_err(|e| DipsError::InvalidVoucher(format!("{}: {}", field, e)))
2924
}
3025

3126
#[async_trait]
3227
impl AgreementStore for PsqlAgreementStore {
3328
async fn get_by_id(
3429
&self,
3530
id: Uuid,
36-
) -> anyhow::Result<Option<(SignedIndexingAgreementVoucher, bool)>> {
31+
) -> Result<Option<(SignedIndexingAgreementVoucher, bool)>, DipsError> {
3732
let item = sqlx::query!("SELECT * FROM indexing_agreements WHERE id=$1", id,)
3833
.fetch_one(&self.pool)
3934
.await;
4035

4136
let item = match item {
4237
Ok(item) => item,
4338
Err(sqlx::Error::RowNotFound) => return Ok(None),
44-
Err(err) => bail!(err),
39+
Err(err) => return Err(DipsError::UnknownError(err.into())),
4540
};
4641

47-
let signed =
48-
SignedIndexingAgreementVoucher::abi_decode(item.signed_payload.as_ref(), true)?;
42+
let signed = SignedIndexingAgreementVoucher::abi_decode(item.signed_payload.as_ref(), true)
43+
.map_err(|e| DipsError::AbiDecoding(e.to_string()))?;
4944
let cancelled = item.cancelled_at.is_some();
5045
Ok(Some((signed, cancelled)))
5146
}
5247
async fn create_agreement(
5348
&self,
5449
agreement: SignedIndexingAgreementVoucher,
5550
metadata: SubgraphIndexingVoucherMetadata,
56-
) -> anyhow::Result<()> {
51+
) -> Result<(), DipsError> {
5752
let id = Uuid::from_bytes(agreement.voucher.agreement_id.into());
5853
let bs = agreement.encode_vec();
5954
let now = Utc::now();
60-
let deadline =
61-
DateTime::from_timestamp(agreement.voucher.deadline.try_into().unwrap(), 0).unwrap();
62-
let base_price_per_epoch = uint256_to_bigdecimal(&metadata.basePricePerEpoch);
63-
let price_per_entity = uint256_to_bigdecimal(&metadata.pricePerEntity);
64-
let duration_epochs = uint32_to_i64(agreement.voucher.durationEpochs);
65-
let max_initial_amount = uint256_to_bigdecimal(&agreement.voucher.maxInitialAmount);
66-
let max_ongoing_amount_per_epoch =
67-
uint256_to_bigdecimal(&agreement.voucher.maxOngoingAmountPerEpoch);
68-
let min_epochs_per_collection = uint32_to_i64(agreement.voucher.minEpochsPerCollection);
69-
let max_epochs_per_collection = uint32_to_i64(agreement.voucher.maxEpochsPerCollection);
55+
let deadline_i64: i64 = agreement
56+
.voucher
57+
.deadline
58+
.try_into()
59+
.map_err(|_| DipsError::InvalidVoucher("deadline".to_string()))?;
60+
let deadline = DateTime::from_timestamp(deadline_i64, 0)
61+
.ok_or(DipsError::InvalidVoucher("deadline".to_string()))?;
62+
let base_price_per_epoch =
63+
uint256_to_bigdecimal(&metadata.basePricePerEpoch, "basePricePerEpoch")?;
64+
let price_per_entity = uint256_to_bigdecimal(&metadata.pricePerEntity, "pricePerEntity")?;
65+
let duration_epochs: i64 = agreement.voucher.durationEpochs.into();
66+
let max_initial_amount =
67+
uint256_to_bigdecimal(&agreement.voucher.maxInitialAmount, "maxInitialAmount")?;
68+
let max_ongoing_amount_per_epoch = uint256_to_bigdecimal(
69+
&agreement.voucher.maxOngoingAmountPerEpoch,
70+
"maxOngoingAmountPerEpoch",
71+
)?;
72+
let min_epochs_per_collection: i64 = agreement.voucher.minEpochsPerCollection.into();
73+
let max_epochs_per_collection: i64 = agreement.voucher.maxEpochsPerCollection.into();
7074
sqlx::query!(
7175
"INSERT INTO indexing_agreements VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,null,null,null)",
7276
id,
@@ -90,7 +94,8 @@ impl AgreementStore for PsqlAgreementStore {
9094
now
9195
)
9296
.execute(&self.pool)
93-
.await?;
97+
.await
98+
.map_err(|e| DipsError::UnknownError(e.into()))?;
9499

95100
Ok(())
96101
}
@@ -221,18 +226,17 @@ pub(crate) mod test {
221226
.unwrap();
222227

223228
// Retrieve agreement
224-
let retrieved = store.get_by_id(id).await.unwrap().unwrap();
229+
let (retrieved_signed_voucher, cancelled) = store.get_by_id(id).await.unwrap().unwrap();
225230

226-
let retrieved_voucher = &retrieved.0.voucher;
227-
let cancelled = retrieved.1;
231+
let retrieved_voucher = &retrieved_signed_voucher.voucher;
228232
let retrieved_metadata =
229233
<indexer_dips::SubgraphIndexingVoucherMetadata as SolType>::abi_decode(
230234
retrieved_voucher.metadata.as_ref(),
231235
true,
232236
)
233237
.unwrap();
234238
// Verify retrieved agreement matches original
235-
assert_eq!(retrieved.0.signature, agreement.signature);
239+
assert_eq!(retrieved_signed_voucher.signature, agreement.signature);
236240
assert_eq!(
237241
retrieved_voucher.durationEpochs,
238242
agreement.voucher.durationEpochs

0 commit comments

Comments
 (0)