1
1
use super :: super :: Result ;
2
2
use super :: PaymentInfo ;
3
3
use super :: block:: {
4
- BillBlock , BillEndorseBlockData , BillIdentParticipantBlockData , BillIssueBlockData ,
5
- BillMintBlockData , BillOfferToSellBlockData , BillParticipantBlockData , BillRecourseBlockData ,
6
- BillRequestRecourseBlockData , BillSellBlockData ,
4
+ BillAcceptBlockData , BillBlock , BillEndorseBlockData , BillIdentParticipantBlockData ,
5
+ BillIssueBlockData , BillMintBlockData , BillOfferToSellBlockData , BillParticipantBlockData ,
6
+ BillRecourseBlockData , BillRejectBlockData , BillRequestRecourseBlockData ,
7
+ BillRequestToAcceptBlockData , BillRequestToPayBlockData , BillSellBlockData ,
7
8
} ;
8
9
use super :: { BillOpCode , RecourseWaitingForPayment } ;
9
10
use super :: { OfferToSellWaitingForPayment , RecoursePaymentInfo } ;
@@ -15,6 +16,7 @@ use crate::contact::{
15
16
BillParticipant , ContactType , LightBillIdentParticipant , LightBillParticipant ,
16
17
} ;
17
18
use crate :: util:: { self , BcrKeys } ;
19
+ use borsh_derive:: { BorshDeserialize , BorshSerialize } ;
18
20
use log:: error;
19
21
use serde:: { Deserialize , Serialize } ;
20
22
use std:: collections:: HashMap ;
@@ -27,7 +29,13 @@ pub struct BillParties {
27
29
pub endorsee : Option < BillParticipantBlockData > ,
28
30
}
29
31
30
- #[ derive( Serialize , Deserialize , Debug , Clone ) ]
32
+ #[ derive( BorshSerialize , BorshDeserialize , Serialize , Deserialize , Debug , Clone ) ]
33
+ pub struct BillBlockPlaintextWrapper {
34
+ pub block : BillBlock ,
35
+ pub plaintext_data_bytes : Vec < u8 > ,
36
+ }
37
+
38
+ #[ derive( BorshSerialize , BorshDeserialize , Serialize , Deserialize , Debug , Clone ) ]
31
39
pub struct BillBlockchain {
32
40
blocks : Vec < BillBlock > ,
33
41
}
@@ -701,6 +709,81 @@ impl BillBlockchain {
701
709
endorsee : last_endorsee,
702
710
} )
703
711
}
712
+
713
+ /// For each block, adds the decrypted and serialized plaintext data next to it
714
+ /// This is an expensive operation, since it deserialized, decrypts and reserializes the block data
715
+ /// validating the integrity of the data at the end
716
+ pub fn get_chain_with_plaintext_block_data (
717
+ & self ,
718
+ bill_keys : & BillKeys ,
719
+ ) -> Result < Vec < BillBlockPlaintextWrapper > > {
720
+ let mut result = Vec :: with_capacity ( self . blocks ( ) . len ( ) ) ;
721
+ for block in self . blocks . iter ( ) {
722
+ let plaintext_data_bytes = match block. op_code ( ) {
723
+ BillOpCode :: Issue => {
724
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillIssueBlockData > ( bill_keys) ?) ?
725
+ }
726
+ BillOpCode :: Accept => {
727
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillAcceptBlockData > ( bill_keys) ?) ?
728
+ }
729
+ BillOpCode :: Endorse => {
730
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillEndorseBlockData > ( bill_keys) ?) ?
731
+ }
732
+ BillOpCode :: RequestToAccept => borsh:: to_vec (
733
+ & block. get_decrypted_block :: < BillRequestToAcceptBlockData > ( bill_keys) ?,
734
+ ) ?,
735
+ BillOpCode :: RequestToPay => borsh:: to_vec (
736
+ & block. get_decrypted_block :: < BillRequestToPayBlockData > ( bill_keys) ?,
737
+ ) ?,
738
+ BillOpCode :: OfferToSell => borsh:: to_vec (
739
+ & block. get_decrypted_block :: < BillOfferToSellBlockData > ( bill_keys) ?,
740
+ ) ?,
741
+ BillOpCode :: Sell => {
742
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillSellBlockData > ( bill_keys) ?) ?
743
+ }
744
+ BillOpCode :: Mint => {
745
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillMintBlockData > ( bill_keys) ?) ?
746
+ }
747
+ BillOpCode :: RejectToAccept => {
748
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillRejectBlockData > ( bill_keys) ?) ?
749
+ }
750
+ BillOpCode :: RejectToPay => {
751
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillRejectBlockData > ( bill_keys) ?) ?
752
+ }
753
+ BillOpCode :: RejectToBuy => {
754
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillRejectBlockData > ( bill_keys) ?) ?
755
+ }
756
+ BillOpCode :: RejectToPayRecourse => {
757
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillRejectBlockData > ( bill_keys) ?) ?
758
+ }
759
+ BillOpCode :: RequestRecourse => borsh:: to_vec (
760
+ & block. get_decrypted_block :: < BillRequestRecourseBlockData > ( bill_keys) ?,
761
+ ) ?,
762
+ BillOpCode :: Recourse => {
763
+ borsh:: to_vec ( & block. get_decrypted_block :: < BillRecourseBlockData > ( bill_keys) ?) ?
764
+ }
765
+ } ;
766
+
767
+ if block. plaintext_hash != util:: sha256_hash ( & plaintext_data_bytes) {
768
+ return Err ( Error :: BlockInvalid ) ;
769
+ }
770
+
771
+ result. push ( BillBlockPlaintextWrapper {
772
+ block : block. clone ( ) ,
773
+ plaintext_data_bytes,
774
+ } ) ;
775
+ }
776
+
777
+ // Validate the chain from the wrapper
778
+ BillBlockchain :: new_from_blocks (
779
+ result
780
+ . iter ( )
781
+ . map ( |wrapper| wrapper. block . to_owned ( ) )
782
+ . collect :: < Vec < BillBlock > > ( ) ,
783
+ ) ?;
784
+
785
+ Ok ( result)
786
+ }
704
787
}
705
788
706
789
#[ cfg( test) ]
@@ -868,7 +951,7 @@ mod tests {
868
951
node_id_last_endorsee. clone( ) ,
869
952
identity. identity. node_id. to_owned( ) ,
870
953
chain. get_first_block( )
871
- ) , ) ) ;
954
+ ) ) ) ;
872
955
873
956
let keys = get_bill_keys ( ) ;
874
957
let result = chain. get_all_nodes_from_bill ( & keys) ;
@@ -942,4 +1025,41 @@ mod tests {
942
1025
assert_eq ! ( result. len( ) , 1 ) ;
943
1026
assert_eq ! ( result[ 0 ] . id, 2 ) ;
944
1027
}
1028
+
1029
+ #[ test]
1030
+ fn test_get_serialized_chain_with_plaintext ( ) {
1031
+ let bill = empty_bitcredit_bill ( ) ;
1032
+ let bill_id = bill. id . clone ( ) ;
1033
+ let bill_keys = get_bill_keys ( ) ;
1034
+ let identity = get_baseline_identity ( ) ;
1035
+ let mut chain = BillBlockchain :: new (
1036
+ & BillIssueBlockData :: from ( bill, None , 1731593928 ) ,
1037
+ identity. key_pair ,
1038
+ None ,
1039
+ BcrKeys :: from_private_key ( & bill_keys. private_key ) . unwrap ( ) ,
1040
+ 1731593928 ,
1041
+ )
1042
+ . unwrap ( ) ;
1043
+ let node_id_last_endorsee =
1044
+ NodeId :: new ( BcrKeys :: new ( ) . pub_key ( ) , bitcoin:: Network :: Testnet ) ;
1045
+ assert ! ( chain. try_add_block( get_offer_to_sell_block(
1046
+ node_id_last_endorsee. clone( ) ,
1047
+ identity. identity. node_id. to_owned( ) ,
1048
+ chain. get_first_block( )
1049
+ ) ) ) ;
1050
+
1051
+ let chain_with_plaintext = chain. get_chain_with_plaintext_block_data ( & bill_keys) ;
1052
+ assert ! ( chain_with_plaintext. is_ok( ) ) ;
1053
+ assert_eq ! ( chain_with_plaintext. as_ref( ) . unwrap( ) . len( ) , 2 ) ;
1054
+
1055
+ let first = chain_with_plaintext. as_ref ( ) . unwrap ( ) [ 0 ] . clone ( ) ;
1056
+ let decrypted_block_data: BillIssueBlockData =
1057
+ borsh:: from_slice ( & first. plaintext_data_bytes ) . unwrap ( ) ;
1058
+ assert_eq ! ( decrypted_block_data. id, bill_id) ;
1059
+
1060
+ let second = chain_with_plaintext. as_ref ( ) . unwrap ( ) [ 1 ] . clone ( ) ;
1061
+ let decrypted_block_data: BillOfferToSellBlockData =
1062
+ borsh:: from_slice ( & second. plaintext_data_bytes ) . unwrap ( ) ;
1063
+ assert_eq ! ( decrypted_block_data. buyer. node_id( ) , node_id_last_endorsee) ;
1064
+ }
945
1065
}
0 commit comments