diff --git a/CHANGELOG.md b/CHANGELOG.md index 87624b84..1ed3800d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.4.2 + +* Add logic to get endorsees from plaintext chain + # 0.4.1 * Add file and pub key to bill to share with external party and add accessors to extract data diff --git a/Cargo.toml b/Cargo.toml index d1218eb3..efdec870 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.4.1" +version = "0.4.2" edition = "2024" license = "MIT" diff --git a/crates/bcr-ebill-core/src/blockchain/bill/chain.rs b/crates/bcr-ebill-core/src/blockchain/bill/chain.rs index 89746930..770fa748 100644 --- a/crates/bcr-ebill-core/src/blockchain/bill/chain.rs +++ b/crates/bcr-ebill-core/src/blockchain/bill/chain.rs @@ -4,7 +4,7 @@ use super::block::{ BillAcceptBlockData, BillBlock, BillEndorseBlockData, BillIdentParticipantBlockData, BillIssueBlockData, BillMintBlockData, BillOfferToSellBlockData, BillParticipantBlockData, BillRecourseBlockData, BillRejectBlockData, BillRequestRecourseBlockData, - BillRequestToAcceptBlockData, BillRequestToPayBlockData, BillSellBlockData, + BillRequestToAcceptBlockData, BillRequestToPayBlockData, BillSellBlockData, HolderFromBlock, }; use super::{BillOpCode, RecourseWaitingForPayment}; use super::{OfferToSellWaitingForPayment, RecoursePaymentInfo}; @@ -44,8 +44,55 @@ impl BillBlockPlaintextWrapper { Err(Error::BlockInvalid) } } + + pub fn get_holder(&self) -> Result> { + match self.block.op_code() { + BillOpCode::Issue => { + let bill: BillIssueBlockData = borsh::from_slice(&self.plaintext_data_bytes)?; + Ok(Some(HolderFromBlock { + holder: bill.payee, + signer: BillParticipantBlockData::Ident(bill.drawer), + signatory: bill.signatory, + })) + } + BillOpCode::Endorse => { + let block: BillEndorseBlockData = borsh::from_slice(&self.plaintext_data_bytes)?; + Ok(Some(HolderFromBlock { + holder: block.endorsee, + signer: block.endorser, + signatory: block.signatory, + })) + } + BillOpCode::Mint => { + let block: BillMintBlockData = borsh::from_slice(&self.plaintext_data_bytes)?; + Ok(Some(HolderFromBlock { + holder: block.endorsee, + signer: block.endorser, + signatory: block.signatory, + })) + } + BillOpCode::Sell => { + let block: BillSellBlockData = borsh::from_slice(&self.plaintext_data_bytes)?; + Ok(Some(HolderFromBlock { + holder: block.buyer, + signer: block.seller, + signatory: block.signatory, + })) + } + BillOpCode::Recourse => { + let block: BillRecourseBlockData = borsh::from_slice(&self.plaintext_data_bytes)?; + Ok(Some(HolderFromBlock { + holder: BillParticipantBlockData::Ident(block.recoursee), + signer: BillParticipantBlockData::Ident(block.recourser), + signatory: block.signatory, + })) + } + _ => Ok(None), + } + } } +/// Gets bill parties from blocks with their plaintext data pub fn get_bill_parties_from_chain_with_plaintext( chain_with_plaintext: &[BillBlockPlaintextWrapper], ) -> Result { @@ -151,6 +198,26 @@ pub fn get_bill_parties_from_chain_with_plaintext( }) } +/// Gets endorsees from blocks with their plaintext data +pub fn get_endorsees_from_chain_with_plaintext( + chain_with_plaintext: &[BillBlockPlaintextWrapper], +) -> Vec { + let mut result: Vec = vec![]; + // iterate from the front to the back, collecting all endorsement blocks + for block_wrapper in chain_with_plaintext.iter() { + // we ignore issue blocks, since we are only interested in endorsements + if block_wrapper.block.op_code == BillOpCode::Issue { + continue; + } + if let Ok(Some(holder_from_block)) = block_wrapper.get_holder() { + let holder = holder_from_block.holder; + result.push(holder.into()); + } + } + + result +} + #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, Clone)] pub struct BillBlockchain { blocks: Vec, @@ -1349,5 +1416,15 @@ mod tests { ) .unwrap() ); + + assert_eq!( + chain.get_endorsees_for_bill(&bill_keys), + get_endorsees_from_chain_with_plaintext( + chain + .get_chain_with_plaintext_block_data(&bill_keys) + .as_ref() + .unwrap() + ) + ) } }