Skip to content

Commit 24b6a96

Browse files
authored
Add Basic Dev Mode for Bill Chains (#642)
1 parent cef1114 commit 24b6a96

File tree

15 files changed

+213
-26
lines changed

15 files changed

+213
-26
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# 0.4.7
2+
3+
* Added basic Dev Mode
4+
* Can be activated using the config flag `dev_mode: true`
5+
* If activated, it's possible to fetch a full JSON Bill Chain by ID with the bill data decrypted for debugging
6+
* Endpoint: `dev_mode_get_full_bill_chain(bill_id: string): Promise<string[]>` on `Bill` api
7+
* The resulting nested list of JSON strings can be consumed like this:
8+
```javascript
9+
await billApi.dev_mode_get_full_bill_chain(bill_id).map((b) => {
10+
const block = JSON.parse(b);
11+
return { ...block, data: JSON.parse(block.data) };
12+
})
13+
```
14+
115
# 0.4.6
216

317
* Add basic logic for implementing (social) identity proofs

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[workspace.package]
2-
version = "0.4.6"
2+
version = "0.4.7"
33
edition = "2024"
44
license = "MIT"
55

crates/bcr-ebill-api/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct Config {
3131
pub nostr_config: NostrConfig,
3232
pub mint_config: MintConfig,
3333
pub payment_config: PaymentConfig,
34+
pub dev_mode_config: DevModeConfig,
3435
}
3536

3637
static CONFIG: OnceLock<Config> = OnceLock::new();
@@ -47,6 +48,13 @@ impl Config {
4748
}
4849
}
4950

51+
/// Developer Mode specific configuration
52+
#[derive(Debug, Clone, Default)]
53+
pub struct DevModeConfig {
54+
/// Whether dev mode is on
55+
pub on: bool,
56+
}
57+
5058
/// Payment specific configuration
5159
#[derive(Debug, Clone, Default)]
5260
pub struct PaymentConfig {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::util::BcrKeys;
1313
use async_trait::async_trait;
1414
use bcr_ebill_core::ServiceTraitBounds;
1515
use bcr_ebill_core::bill::{BillAction, BillIssueData, PastPaymentResult};
16+
use bcr_ebill_core::blockchain::bill::chain::BillBlockPlaintextWrapper;
1617

1718
pub use error::Error;
1819
#[cfg(test)]
@@ -218,6 +219,13 @@ pub trait BillServiceApi: ServiceTraitBounds {
218219

219220
/// Check mint state for all bills
220221
async fn check_mint_state_for_all_bills(&self) -> Result<()>;
222+
223+
/// If dev mode is on, return the full bill chain with decrypted data
224+
async fn dev_mode_get_full_bill_chain(
225+
&self,
226+
bill_id: &BillId,
227+
current_identity_node_id: &NodeId,
228+
) -> Result<Vec<BillBlockPlaintextWrapper>>;
221229
}
222230

223231
#[cfg(test)]

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use bcr_ebill_core::bill::{
3838
use bcr_ebill_core::blockchain::bill::block::{
3939
BillParticipantBlockData, BillRequestRecourseBlockData,
4040
};
41+
use bcr_ebill_core::blockchain::bill::chain::BillBlockPlaintextWrapper;
4142
use bcr_ebill_core::blockchain::bill::create_bill_to_share_with_external_party;
4243
use bcr_ebill_core::company::{Company, CompanyKeys};
4344
use bcr_ebill_core::constants::{
@@ -1799,4 +1800,43 @@ impl BillServiceApi for BillService {
17991800
Err(Error::RejectMintRequestNotOffered)
18001801
}
18011802
}
1803+
1804+
async fn dev_mode_get_full_bill_chain(
1805+
&self,
1806+
bill_id: &BillId,
1807+
current_identity_node_id: &NodeId,
1808+
) -> Result<Vec<BillBlockPlaintextWrapper>> {
1809+
// if dev mode is off - we return an error
1810+
if !get_config().dev_mode_config.on {
1811+
error!("Called dev mode operation with dev mode disabled - please enable!");
1812+
return Err(Error::InvalidOperation);
1813+
}
1814+
1815+
validate_bill_id_network(bill_id)?;
1816+
validate_node_id_network(current_identity_node_id)?;
1817+
1818+
// if there is no such bill, we return an error
1819+
match self.store.exists(bill_id).await {
1820+
Ok(true) => (),
1821+
_ => {
1822+
return Err(Error::NotFound);
1823+
}
1824+
};
1825+
1826+
let chain = self.blockchain_store.get_chain(bill_id).await?;
1827+
let bill_keys = self.store.get_keys(bill_id).await?;
1828+
let bill_participant_node_ids = chain.get_all_nodes_from_bill(&bill_keys)?;
1829+
1830+
// if currently active identity is not part of the bill, we can't access it
1831+
if !bill_participant_node_ids
1832+
.iter()
1833+
.any(|p| p == current_identity_node_id)
1834+
{
1835+
return Err(Error::NotFound);
1836+
}
1837+
1838+
let plaintext_chain = chain.get_chain_with_plaintext_block_data(&bill_keys)?;
1839+
1840+
Ok(plaintext_chain)
1841+
}
18021842
}

crates/bcr-ebill-api/src/tests/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
#[allow(clippy::module_inception)]
33
pub mod tests {
44
use crate::service::notification_service::{self, chain_keys::ChainKeyServiceApi};
5-
use crate::{CONFIG, DbContext, MintConfig, NostrConfig, PaymentConfig, data::bill::BillKeys};
5+
use crate::{
6+
CONFIG, DbContext, DevModeConfig, MintConfig, NostrConfig, PaymentConfig,
7+
data::bill::BillKeys,
8+
};
69
use async_trait::async_trait;
710
use bcr_ebill_core::{
811
NodeId, OptionalPostalAddress, PostalAddress, PublicKey, SecretKey, ServiceTraitBounds,
@@ -476,6 +479,9 @@ pub mod tests {
476479
},
477480
payment_config: PaymentConfig {
478481
num_confirmations_for_payment: 6,
482+
},
483+
dev_mode_config: DevModeConfig {
484+
on: false
479485
}
480486
});
481487
}

crates/bcr-ebill-core/src/blockchain/bill/block.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub struct BillBlockDataToHash {
5959
}
6060

6161
/// Data for reject to accept/pay/recourse
62-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
62+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
6363
pub struct BillRejectBlockData {
6464
pub rejecter: BillIdentParticipantBlockData, // reject to accept/pay/recourse has to be identified
6565
pub signatory: Option<BillSignatoryBlockData>,
@@ -82,7 +82,7 @@ impl Validate for BillRejectBlockData {
8282
}
8383

8484
/// Data for reject to buy
85-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
85+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
8686
pub struct BillRejectToBuyBlockData {
8787
pub rejecter: BillParticipantBlockData, // reject to buy can be done by anon
8888
pub signatory: Option<BillSignatoryBlockData>,
@@ -104,7 +104,7 @@ impl Validate for BillRejectToBuyBlockData {
104104
}
105105
}
106106

107-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
107+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
108108
pub struct BillIssueBlockData {
109109
pub id: BillId,
110110
pub country_of_issuing: String,
@@ -200,7 +200,7 @@ impl BillIssueBlockData {
200200
}
201201
}
202202

203-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
203+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
204204
pub struct BillAcceptBlockData {
205205
pub accepter: BillIdentParticipantBlockData, // accepter is drawer and has to be identified
206206
pub signatory: Option<BillSignatoryBlockData>,
@@ -222,7 +222,7 @@ impl Validate for BillAcceptBlockData {
222222
}
223223
}
224224

225-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
225+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
226226
pub struct BillRequestToPayBlockData {
227227
pub requester: BillParticipantBlockData, // requester is holder and can be anon
228228
pub currency: String,
@@ -247,7 +247,7 @@ impl Validate for BillRequestToPayBlockData {
247247
}
248248
}
249249

250-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
250+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
251251
pub struct BillRequestToAcceptBlockData {
252252
pub requester: BillParticipantBlockData, // requester is holder and can be anon
253253
pub signatory: Option<BillSignatoryBlockData>,
@@ -269,7 +269,7 @@ impl Validate for BillRequestToAcceptBlockData {
269269
}
270270
}
271271

272-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
272+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
273273
pub struct BillMintBlockData {
274274
pub endorser: BillParticipantBlockData, // bill can be minted by anon
275275
pub endorsee: BillParticipantBlockData, // mints can be anon
@@ -302,7 +302,7 @@ impl Validate for BillMintBlockData {
302302
}
303303
}
304304

305-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
305+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
306306
pub struct BillOfferToSellBlockData {
307307
pub seller: BillParticipantBlockData, // seller is holder and can be anon
308308
pub buyer: BillParticipantBlockData, // buyer can be anon
@@ -340,7 +340,7 @@ impl Validate for BillOfferToSellBlockData {
340340
}
341341
}
342342

343-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
343+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
344344
pub struct BillSellBlockData {
345345
pub seller: BillParticipantBlockData, // seller is holder and can be anon
346346
pub buyer: BillParticipantBlockData, // buyer can be anon
@@ -378,7 +378,7 @@ impl Validate for BillSellBlockData {
378378
}
379379
}
380380

381-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
381+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
382382
pub struct BillEndorseBlockData {
383383
pub endorser: BillParticipantBlockData, // endorser is holder and can be anon
384384
pub endorsee: BillParticipantBlockData, // endorsee can be anon
@@ -406,7 +406,7 @@ impl Validate for BillEndorseBlockData {
406406
}
407407
}
408408

409-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
409+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
410410
pub struct BillRequestRecourseBlockData {
411411
pub recourser: BillIdentParticipantBlockData, // anon can't do recourse
412412
pub recoursee: BillIdentParticipantBlockData, // anon can't be recoursed against
@@ -418,7 +418,7 @@ pub struct BillRequestRecourseBlockData {
418418
pub signing_address: PostalAddress, // address of the endorser
419419
}
420420

421-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)]
421+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
422422
pub enum BillRecourseReasonBlockData {
423423
Accept,
424424
Pay,
@@ -446,7 +446,7 @@ impl Validate for BillRequestRecourseBlockData {
446446
}
447447
}
448448

449-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
449+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
450450
pub struct BillRecourseBlockData {
451451
pub recourser: BillIdentParticipantBlockData, // anon can't do recourse
452452
pub recoursee: BillIdentParticipantBlockData, // anon can't be recoursed against
@@ -481,7 +481,7 @@ impl Validate for BillRecourseBlockData {
481481
}
482482

483483
/// Participant in a bill transaction - either anonymous, or identified
484-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)]
484+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
485485
pub enum BillParticipantBlockData {
486486
Anon(BillAnonParticipantBlockData),
487487
Ident(BillIdentParticipantBlockData),
@@ -547,7 +547,7 @@ impl Validate for BillParticipantBlockData {
547547
}
548548

549549
/// Anon bill participany data
550-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)]
550+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
551551
pub struct BillAnonParticipantBlockData {
552552
pub node_id: NodeId,
553553
}
@@ -559,7 +559,7 @@ impl Validate for BillAnonParticipantBlockData {
559559
}
560560

561561
/// Legal data for parties of a bill within the liability chain
562-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)]
562+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
563563
pub struct BillIdentParticipantBlockData {
564564
pub t: ContactType,
565565
pub node_id: NodeId,
@@ -654,7 +654,7 @@ impl From<BillIdentParticipantBlockData> for LightBillIdentParticipant {
654654
}
655655

656656
/// The name and node_id of a company signatory
657-
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
657+
#[derive(BorshSerialize, BorshDeserialize, Serialize, Debug, Clone, PartialEq)]
658658
pub struct BillSignatoryBlockData {
659659
pub node_id: NodeId,
660660
pub name: String,

crates/bcr-ebill-core/src/blockchain/bill/chain.rs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use super::{BillOpCode, RecourseWaitingForPayment};
1010
use super::{OfferToSellWaitingForPayment, RecoursePaymentInfo};
1111
use crate::NodeId;
1212
use crate::bill::{BillKeys, Endorsement, LightSignedBy, PastEndorsee, PastPaymentStatus};
13+
use crate::blockchain::bill::block::BillRejectToBuyBlockData;
1314
use crate::blockchain::{Block, Blockchain, Error};
1415
use crate::constants::{PAYMENT_DEADLINE_SECONDS, RECOURSE_DEADLINE_SECONDS};
1516
use crate::contact::{
@@ -90,6 +91,64 @@ impl BillBlockPlaintextWrapper {
9091
_ => Ok(None),
9192
}
9293
}
94+
95+
/// This is only used for dev mode
96+
pub fn to_json_text(&self) -> Result<String> {
97+
let mut block = self.block.clone();
98+
let block_data_string: String = match self.block.op_code() {
99+
BillOpCode::Issue => {
100+
Self::borsh_to_json_string::<BillIssueBlockData>(&self.plaintext_data_bytes)?
101+
}
102+
BillOpCode::Accept => {
103+
Self::borsh_to_json_string::<BillAcceptBlockData>(&self.plaintext_data_bytes)?
104+
}
105+
BillOpCode::Endorse => {
106+
Self::borsh_to_json_string::<BillEndorseBlockData>(&self.plaintext_data_bytes)?
107+
}
108+
BillOpCode::RequestToAccept => Self::borsh_to_json_string::<
109+
BillRequestToAcceptBlockData,
110+
>(&self.plaintext_data_bytes)?,
111+
BillOpCode::RequestToPay => {
112+
Self::borsh_to_json_string::<BillRequestToPayBlockData>(&self.plaintext_data_bytes)?
113+
}
114+
BillOpCode::OfferToSell => {
115+
Self::borsh_to_json_string::<BillOfferToSellBlockData>(&self.plaintext_data_bytes)?
116+
}
117+
BillOpCode::Sell => {
118+
Self::borsh_to_json_string::<BillSellBlockData>(&self.plaintext_data_bytes)?
119+
}
120+
BillOpCode::Mint => {
121+
Self::borsh_to_json_string::<BillMintBlockData>(&self.plaintext_data_bytes)?
122+
}
123+
BillOpCode::RejectToAccept => {
124+
Self::borsh_to_json_string::<BillRejectBlockData>(&self.plaintext_data_bytes)?
125+
}
126+
BillOpCode::RejectToPay => {
127+
Self::borsh_to_json_string::<BillRejectBlockData>(&self.plaintext_data_bytes)?
128+
}
129+
BillOpCode::RejectToBuy => {
130+
Self::borsh_to_json_string::<BillRejectToBuyBlockData>(&self.plaintext_data_bytes)?
131+
}
132+
BillOpCode::RejectToPayRecourse => {
133+
Self::borsh_to_json_string::<BillRejectBlockData>(&self.plaintext_data_bytes)?
134+
}
135+
BillOpCode::RequestRecourse => Self::borsh_to_json_string::<
136+
BillRequestRecourseBlockData,
137+
>(&self.plaintext_data_bytes)?,
138+
BillOpCode::Recourse => {
139+
Self::borsh_to_json_string::<BillRecourseBlockData>(&self.plaintext_data_bytes)?
140+
}
141+
};
142+
block.data = block_data_string;
143+
serde_json::to_string(&block).map_err(|e| Error::JSON(e.to_string()))
144+
}
145+
146+
fn borsh_to_json_string<T: borsh::BorshDeserialize + serde::Serialize>(
147+
bytes: &[u8],
148+
) -> Result<String> {
149+
let block_data: T = borsh::from_slice(bytes)?;
150+
serde_json::to_string(&block_data).map_err(|e| Error::JSON(e.to_string()))
151+
}
93152
}
94153

95154
/// Gets bill parties from blocks with their plaintext data
@@ -937,9 +996,9 @@ impl BillBlockchain {
937996
BillOpCode::RejectToPay => {
938997
borsh::to_vec(&block.get_decrypted_block::<BillRejectBlockData>(bill_keys)?)?
939998
}
940-
BillOpCode::RejectToBuy => {
941-
borsh::to_vec(&block.get_decrypted_block::<BillRejectBlockData>(bill_keys)?)?
942-
}
999+
BillOpCode::RejectToBuy => borsh::to_vec(
1000+
&block.get_decrypted_block::<BillRejectToBuyBlockData>(bill_keys)?,
1001+
)?,
9431002
BillOpCode::RejectToPayRecourse => {
9441003
borsh::to_vec(&block.get_decrypted_block::<BillRejectBlockData>(bill_keys)?)?
9451004
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ pub enum Error {
6969
/// The given blockchain type string could not be converted to a valid type
7070
#[error("Invalid blockchain type: {0}")]
7171
InvalidBlockchainType(String),
72+
73+
/// Errors from JSON serialization
74+
#[error("JSON serialization error: {0}")]
75+
JSON(String),
7276
}
7377

7478
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]

0 commit comments

Comments
 (0)