1use sha2::{Digest, Sha256};
2use crate::*;
4use async_trait::async_trait;
5use cyfs_base::*;
6use cyfs_core::CoreObjectType;
7
8pub type TxHash = ObjectId;
9pub type StateHash = HashValue;
10
11pub type BlockHash = ObjectId;
12
13type ReceiptHash = HashValue;
14type TransactionHash = HashValue;
15
16pub trait BlockDescTrait {
17 fn hash(&self) -> BlockHash;
18 fn hash_str(&self) -> String;
19 fn pre_block_hash(&self) -> &BlockHash;
20 fn pre_block_hash_str(&self) -> String;
21 fn number(&self) -> i64;
22 fn coinbase(&self) -> &ObjectId;
23 fn is_pre_block_of(&self, other: &Self) -> bool;
24 fn state_hash(&self) -> &HashValue;
25 fn transactions_hash(&self) -> &HashValue;
26 fn receipts_hash(&self) -> &HashValue;
27 fn event_records_hash(&self) -> &HashValue;
28}
29
30pub trait BlockBodyTrait {
31 type Receipt;
32 fn transactions(&self) -> &Vec<MetaTx>;
33 fn receipts(&self) -> Vec<Self::Receipt>;
34 fn add_transaction(&mut self, tx: MetaTx) -> Result<usize, u32>;
36 fn add_receipts(&mut self, receipts: Vec<Self::Receipt>) -> Result<(), u32>;
37 fn add_event_record(&mut self, event_record: EventRecord);
38 fn set_event_records(&mut self, event_records: Vec<EventRecord>);
39 fn event_records(&self) -> &Vec<EventRecord>;
40}
41
42#[async_trait]
43pub trait BlockTrait {
44 type BlockDesc;
45 type BlockBody;
46 type BlockBuilder;
47 type Receipt;
48 fn new(
49 coinbase: ObjectId,
50 pre_block: Option<&Self::BlockDesc>,
51 state_hash: StateHash,
52 body: Self::BlockBody,
53 ) -> BuckyResult<Self::BlockBuilder>;
54 fn new2(
55 src_desc: &Self::BlockDesc,
56 state_hash: StateHash,
57 body: Self::BlockBody,
58 ) -> BuckyResult<Self::BlockBuilder>;
59 fn header(&self) -> &Self::BlockDesc;
60 fn transactions(&self) -> &Vec<MetaTx>;
61 fn receipts(&self) -> Vec<Self::Receipt>;
62 fn event_records(&self) -> &Vec<EventRecord>;
63 async fn sign(
64 &mut self,
65 private_key: PrivateKey,
66 sign_source: &SignatureSource,
67 ) -> BuckyResult<Signature>;
68 fn version(&self) -> u64;
69}
70
71type TxList = Vec<MetaTx>;
80type ReceiptList = Vec<Receipt>;
81type EventRecordList = Vec<EventRecord>;
82
83#[derive(Clone, RawEncode, RawDecode)]
86pub struct BlockDescContentV1 {
87 pub number: i64,
88 pub coinbase: ObjectId,
89 pub state_hash: StateHash,
90 pub pre_block_hash: BlockHash,
91 pub transactions_hash: TransactionHash,
93 pub receipts_hash: ReceiptHash,
94 }
96
97impl BlockDescContentV1 {
98 pub fn new(coinbase: ObjectId, pre_block: Option<&BlockDescV1>) -> Self {
99 let mut desc_content = BlockDescContentV1 {
100 number: 0,
101 coinbase,
102 state_hash: HashValue::default(),
103 pre_block_hash: BlockHash::default(),
104 transactions_hash: HashValue::default(),
105 receipts_hash: HashValue::default(),
106 };
108
109 if let Some(pre_header) = pre_block {
110 desc_content.number = pre_header.number() + 1;
111 desc_content.pre_block_hash = pre_header.calculate_id();
112 }
113
114 desc_content
115 }
116}
117
118impl DescContent for BlockDescContentV1 {
119 fn obj_type() -> u16 {
120 CoreObjectType::BlockV1 as u16
121 }
122
123 type OwnerType = SubDescNone;
124 type AreaType = SubDescNone;
125 type AuthorType = SubDescNone;
126 type PublicKeyType = SubDescNone;
127}
128
129#[derive(Clone, RawEncode, RawDecode)]
130pub struct BlockBodyV1 {
131 pub transactions: TxList,
132 pub receipts: Vec<ReceiptV1>,
133 }
135
136impl BodyContent for BlockBodyV1 {}
137
138impl BlockBodyV1 {
139 pub fn new() -> Self {
140 BlockBodyV1 {
141 transactions: vec![],
142 receipts: vec![],
143 }
144 }
145}
146
147impl BlockBodyTrait for BlockBodyV1 {
148 type Receipt = ReceiptV1;
149 fn transactions(&self) -> &Vec<MetaTx> {
150 &self.transactions
151 }
152
153 fn receipts(&self) -> Vec<Self::Receipt> {
154 self.receipts.clone()
155 }
156 fn add_transaction(&mut self, tx: MetaTx) -> Result<usize, u32> {
158 self.transactions.push(tx);
159 Ok(self.transactions.len() - 1)
160 }
161
162 fn add_receipts(&mut self, receipts: Vec<Self::Receipt>) -> Result<(), u32> {
163 for receipt in receipts {
164 self.receipts.push(receipt);
165 }
166 Ok(())
167 }
168
169 fn add_event_record(&mut self, _event_record: EventRecord) {
170 }
172
173 fn set_event_records(&mut self, _event_records: Vec<EventRecord>) {
174 }
176
177 fn event_records(&self) -> &Vec<EventRecord> {
178 unimplemented!()
179 }
180}
181
182pub type BlockDescV1 = NamedObjectDesc<BlockDescContentV1>;
183pub type BlockTypeV1 = NamedObjType<BlockDescContentV1, BlockBodyV1>;
184pub type BlockIdV1 = NamedObjectId<BlockTypeV1>;
185pub type BlockV1 = NamedObjectBase<BlockTypeV1>;
186pub type BlockBuilderV1 = NamedObjectBuilder<BlockDescContentV1, BlockBodyV1>;
187
188impl BlockDescTrait for NamedObjectDesc<BlockDescContentV1> {
189 fn hash(&self) -> BlockHash {
190 self.calculate_id()
191 }
192
193 fn hash_str(&self) -> String {
194 self.calculate_id().to_string()
195 }
196
197 fn pre_block_hash(&self) -> &BlockHash {
198 &self.content().pre_block_hash
199 }
200
201 fn pre_block_hash_str(&self) -> String {
202 self.content().pre_block_hash.to_hex().unwrap()
203 }
204
205 fn number(&self) -> i64 {
206 self.content().number
207 }
208
209 fn coinbase(&self) -> &ObjectId {
210 &self.content().coinbase
211 }
212
213 fn is_pre_block_of(&self, other: &Self) -> bool {
214 return (self.content().number == other.content().number + 1)
215 && (self.calculate_id().eq(&other.content().pre_block_hash));
216 }
217
218 fn state_hash(&self) -> &HashValue {
219 &self.content().state_hash
220 }
221
222 fn transactions_hash(&self) -> &HashValue {
223 &self.content().transactions_hash
224 }
225
226 fn receipts_hash(&self) -> &HashValue {
227 &self.content().receipts_hash
228 }
229
230 fn event_records_hash(&self) -> &HashValue {
231 unimplemented!()
232 }
233}
234
235#[async_trait]
236impl BlockTrait for NamedObjectBase<BlockTypeV1> {
237 type BlockDesc = BlockDescV1;
238 type BlockBody = BlockBodyV1;
239 type BlockBuilder = BlockBuilderV1;
240 type Receipt = ReceiptV1;
241
242 fn new(
243 coinbase: ObjectId,
244 pre_block: Option<&Self::BlockDesc>,
245 state_hash: StateHash,
246 body: Self::BlockBody,
247 ) -> BuckyResult<Self::BlockBuilder> {
248 let mut transactions_hasher = Sha256::new();
249 for tx in &body.transactions {
250 transactions_hasher.input(tx.desc().calculate_id().to_string())
251 }
252 let transactions_hash = HashValue::from(transactions_hasher.result());
253
254 let mut receipts_hasher = Sha256::new();
255 for receipt in &body.receipts {
256 receipts_hasher.input(receipt.to_vec()?);
257 }
258 let receipts_hash = HashValue::from(receipts_hasher.result());
259
260 let mut header = BlockDescContentV1 {
261 number: 0,
262 coinbase,
263 state_hash,
264 pre_block_hash: BlockHash::default(),
265 transactions_hash,
266 receipts_hash,
267 };
269 if let Some(pre_header) = pre_block {
270 header.number = pre_header.content().number + 1;
271 header.pre_block_hash = pre_header.calculate_id();
272 }
273
274 Ok(BlockBuilderV1::new(header, body))
275 }
276
277 fn new2(
278 src_desc: &Self::BlockDesc,
279 state_hash: StateHash,
280 body: Self::BlockBody,
281 ) -> BuckyResult<Self::BlockBuilder> {
282 let mut transactions_hasher = Sha256::new();
283 for tx in &body.transactions {
284 transactions_hasher.input(tx.desc().calculate_id().to_string())
285 }
286 let transactions_hash = HashValue::from(transactions_hasher.result());
287
288 let mut receipts_hasher = Sha256::new();
289 for receipt in &body.receipts {
290 receipts_hasher.input(receipt.to_vec()?);
291 }
292 let receipts_hash = HashValue::from(receipts_hasher.result());
293
294 let header = BlockDescContentV1 {
295 number: src_desc.number(),
296 coinbase: src_desc.coinbase().clone(),
297 state_hash,
298 pre_block_hash: src_desc.pre_block_hash().clone(),
299 transactions_hash,
300 receipts_hash,
301 };
303 let builder = BlockBuilderV1::new(header, body).create_time(src_desc.create_time());
304 Ok(builder)
305 }
306
307 fn header(&self) -> &Self::BlockDesc {
308 self.desc()
309 }
310
311 fn transactions(&self) -> &Vec<MetaTx> {
312 &self.body().as_ref().unwrap().content().transactions
313 }
314
315 fn receipts(&self) -> Vec<Self::Receipt> {
316 self.body().as_ref().unwrap().content().receipts.clone()
317 }
318
319 fn event_records(&self) -> &Vec<EventRecord> {
320 unreachable!()
321 }
322
323 async fn sign(
324 &mut self,
325 private_key: PrivateKey,
326 sign_source: &SignatureSource,
327 ) -> BuckyResult<Signature> {
328 let signer = RsaCPUObjectSigner::new(private_key.public(), private_key);
329 let sign = sign_named_object_desc(&signer, self, sign_source).await?;
330 self.signs_mut().push_desc_sign(sign.clone());
331 Ok(sign)
332 }
333
334 fn version(&self) -> u64 {
335 1
336 }
337}
338
339#[derive(Clone, RawEncode, RawDecode)]
340pub struct BlockDescContentV2 {
341 pub number: i64,
342 pub coinbase: ObjectId,
343 pub state_hash: StateHash,
344 pub pre_block_hash: BlockHash,
345 pub transactions_hash: TransactionHash,
347 pub receipts_hash: ReceiptHash,
348 pub event_records_hash: HashValue,
349}
350
351impl BlockDescContent {
352 pub fn new(coinbase: ObjectId, pre_block: Option<&BlockDesc>) -> Self {
353 if let Some(pre_header) = pre_block {
354 BlockDescContent::V2(BlockDescContentV2 {
355 number: pre_header.number() + 1,
356 coinbase,
357 state_hash: HashValue::default(),
358 pre_block_hash: pre_header.hash(),
359 transactions_hash: HashValue::default(),
360 receipts_hash: HashValue::default(),
361 event_records_hash: HashValue::default(),
362 })
363 } else {
364 BlockDescContent::V2(BlockDescContentV2 {
365 number: 0,
366 coinbase,
367 state_hash: HashValue::default(),
368 pre_block_hash: BlockHash::default(),
369 transactions_hash: HashValue::default(),
370 receipts_hash: HashValue::default(),
371 event_records_hash: HashValue::default(),
372 })
373 }
374 }
375}
376
377#[derive(Clone, RawEncode, RawDecode)]
378pub enum BlockDescContent {
379 V1(BlockDescV1),
380 V2(BlockDescContentV2),
381}
382
383impl DescContent for BlockDescContent {
384 fn obj_type() -> u16 {
385 CoreObjectType::BlockV2 as u16
386 }
387
388 type OwnerType = SubDescNone;
389 type AreaType = SubDescNone;
390 type AuthorType = SubDescNone;
391 type PublicKeyType = SubDescNone;
392}
393
394#[derive(Clone, RawEncode, RawDecode)]
395pub struct BlockBodyV2 {
396 pub transactions: TxList,
397 pub receipts: Vec<ReceiptV2>,
398 pub event_records: EventRecordList,
399}
400
401#[derive(Clone, RawEncode, RawDecode)]
402pub struct BlockBodyV3 {
403 pub transactions: TxList,
404 pub receipts: ReceiptList,
405 pub event_records: EventRecordList,
406}
407
408#[derive(Clone, RawEncode, RawDecode)]
409pub enum BlockBody {
410 V1(BlockV1, Vec<Receipt>),
411 V2(BlockBodyV2),
412 V3(BlockBodyV3),
413}
414
415impl BodyContent for BlockBody {}
416
417impl BlockBody {
418 pub fn new() -> Self {
419 BlockBody::V3(BlockBodyV3 {
420 transactions: vec![],
421 receipts: vec![],
422 event_records: vec![],
423 })
424 }
425}
426
427impl BlockBodyTrait for BlockBody {
428 type Receipt = crate::Receipt;
429 fn transactions(&self) -> &Vec<MetaTx> {
430 match self {
431 BlockBody::V1(body, _) => body.transactions(),
432 BlockBody::V2(body) => &body.transactions,
433 BlockBody::V3(body) => &body.transactions,
434 }
435 }
436
437 fn receipts(&self) -> Vec<Self::Receipt> {
438 match self {
439 BlockBody::V1(_, receipts) => receipts.clone(),
440 BlockBody::V2(body) => body.receipts.iter().map(|r| r.into()).collect(),
441 BlockBody::V3(body) => body.receipts.clone(),
442 }
443 }
444 fn add_transaction(&mut self, tx: MetaTx) -> Result<usize, u32> {
446 match self {
447 BlockBody::V1(body, _) => body
448 .body_mut()
449 .as_mut()
450 .unwrap()
451 .content_mut()
452 .add_transaction(tx),
453 BlockBody::V2(body) => {
454 body.transactions.push(tx);
455 Ok(body.transactions.len() - 1)
456 }
457 BlockBody::V3(body) => {
458 body.transactions.push(tx);
459 Ok(body.transactions.len() - 1)
460 }
461 }
462 }
463
464 fn add_receipts(&mut self, receipts: Vec<Receipt>) -> Result<(), u32> {
465 match self {
466 BlockBody::V3(body) => {
467 for receipt in receipts {
468 body.receipts.push(receipt);
469 }
470 Ok(())
471 }
472 _ => {
473 unreachable!()
474 }
475 }
476 }
477
478 fn add_event_record(&mut self, event_record: EventRecord) {
479 match self {
480 BlockBody::V3(body) => {
481 body.event_records.push(event_record);
482 }
483 _ => {
484 unreachable!()
485 }
486 }
487 }
488
489 fn set_event_records(&mut self, event_records: Vec<EventRecord>) {
490 match self {
491 BlockBody::V3(body) => {
492 body.event_records = event_records;
493 }
494 _ => {
495 unreachable!()
496 }
497 }
498 }
499
500 fn event_records(&self) -> &Vec<EventRecord> {
501 match self {
502 BlockBody::V3(body) => &body.event_records,
503 _ => {
504 unreachable!()
505 }
506 }
507 }
508}
509
510pub type BlockDesc = NamedObjectDesc<BlockDescContent>;
511pub type BlockType = NamedObjType<BlockDescContent, BlockBody>;
512pub type BlockId = NamedObjectId<BlockType>;
513pub type Block = NamedObjectBase<BlockType>;
514pub type BlockBuilder = NamedObjectBuilder<BlockDescContent, BlockBody>;
515
516impl BlockDescTrait for NamedObjectDesc<BlockDescContent> {
517 fn hash(&self) -> BlockHash {
518 match self.content() {
519 BlockDescContent::V1(desc) => desc.calculate_id(),
520 BlockDescContent::V2(_) => self.calculate_id(),
521 }
522 }
523
524 fn hash_str(&self) -> String {
525 self.hash().to_hex().unwrap()
526 }
527
528 fn pre_block_hash(&self) -> &BlockHash {
529 match self.content() {
530 BlockDescContent::V1(desc) => desc.pre_block_hash(),
531 BlockDescContent::V2(desc) => &desc.pre_block_hash,
532 }
533 }
534
535 fn pre_block_hash_str(&self) -> String {
536 match self.content() {
537 BlockDescContent::V1(desc) => desc.pre_block_hash_str(),
538 BlockDescContent::V2(desc) => desc.pre_block_hash.to_hex().unwrap(),
539 }
540 }
541
542 fn number(&self) -> i64 {
543 match self.content() {
544 BlockDescContent::V1(desc) => desc.number(),
545 BlockDescContent::V2(desc) => desc.number,
546 }
547 }
548
549 fn coinbase(&self) -> &ObjectId {
550 match self.content() {
551 BlockDescContent::V1(desc) => desc.coinbase(),
552 BlockDescContent::V2(desc) => &desc.coinbase,
553 }
554 }
555
556 fn is_pre_block_of(&self, other: &Self) -> bool {
557 return (self.number() == other.number() + 1)
558 && (self.calculate_id().eq(other.pre_block_hash()));
559 }
560
561 fn state_hash(&self) -> &HashValue {
562 match self.content() {
563 BlockDescContent::V1(desc) => desc.state_hash(),
564 BlockDescContent::V2(desc) => &desc.state_hash,
565 }
566 }
567
568 fn transactions_hash(&self) -> &HashValue {
569 match self.content() {
570 BlockDescContent::V1(desc) => desc.transactions_hash(),
571 BlockDescContent::V2(desc) => &desc.transactions_hash,
572 }
573 }
574
575 fn receipts_hash(&self) -> &HashValue {
576 match self.content() {
577 BlockDescContent::V1(desc) => desc.receipts_hash(),
578 BlockDescContent::V2(desc) => &desc.receipts_hash,
579 }
580 }
581
582 fn event_records_hash(&self) -> &HashValue {
583 match self.content() {
584 BlockDescContent::V2(desc) => &desc.event_records_hash,
585 _ => {
586 unreachable!()
587 }
588 }
589 }
590}
591
592#[async_trait]
593impl BlockTrait for NamedObjectBase<BlockType> {
594 type BlockDesc = BlockDesc;
595 type BlockBody = BlockBody;
596 type BlockBuilder = BlockBuilder;
597 type Receipt = crate::Receipt;
598
599 fn new(
600 coinbase: ObjectId,
601 pre_block: Option<&Self::BlockDesc>,
602 state_hash: StateHash,
603 body: Self::BlockBody,
604 ) -> BuckyResult<Self::BlockBuilder> {
605 let mut transactions_hasher = Sha256::new();
606 for tx in body.transactions() {
607 transactions_hasher.input(tx.desc().calculate_id().to_string())
608 }
609 let transactions_hash = HashValue::from(transactions_hasher.result());
610
611 let mut receipts_hasher = Sha256::new();
612 for receipt in body.receipts() {
613 receipts_hasher.input(receipt.to_vec()?);
614 }
615 let receipts_hash = HashValue::from(receipts_hasher.result());
616
617 let mut event_records_haser = Sha256::new();
618 for record in body.event_records() {
619 event_records_haser.input(record.to_vec()?);
620 }
621 let event_records_hash = HashValue::from(event_records_haser.result());
622
623 let header = if let Some(pre_header) = pre_block {
624 BlockDescContent::V2(BlockDescContentV2 {
625 number: pre_header.number() + 1,
626 coinbase,
627 state_hash,
628 pre_block_hash: pre_header.hash(),
629 transactions_hash,
630 receipts_hash,
631 event_records_hash,
632 })
633 } else {
634 BlockDescContent::V2(BlockDescContentV2 {
635 number: 0,
636 coinbase,
637 state_hash,
638 pre_block_hash: BlockHash::default(),
639 transactions_hash,
640 receipts_hash,
641 event_records_hash,
642 })
643 };
644
645 Ok(BlockBuilder::new(header, body))
646 }
647
648 fn new2(
649 src_desc: &Self::BlockDesc,
650 state_hash: StateHash,
651 body: Self::BlockBody,
652 ) -> BuckyResult<Self::BlockBuilder> {
653 let mut transactions_hasher = Sha256::new();
654 for tx in body.transactions() {
655 transactions_hasher.input(tx.desc().calculate_id().to_string())
656 }
657 let transactions_hash = HashValue::from(transactions_hasher.result());
658
659 let mut receipts_hasher = Sha256::new();
660 for receipt in body.receipts() {
661 receipts_hasher.input(receipt.to_vec()?);
662 }
663 let receipts_hash = HashValue::from(receipts_hasher.result());
664
665 let mut event_records_haser = Sha256::new();
666 for record in body.event_records() {
667 event_records_haser.input(record.to_vec()?);
668 }
669 let event_records_hash = HashValue::from(event_records_haser.result());
670
671 let header = BlockDescContent::V2(BlockDescContentV2 {
672 number: src_desc.number(),
673 coinbase: src_desc.coinbase().clone(),
674 state_hash,
675 pre_block_hash: src_desc.pre_block_hash().clone(),
676 transactions_hash,
677 receipts_hash,
678 event_records_hash,
679 });
680 let builder = BlockBuilder::new(header, body).create_time(src_desc.create_time());
681 Ok(builder)
682 }
683
684 fn header(&self) -> &BlockDesc {
685 self.desc()
686 }
687
688 fn transactions(&self) -> &Vec<MetaTx> {
689 &self.body().as_ref().unwrap().content().transactions()
690 }
691
692 fn receipts(&self) -> Vec<Self::Receipt> {
693 self.body().as_ref().unwrap().content().receipts()
694 }
695
696 fn event_records(&self) -> &Vec<EventRecord> {
697 &self.body().as_ref().unwrap().content().event_records()
698 }
699
700 async fn sign(
701 &mut self,
702 private_key: PrivateKey,
703 sign_source: &SignatureSource,
704 ) -> BuckyResult<Signature> {
705 let signer = RsaCPUObjectSigner::new(private_key.public(), private_key);
706 let sign = sign_named_object_desc(&signer, self, sign_source).await?;
707 self.signs_mut().push_desc_sign(sign.clone());
708 Ok(sign)
709 }
710
711 fn version(&self) -> u64 {
712 match self.desc().content() {
713 BlockDescContent::V1(_) => 1,
714 BlockDescContent::V2(_) => 2,
715 }
716 }
717}