Skip to content

Commit cef1114

Browse files
authored
Last Bill Action Timestamp and Balances fix for only-anon endorsements (#639)
1 parent a6624b9 commit cef1114

File tree

10 files changed

+259
-35
lines changed

10 files changed

+259
-35
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Fix block propagation inconsistencies with company identities
66
* Changed default relay to `wss://bcr-relay-dev.minibill.tech`
77
* Change `endorsements` endpoint, making sure all endorsees (also anon) are displayed (breaking for API because of the return type)
8+
* Add `last_block_time` to `status` of `BitcreditBillResult` (breaking DB and API), so bill responses can be ordered by their last change
9+
* For the balance endpoint, don't add to `contingency`, if the current user is only in the guarantee chain as an anon endorsee (breaking DB change)
810

911
# 0.4.5
1012

crates/bcr-ebill-api/src/service/bill_service/data_fetching.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use super::service::BillService;
44
use super::{Error, Result};
55
use bcr_ebill_core::bill::validation::get_expiration_deadline_base_for_req_to_pay;
66
use bcr_ebill_core::bill::{BillMintStatus, BillWaitingStatePaymentData, PaymentState};
7+
use bcr_ebill_core::blockchain::Block;
78
use bcr_ebill_core::constants::RECOURSE_DEADLINE_SECONDS;
89
use bcr_ebill_core::contact::{BillParticipant, Contact};
910
use bcr_ebill_core::identity::IdentityType;
@@ -150,7 +151,8 @@ impl BillService {
150151
let time_of_drawing = first_version_bill.signing_timestamp;
151152

152153
let bill_participants = chain.get_all_nodes_from_bill(bill_keys)?;
153-
let endorsements_count = chain.get_endorsements_for_bill(bill_keys).len() as u64;
154+
let endorsements = chain.get_endorsements_for_bill(bill_keys);
155+
let endorsements_count = endorsements.len() as u64;
154156

155157
let holder = match bill.endorsee {
156158
None => &bill.payee,
@@ -293,6 +295,7 @@ impl BillService {
293295
}
294296

295297
let last_block = chain.get_latest_block();
298+
let last_block_time = last_block.timestamp();
296299
let current_waiting_state = match last_block.op_code {
297300
BillOpCode::OfferToSell => {
298301
if let OfferToSellWaitingForPayment::Yes(payment_info) = chain
@@ -559,13 +562,15 @@ impl BillService {
559562
mint: BillMintStatus { has_mint_requests },
560563
redeemed_funds_available,
561564
has_requested_funds,
565+
last_block_time,
562566
};
563567

564568
let participants = BillParticipants {
565569
drawee: bill.drawee,
566570
drawer: bill.drawer,
567571
payee: bill.payee,
568572
endorsee: bill.endorsee,
573+
endorsements,
569574
endorsements_count,
570575
all_participant_node_ids: bill_participants,
571576
};

crates/bcr-ebill-api/src/service/bill_service/mod.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ pub trait BillServiceApi: ServiceTraitBounds {
161161
async fn get_endorsements(
162162
&self,
163163
bill_id: &BillId,
164+
identity: &Identity,
164165
current_identity_node_id: &NodeId,
166+
current_timestamp: u64,
165167
) -> Result<Vec<Endorsement>>;
166168

167169
/// Clear the bill cache
@@ -3464,7 +3466,12 @@ pub mod tests {
34643466

34653467
// Verify the endorsement chain
34663468
let endorsements = final_service
3467-
.get_endorsements(&bill_id_test(), &identity.identity.node_id)
3469+
.get_endorsements(
3470+
&bill_id_test(),
3471+
&identity.identity,
3472+
&identity.identity.node_id,
3473+
1731593928,
3474+
)
34683475
.await;
34693476
assert!(endorsements.is_ok());
34703477

@@ -4003,11 +4010,19 @@ pub mod tests {
40034010
ctx.bill_blockchain_store
40044011
.expect_get_chain()
40054012
.returning(move |_| Ok(get_genesis_chain(Some(bill.clone()))));
4013+
ctx.notification_service
4014+
.expect_get_active_bill_notification()
4015+
.returning(|_| None);
40064016

40074017
let service = get_service(ctx);
40084018

40094019
let res = service
4010-
.get_endorsements(&bill_id_test(), &identity.identity.node_id)
4020+
.get_endorsements(
4021+
&bill_id_test(),
4022+
&identity.identity,
4023+
&identity.identity.node_id,
4024+
1731593928,
4025+
)
40114026
.await;
40124027
assert!(res.is_ok());
40134028
assert_eq!(res.as_ref().unwrap().len(), 0);
@@ -4016,6 +4031,9 @@ pub mod tests {
40164031
#[tokio::test]
40174032
async fn get_endorsements_multi_with_anon() {
40184033
let mut ctx = get_ctx();
4034+
ctx.notification_service
4035+
.expect_get_active_bill_notification()
4036+
.returning(|_| None);
40194037
let identity = get_baseline_identity();
40204038
let mut bill = get_baseline_bill(&bill_id_test());
40214039
let drawer = bill_identified_participant_only_node_id(NodeId::new(
@@ -4127,7 +4145,12 @@ pub mod tests {
41274145
let service = get_service(ctx);
41284146

41294147
let res = service
4130-
.get_endorsements(&bill_id_test(), &identity.identity.node_id)
4148+
.get_endorsements(
4149+
&bill_id_test(),
4150+
&identity.identity,
4151+
&identity.identity.node_id,
4152+
1731593928,
4153+
)
41314154
.await;
41324155
assert!(res.is_ok());
41334156
// with duplicates, anon are also counted
@@ -4147,6 +4170,9 @@ pub mod tests {
41474170
#[tokio::test]
41484171
async fn get_endorsements_multi() {
41494172
let mut ctx = get_ctx();
4173+
ctx.notification_service
4174+
.expect_get_active_bill_notification()
4175+
.returning(|_| None);
41504176
let identity = get_baseline_identity();
41514177
let mut bill = get_baseline_bill(&bill_id_test());
41524178
let drawer = bill_identified_participant_only_node_id(NodeId::new(
@@ -4259,7 +4285,12 @@ pub mod tests {
42594285
let service = get_service(ctx);
42604286

42614287
let res = service
4262-
.get_endorsements(&bill_id_test(), &identity.identity.node_id)
4288+
.get_endorsements(
4289+
&bill_id_test(),
4290+
&identity.identity,
4291+
&identity.identity.node_id,
4292+
1731593928,
4293+
)
42634294
.await;
42644295
assert!(res.is_ok());
42654296
// with duplicates
@@ -6891,13 +6922,23 @@ pub mod tests {
68916922
));
68926923
assert!(matches!(
68936924
service
6894-
.get_endorsements(&mainnet_bill_id, &node_id_test())
6925+
.get_endorsements(
6926+
&mainnet_bill_id,
6927+
&identity.identity,
6928+
&node_id_test(),
6929+
1731593928
6930+
)
68956931
.await,
68966932
Err(Error::Validation(ValidationError::InvalidBillId))
68976933
));
68986934
assert!(matches!(
68996935
service
6900-
.get_endorsements(&bill_id_test(), &mainnet_node_id)
6936+
.get_endorsements(
6937+
&bill_id_test(),
6938+
&identity.identity,
6939+
&mainnet_node_id,
6940+
1731593928
6941+
)
69016942
.await,
69026943
Err(Error::Validation(ValidationError::InvalidNodeId))
69036944
));

crates/bcr-ebill-api/src/service/bill_service/service.rs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ use bcr_ebill_core::company::{Company, CompanyKeys};
4343
use bcr_ebill_core::constants::{
4444
ACCEPT_DEADLINE_SECONDS, PAYMENT_DEADLINE_SECONDS, RECOURSE_DEADLINE_SECONDS,
4545
};
46-
use bcr_ebill_core::contact::{BillAnonParticipant, BillParticipant, Contact};
46+
use bcr_ebill_core::contact::{
47+
BillAnonParticipant, BillParticipant, Contact, LightBillParticipant,
48+
};
4749
use bcr_ebill_core::identity::{IdentityType, IdentityWithAll};
4850
use bcr_ebill_core::mint::{MintRequest, MintRequestState, MintRequestStatus};
4951
use bcr_ebill_core::notification::ActionType;
@@ -700,7 +702,26 @@ impl BillServiceApi for BillService {
700702
match bill_role {
701703
BillRole::Payee => payee_sum += sum,
702704
BillRole::Payer => payer_sum += sum,
703-
BillRole::Contingent => contingent_sum += sum,
705+
BillRole::Contingent => {
706+
// if we're in the guarantee chain, but only anonymously, we don't count it
707+
let endorsements = bill.participants.endorsements;
708+
let mut in_guarantee_chain_as_non_anon = false;
709+
for endorsement in endorsements.iter() {
710+
let holder = &endorsement.pay_to_the_order_of;
711+
// we're in the chain as non-anon
712+
if &holder.node_id() == current_identity_node_id
713+
&& matches!(holder, LightBillParticipant::Ident(_))
714+
{
715+
in_guarantee_chain_as_non_anon = true;
716+
break;
717+
}
718+
}
719+
if in_guarantee_chain_as_non_anon
720+
|| &bill.participants.drawer.node_id == current_identity_node_id
721+
{
722+
contingent_sum += sum
723+
}
724+
}
704725
};
705726
}
706727
}
@@ -1399,31 +1420,21 @@ impl BillServiceApi for BillService {
13991420
async fn get_endorsements(
14001421
&self,
14011422
bill_id: &BillId,
1423+
identity: &Identity,
14021424
current_identity_node_id: &NodeId,
1425+
current_timestamp: u64,
14031426
) -> Result<Vec<Endorsement>> {
14041427
validate_bill_id_network(bill_id)?;
14051428
validate_node_id_network(current_identity_node_id)?;
1406-
match self.store.exists(bill_id).await {
1407-
Ok(true) => (),
1408-
_ => {
1409-
return Err(Error::NotFound);
1410-
}
1411-
};
1412-
1413-
let chain = self.blockchain_store.get_chain(bill_id).await?;
1414-
let bill_keys = self.store.get_keys(bill_id).await?;
1415-
1416-
let bill_participants = chain.get_all_nodes_from_bill(&bill_keys)?;
1417-
// active identity is not part of the bill
1418-
if !bill_participants
1419-
.iter()
1420-
.any(|p| p == current_identity_node_id)
1421-
{
1422-
debug!("caller is not a participant of bill {bill_id}");
1423-
return Err(Error::NotFound);
1424-
}
1425-
1426-
let result = chain.get_endorsements_for_bill(&bill_keys);
1429+
let bill = self
1430+
.get_detail(
1431+
bill_id,
1432+
identity,
1433+
current_identity_node_id,
1434+
current_timestamp,
1435+
)
1436+
.await?;
1437+
let result = bill.participants.endorsements;
14271438
Ok(result)
14281439
}
14291440

crates/bcr-ebill-api/src/service/bill_service/test_utils.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pub fn get_baseline_cached_bill(id: BillId) -> BitcreditBillResult {
8383
node_id_test_other2(),
8484
)),
8585
endorsee: None,
86+
endorsements: vec![],
8687
endorsements_count: 5,
8788
all_participant_node_ids: vec![
8889
node_id_test(),
@@ -139,6 +140,7 @@ pub fn get_baseline_cached_bill(id: BillId) -> BitcreditBillResult {
139140
},
140141
redeemed_funds_available: false,
141142
has_requested_funds: false,
143+
last_block_time: 1731593928,
142144
},
143145
current_waiting_state: None,
144146
}

crates/bcr-ebill-core/src/bill/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ pub struct BillStatus {
287287
pub mint: BillMintStatus,
288288
pub redeemed_funds_available: bool,
289289
pub has_requested_funds: bool,
290+
pub last_block_time: u64,
290291
}
291292

292293
#[derive(Debug, Clone)]
@@ -353,6 +354,7 @@ pub struct BillParticipants {
353354
pub drawer: BillIdentParticipant,
354355
pub payee: BillParticipant,
355356
pub endorsee: Option<BillParticipant>,
357+
pub endorsements: Vec<Endorsement>,
356358
pub endorsements_count: u64,
357359
pub all_participant_node_ids: Vec<NodeId>,
358360
}
@@ -527,23 +529,23 @@ pub enum BillsFilterRole {
527529
Contingent,
528530
}
529531

530-
#[derive(Debug)]
532+
#[derive(Clone, Debug)]
531533
pub struct PastEndorsee {
532534
pub pay_to_the_order_of: LightBillIdentParticipant,
533535
pub signed: LightSignedBy,
534536
pub signing_timestamp: u64,
535537
pub signing_address: Option<PostalAddress>,
536538
}
537539

538-
#[derive(Debug)]
540+
#[derive(Clone, Debug)]
539541
pub struct Endorsement {
540542
pub pay_to_the_order_of: LightBillParticipant,
541543
pub signed: LightSignedBy,
542544
pub signing_timestamp: u64,
543545
pub signing_address: Option<PostalAddress>,
544546
}
545547

546-
#[derive(Debug)]
548+
#[derive(Clone, Debug)]
547549
pub struct LightSignedBy {
548550
pub data: LightBillParticipant,
549551
pub signatory: Option<LightBillIdentParticipant>,

0 commit comments

Comments
 (0)