1use cyfs_base::*;
2use sha2::{Digest, Sha256};
3use crate::contract::*;
4use crate::{MetaExtensionTx, NFTAgreeApplyTx, NFTApplyBuyTx, NFTAuctionTx, NFTBidTx, NFTBuyTx, NFTCancelApplyBuyTx, NFTCancelSellTx, NFTCreateTx, NFTCreateTx2, NFTLikeTx, NFTSellTx, NFTSellTx2, NFTSetNameTx, NFTTransTx, SNService, SPVTx};
5use async_trait::async_trait;
6use cyfs_core::CoreObjectType;
7use generic_array::typenum::U32;
8use generic_array::GenericArray;
9use serde::{Deserialize, Serialize};
10use std::convert::TryFrom;
11
12#[derive(Clone, Debug, RawEncode, RawDecode)]
13pub enum MetaTxBody {
14 TransBalance(TransBalanceTx),
15 CreateUnion(CreateUnionTx),
16 DeviateUnion(DeviateUnionTx), WithdrawFromUnion(WithdrawFromUnionTx),
18 CreateDesc(CreateDescTx), UpdateDesc(UpdateDescTx), RemoveDesc(RemoveDescTx), BidName(BidNameTx), UpdateName(UpdateNameTx),
23 TransName(TransNameTx),
24 Contract(ContractTx), SetConfig(SetConfigTx),
26 AuctionName(AuctionNameTx),
27 CancelAuctionName(CancelAuctionNameTx),
28 BuyBackName(BuyBackNameTx),
29 BTCCoinageRecord(BTCCoinageRecordTx),
30 WithdrawToOwner(WithdrawToOwner),
31 CreateMinerGroup(MinerGroup),
32 UpdateMinerGroup(MinerGroup),
33 CreateSubChainAccount(MinerGroup),
34 UpdateSubChainAccount(MinerGroup),
35 SubChainWithdraw(SubChainWithdrawTx),
36 WithdrawFromSubChain(WithdrawFromSubChainTx),
37 SubChainCoinageRecord(SubChainCoinageRecordTx),
38 Extension(MetaExtensionTx),
39
40 CreateContract(CreateContractTx),
42 CreateContract2(CreateContract2Tx),
43 CallContract(CallContractTx),
44
45 SetBenefi(SetBenefiTx),
47
48 NFTCreate(NFTCreateTx),
49 NFTAuction(NFTAuctionTx),
50 NFTBid(NFTBidTx),
51 NFTBuy(NFTBuyTx),
52 NFTSell(NFTSellTx),
53 NFTApplyBuy(NFTApplyBuyTx),
54 NFTCancelApplyBuyTx(NFTCancelApplyBuyTx),
55 NFTAgreeApply(NFTAgreeApplyTx),
56 NFTLike(NFTLikeTx),
57 NFTCancelSellTx(NFTCancelSellTx),
58 NFTSetNameTx(NFTSetNameTx),
59 NFTCreate2(NFTCreateTx2),
60 NFTSell2(NFTSellTx2),
61 NFTTrans(NFTTransTx),
62}
63
64#[derive(Clone, Debug, RawEncode, RawDecode)]
65pub struct TransBalanceTx {
66 pub ctid: CoinTokenId,
67 pub to: Vec<(ObjectId, i64)>, }
70
71#[derive(Clone, Debug, RawEncode, RawDecode)]
72pub struct CreateUnionBody {
73 pub account: UnionAccount,
74 pub ctid: CoinTokenId,
75 pub left_balance: i64,
76 pub right_balance: i64,
77}
78
79#[derive(Clone, Debug, RawEncode, RawDecode)]
80pub struct DeviateUnionBody {
81 pub ctid: CoinTokenId,
82 pub seq: i64,
83 pub deviation: i64, pub union: ObjectId,
85}
86
87#[derive(Clone, Debug, RawEncode, RawDecode)]
89pub struct SignedTx<T> {
90 pub body: T,
91 pub signs: Vec<Signature>,
92}
93
94pub type CreateUnionTx = SignedTx<CreateUnionBody>;
95impl SignedTx<CreateUnionBody> {
96 pub fn new(union_account: UnionAccount, ctid: CoinTokenId) -> CreateUnionTx {
97 CreateUnionTx {
98 body: CreateUnionBody {
99 account: union_account,
100 ctid,
101 left_balance: 0,
102 right_balance: 0,
103 },
104 signs: vec![],
105 }
106 }
107
108 pub fn set_recharge_amount(&mut self, account: &ObjectId, amount: i64) -> BuckyResult<()> {
109 if self.body.account.desc().content().left() == account {
110 self.body.left_balance = amount;
111 } else if self.body.account.desc().content().right() == account {
112 self.body.right_balance = amount;
113 } else {
114 return Err(BuckyError::new(BuckyErrorCode::Failed, "Failed"));
115 }
116 Ok(())
117 }
118}
119
120pub type DeviateUnionTx = SignedTx<DeviateUnionBody>;
121impl SignedTx<DeviateUnionBody> {
122 pub fn new(union: ObjectId, ctid: CoinTokenId, seq: i64, deviation: i64) -> DeviateUnionTx {
123 DeviateUnionTx {
124 body: DeviateUnionBody {
125 ctid,
126 seq,
127 deviation,
128 union,
129 },
130 signs: vec![],
131 }
132 }
133}
134
135impl<T: RawEncode> SignedTx<T> {
136 pub fn sign(&mut self, id: ObjectLink, secret: PrivateKey) -> BuckyResult<()> {
137 let mut i = 0;
138 let mut find = false;
139 for sign in &self.signs {
140 if let SignatureSource::Object(sign_obj_link) = sign.sign_source() {
141 if *sign_obj_link == id {
142 find = true;
143 break;
144 }
145 }
146 i += 1;
147 }
148 if find {
149 self.signs.remove(i);
150 }
151
152 let signer = RsaCPUObjectSigner::new(secret.public(), secret);
153 let data = self.body.to_vec().map_err(|e| {
154 log::error!("UnionAccountTx<T>::sign/body.to_vec error:{}", e);
155 e
156 })?;
157
158 let hash = hash_data(data.as_slice());
159 let signature =
160 async_std::task::block_on(signer.sign(hash.as_slice(), &SignatureSource::Object(id)))
161 .map_err(|e| {
162 log::error!("UnionAccountTx<T>::sign/sign error:{}", e);
163 e
164 })?;
165
166 self.signs.push(signature);
167 Ok(())
168 }
169
170 pub async fn async_sign(&mut self, id: ObjectLink, secret: PrivateKey) -> BuckyResult<()> {
171 let mut i = 0;
172 let mut find = false;
173 for sign in &self.signs {
174 if let SignatureSource::Object(sign_obj_link) = sign.sign_source() {
175 if *sign_obj_link == id {
176 find = true;
177 break;
178 }
179 }
180 i += 1;
181 }
182 if find {
183 self.signs.remove(i);
184 }
185
186 let signer = RsaCPUObjectSigner::new(secret.public(), secret);
187 let data = self.body.to_vec().map_err(|e| {
188 log::error!("UnionAccountTx<T>::async_sign/body.to_vec error:{}", e);
189 e
190 })?;
191
192 let hash = hash_data(data.as_slice());
193 let signature = signer
194 .sign(hash.as_slice(), &SignatureSource::Object(id))
195 .await
196 .map_err(|e| {
197 log::error!("UnionAccountTx<T>::async_sign/sign error:{}", e);
198 e
199 })?;
200
201 self.signs.push(signature);
202 Ok(())
203 }
204
205 pub fn verify(&self, key_list: Vec<(ObjectId, PublicKey)>) -> BuckyResult<bool> {
206 let data = self.body.to_vec().map_err(|e| {
207 log::error!("UnionAccountTx<T>::verify/body.to_vec error:{}", e);
208 e
209 })?;
210
211 let hash = hash_data(data.as_slice());
212 for (id, public_key) in key_list {
213 let mut verify = false;
214 for sign in &self.signs {
215 if let SignatureSource::Object(sign_obj_link) = sign.sign_source() {
216 if sign_obj_link.obj_id == id {
217 let verifier = RsaCPUObjectVerifier::new(public_key.clone());
218 let verify_ret =
219 async_std::task::block_on(verifier.verify(hash.as_slice(), sign));
220 if verify_ret {
221 verify = verify_ret;
222 break;
223 }
224 }
225 }
226 }
227 if !verify {
228 return Ok(false);
229 }
230 }
231 Ok(true)
232 }
233}
234
235#[derive(Clone, Debug, RawEncode, RawDecode)]
236pub struct WithdrawToOwner {
237 pub ctid: CoinTokenId,
238 pub id: ObjectId,
239 pub value: i64,
240}
241
242#[derive(Clone, Debug, RawEncode, RawDecode)]
244pub struct WithdrawFromUnionTx {
245 pub ctid: CoinTokenId,
246 pub union: ObjectId,
247 pub value: i64,
248}
249
250#[derive(Clone, Debug, RawEncode, RawDecode)]
251pub struct Data {
252 pub id: ObjectId,
253 pub data: Vec<u8>,
254}
255
256#[derive(Clone, Debug, RawEncode, RawDecode)]
316pub enum SavedMetaObject {
317 Device(Device), People(People), UnionAccount(UnionAccount), Group(SimpleGroup), File(File),
322 Data(Data),
323 Org(Org),
324 MinerGroup(MinerGroup),
325 SNService(SNService),
326 Contract(Contract),
327}
328
329impl SavedMetaObject {
330 pub fn hash(&self) -> BuckyResult<HashValue> {
331 let data = self.to_vec()?;
332 let mut hasher = Sha256::new();
333 hasher.input(data);
334 Ok(HashValue::from(hasher.result()))
335 }
336
337 pub fn id(&self) -> ObjectId {
338 match self {
339 SavedMetaObject::Device(o) => {o.desc().calculate_id()}
340 SavedMetaObject::People(o) => {o.desc().calculate_id()}
341 SavedMetaObject::UnionAccount(o) => {o.desc().calculate_id()}
342 SavedMetaObject::Group(o) => {o.desc().calculate_id()}
343 SavedMetaObject::File(o) => {o.desc().calculate_id()}
344 SavedMetaObject::Data(o) => {o.id.clone()}
345 SavedMetaObject::Org(o) => {o.desc().calculate_id()}
346 SavedMetaObject::MinerGroup(o) => {o.desc().calculate_id()}
347 SavedMetaObject::SNService(o) => {o.desc().calculate_id()}
348 SavedMetaObject::Contract(o) => {o.desc().calculate_id()}
349 }
350 }
351}
352
353impl TryFrom<SavedMetaObject> for AnyNamedObject {
354 type Error = BuckyError;
355
356 fn try_from(value: SavedMetaObject) -> Result<Self, Self::Error> {
357 match value {
358 SavedMetaObject::Data(v) => Ok(AnyNamedObject::clone_from_slice(&v.data)?),
359 SavedMetaObject::MinerGroup(v) => Ok(AnyNamedObject::clone_from_slice(&v.to_vec()?)?),
360 SavedMetaObject::SNService(v) => Ok(AnyNamedObject::clone_from_slice(&v.to_vec()?)?),
361 v @ _ => Ok(AnyNamedObject::Standard(StandardObject::try_from(v)?)),
362 }
363 }
364}
365
366impl TryFrom<SavedMetaObject> for StandardObject {
367 type Error = BuckyError;
368 fn try_from(object: SavedMetaObject) -> Result<Self, Self::Error> {
369 match object {
370 SavedMetaObject::Device(v) => Ok(Self::Device(v)),
371 SavedMetaObject::People(v) => Ok(Self::People(v)),
372 SavedMetaObject::UnionAccount(v) => Ok(Self::UnionAccount(v)),
373 SavedMetaObject::Group(v) => Ok(Self::SimpleGroup(v)),
374 SavedMetaObject::File(v) => Ok(Self::File(v)),
375 SavedMetaObject::Org(v) => Ok(Self::Org(v)),
376 SavedMetaObject::Contract(v) => Ok(Self::Contract(v)),
377 _ => Err(BuckyError::from(BuckyErrorCode::NotSupport)),
378 }
379 }
380}
381
382impl TryFrom<StandardObject> for SavedMetaObject {
383 type Error = BuckyError;
384
385 fn try_from(object: StandardObject) -> Result<Self, Self::Error> {
386 let ret = match object {
387 StandardObject::Device(v) => Self::Device(v),
388 StandardObject::People(v) => Self::People(v),
389 StandardObject::UnionAccount(v) => Self::UnionAccount(v),
390 StandardObject::SimpleGroup(v) => SavedMetaObject::Group(v),
391 StandardObject::File(v) => Self::File(v),
392 StandardObject::Org(v) => Self::Org(v),
393 StandardObject::Contract(v) => Self::Contract(v),
394 _ => {
395 return Err(BuckyError::from(BuckyErrorCode::NotSupport));
396 }
397 };
398
399 Ok(ret)
400 }
401}
402
403#[derive(Clone, Debug, RawEncode, RawDecode)]
408pub struct CreateDescTx {
409 pub coin_id: u8,
410 pub from: Option<ObjectId>, pub value: i64,
413 pub desc_hash: HashValue,
414 pub price: u32, }
416
417#[derive(Clone, Debug, RawEncode, RawDecode)]
418pub struct MetaPrice {
419 pub coin_id: u8,
420 pub price: u32,
421}
422
423#[derive(Clone, Debug, RawEncode, RawDecode)]
424pub struct UpdateDescTx {
425 pub write_flag: u8, pub price: Option<MetaPrice>,
428 pub desc_hash: HashValue,
429}
430
431#[derive(Clone, Debug, RawEncode, RawDecode)]
432pub struct RemoveDescTx {
433 pub id: ObjectId,
434}
435
436#[derive(Clone, Debug, RawEncode, RawDecode)]
440pub struct BidNameTx {
441 pub name: String,
442 pub owner: Option<ObjectId>, pub name_price: u64, pub price: u32, }
446
447#[derive(Clone, Debug, RawEncode, RawDecode)]
448pub struct UpdateNameTx {
449 pub name: String,
450 pub info: NameInfo,
451 pub write_flag: u8,
452}
453
454#[derive(Clone, Debug, RawEncode, RawDecode)]
455pub struct AuctionNameTx {
456 pub name: String,
457 pub price: u64, }
459
460#[derive(Clone, Debug, RawEncode, RawDecode)]
461pub struct CancelAuctionNameTx {
462 pub name: String,
463}
464
465#[derive(Clone, Debug, RawEncode, RawDecode)]
466pub struct BuyBackNameTx {
467 pub name: String,
468}
469
470#[derive(Clone, Debug, RawEncode, RawDecode)]
472pub struct TransNameTx {
473 pub sub_name: Option<String>,
474 pub new_owner: ObjectId,
475}
476
477#[derive(Clone, Debug, RawEncode, RawDecode)]
479pub struct InstanceContractTx {
480 pub contract_id: ObjectId,
481 pub template_parms: Vec<u8>,
482}
483
484#[derive(Clone, Debug, RawEncode, RawDecode)]
485pub struct ContractTx {
486 pub instance_id: ObjectId, pub func_name: String,
488 pub parm_body: Vec<u8>,
489}
490
491#[derive(Clone, Debug, RawEncode, RawDecode)]
492pub enum TxLog {
493 ContractLog(ContractLog),
494 ExtensionTx(Vec<u8>),
495}
496
497#[derive(Clone, Debug, RawEncode, RawDecode)]
498pub struct ContractLog {
499 pub address: ObjectId,
500 pub topics: Vec<GenericArray<u8, U32>>,
501 pub data: Vec<u8>,
502}
503
504impl From<crate::evm_def::Log> for TxLog {
505 fn from(log: crate::evm_def::Log) -> Self {
506 TxLog::ContractLog(ContractLog {
507 address: log.address,
508 topics: log
509 .topics
510 .iter()
511 .map(|topic| GenericArray::clone_from_slice(topic.as_bytes()))
512 .collect(),
513 data: log.data,
514 })
515 }
516}
517
518#[derive(Clone, Debug, RawEncode, RawDecode)]
519pub struct ReceiptV1 {
520 pub result: u32,
521 pub fee_used: u32,
522}
523
524#[derive(Clone, Debug, RawEncode, RawDecode)]
525pub struct ReceiptV2 {
526 pub result: u32,
527 pub fee_used: u32,
528 pub logs: Vec<TxLog>,
529}
530
531#[derive(Clone, Debug, RawEncode, RawDecode)]
532pub struct Receipt {
533 pub result: u32,
534 pub fee_used: u32,
535 pub logs: Vec<TxLog>,
536 pub address: Option<ObjectId>,
537 pub return_value: Option<Vec<u8>>,
538}
539
540impl From<&ReceiptV1> for Receipt {
541 fn from(r: &ReceiptV1) -> Self {
542 Self {
543 result: r.result,
544 fee_used: r.fee_used,
545 logs: vec![],
546 address: None,
547 return_value: None,
548 }
549 }
550}
551
552impl From<ReceiptV1> for Receipt {
553 fn from(r: ReceiptV1) -> Self {
554 (&r).into()
555 }
556}
557
558impl From<&ReceiptV2> for Receipt {
559 fn from(r: &ReceiptV2) -> Self {
560 Self {
561 result: r.result,
562 fee_used: r.fee_used,
563 logs: r.logs.clone(),
564 address: None,
565 return_value: None,
566 }
567 }
568}
569
570impl Receipt {
571 pub fn new(result: u32, fee_used: u32) -> Self {
572 Self {
573 result,
574 fee_used,
575 logs: vec![],
576 address: None,
577 return_value: None,
578 }
579 }
580}
581
582#[derive(Clone, Debug, RawEncode, RawDecode)]
583pub struct SetConfigTx {
584 pub key: String,
585 pub value: String,
586}
587
588#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize, RawEncode, RawDecode)]
589#[allow(non_snake_case)]
590pub struct BTCTxRecord {
591 pub txid: String,
592 pub blockHash: String,
593 pub blockNumber: u64,
594 pub confirmed: u64,
595 pub received: u64,
596 pub exodusAddress: String,
597 pub btcValue: u64,
598 pub version: u32,
599 pub propertyID: u32,
600 pub op: u32,
601 pub address: String,
602}
603
604#[derive(Clone, Debug, RawEncode, RawDecode)]
605pub struct BTCCoinageRecordTx {
606 pub height: u64,
607 pub list: Vec<BTCTxRecord>,
608}
609
610#[derive(Clone, Debug, RawEncode, RawDecode)]
611pub struct MinerGroupDescContent {}
612
613impl DescContent for MinerGroupDescContent {
614 fn obj_type() -> u16 {
615 CoreObjectType::MetaMinerGroup as u16
616 }
617
618 type OwnerType = SubDescNone;
619 type AreaType = SubDescNone;
620 type AuthorType = SubDescNone;
621 type PublicKeyType = SubDescNone;
622}
623
624#[derive(Clone, Debug, RawEncode, RawDecode)]
625pub struct MinerGroupBodyContent {
626 pub members: Vec<DeviceDesc>,
627}
628
629impl BodyContent for MinerGroupBodyContent {}
630
631pub type MinerGroupType = NamedObjType<MinerGroupDescContent, MinerGroupBodyContent>;
632pub type MinerGroupBuilder = NamedObjectBuilder<MinerGroupDescContent, MinerGroupBodyContent>;
633pub type MinerGroup = NamedObjectBase<MinerGroupType>;
634
635pub trait MinerGroupTrait {
636 fn new(members: Vec<DeviceDesc>) -> MinerGroupBuilder;
637 fn members(&self) -> &Vec<DeviceDesc>;
638 fn members_mut(&mut self) -> &mut Vec<DeviceDesc>;
639 fn has_member(&self, id: &ObjectId) -> bool;
640}
641
642impl MinerGroupTrait for NamedObjectBase<MinerGroupType> {
643 fn new(members: Vec<DeviceDesc>) -> MinerGroupBuilder {
644 let desc = MinerGroupDescContent {};
645 let body = MinerGroupBodyContent { members };
646
647 MinerGroupBuilder::new(desc, body)
648 }
649
650 fn members(&self) -> &Vec<DeviceDesc> {
651 &self.body().as_ref().unwrap().content().members
652 }
653
654 fn members_mut(&mut self) -> &mut Vec<DeviceDesc> {
655 &mut self.body_mut().as_mut().unwrap().content_mut().members
656 }
657
658 fn has_member(&self, id: &ObjectId) -> bool {
659 let members = &self.body().as_ref().unwrap().content().members;
660 for member in members {
661 if &member.calculate_id() == id {
662 return true;
663 }
664 }
665 return false;
666 }
667}
668
669#[derive(Clone, Debug, RawEncode, RawDecode)]
670pub struct MinerDesc {}
671
672#[derive(Clone, Debug, RawEncode, RawDecode)]
673pub struct SubChainWithdrawTx {
674 pub subchain_id: ObjectId,
675 pub withdraw_tx: Vec<u8>,
676}
677
678#[derive(Clone, Debug, RawEncode, RawDecode)]
679pub struct WithdrawFromSubChainTx {
680 pub coin_id: CoinTokenId,
681 pub value: i64,
682}
683
684#[derive(Clone, Debug, RawEncode, RawDecode)]
685pub struct SubChainCoinageRecordTx {
686 pub height: i64,
687 pub list: Vec<SPVTx>,
688}
689
690#[derive(Clone, Debug, RawEncode, RawDecode)]
691pub struct FlowServiceDescContent {}
692
693impl DescContent for FlowServiceDescContent {
694 fn obj_type() -> u16 {
695 0_u16
696 }
697
698 type OwnerType = Option<ObjectId>;
699 type AreaType = SubDescNone;
700 type AuthorType = SubDescNone;
701 type PublicKeyType = SubDescNone;
702}
703
704#[derive(Clone, Debug, RawEncode, RawDecode)]
705pub struct FlowServiceBodyContent {
706 price: i64,
707}
708
709impl BodyContent for FlowServiceBodyContent {}
710
711pub type FlowServiceType = NamedObjType<FlowServiceDescContent, FlowServiceBodyContent>;
712pub type FlowServiceBuilder = NamedObjectBuilder<FlowServiceDescContent, FlowServiceBodyContent>;
713pub type FlowService = NamedObjectBase<FlowServiceType>;
714
715#[derive(Clone, Debug, RawEncode, RawDecode)]
716pub enum FlowServiceTx {
717 Create(FlowService),
718 Purchase(u32),
719 Settle,
720}
721
722#[derive(Clone, Debug, RawEncode, RawDecode)]
723pub enum SNServiceTx {
724 Publish(SNService),
725 Remove(ObjectId),
726 Purchase(Contract),
727 Settle(ProofOfService),
728}
729
730pub type MetaTxDescContent = TxDescContent<TypeBuffer<Vec<MetaTxBody>>>;
731
732pub type MetaTxDesc = NamedObjectDesc<MetaTxDescContent>;
733pub type MetaTxType = NamedObjType<MetaTxDescContent, TxBodyContent>;
734pub type MetaTxId = NamedObjectId<MetaTxType>;
735pub type MetaTx = NamedObjectBase<MetaTxType>;
736pub type MetaTxBuilder = NamedObjectBuilder<MetaTxDescContent, TxBodyContent>;
737
738pub trait MetaTxDescTrait {
739 fn tx_id(&self) -> TxId;
740}
741
742impl MetaTxDescTrait for NamedObjectDesc<MetaTxDescContent> {
743 fn tx_id(&self) -> TxId {
744 TxId::try_from(self.calculate_id()).unwrap()
745 }
746}
747
748#[async_trait]
749pub trait MetaTxTrait {
750 fn new(
751 nonce: i64,
752 caller: TxCaller,
753 gas_coin_id: u8,
754 gas_price: u16,
755 max_fee: u32,
756 condition: Option<TxCondition>,
757 body: MetaTxBody,
758 data: Vec<u8>,
759 ) -> MetaTxBuilder;
760 fn new_multi_body(
761 nonce: i64,
762 caller: TxCaller,
763 gas_coin_id: u8,
764 gas_price: u16,
765 max_fee: u32,
766 condition: Option<TxCondition>,
767 bodys: Vec<MetaTxBody>,
768 data: Vec<u8>,
769 ) -> MetaTxBuilder;
770 fn verify_signature(&self, public_key: PublicKey) -> BuckyResult<bool>;
771 async fn async_verify_signature(&self, public_key: PublicKey) -> BuckyResult<bool>;
772 fn sign(&mut self, secret: PrivateKey) -> BuckyResult<()>;
773 async fn async_sign(&mut self, secret: PrivateKey) -> BuckyResult<()>;
774}
775#[async_trait]
781impl MetaTxTrait for NamedObjectBase<MetaTxType> {
782 fn new(
783 nonce: i64,
784 caller: TxCaller,
785 gas_coin_id: u8,
786 gas_price: u16,
787 max_fee: u32,
788 condition: Option<TxCondition>,
789 body: MetaTxBody,
790 data: Vec<u8>,
791 ) -> MetaTxBuilder {
792 let desc_content = MetaTxDescContent {
793 nonce,
794 caller,
795 gas_coin_id,
796 gas_price,
797 max_fee,
798 condition,
799 body: TypeBuffer::from(vec![body]),
800 };
801
802 let body_content = TxBodyContent::new(data);
803
804 MetaTxBuilder::new(desc_content, body_content)
805 }
806
807 fn new_multi_body(
808 nonce: i64,
809 caller: TxCaller,
810 gas_coin_id: u8,
811 gas_price: u16,
812 max_fee: u32,
813 condition: Option<TxCondition>,
814 bodys: Vec<MetaTxBody>,
815 data: Vec<u8>,
816 ) -> MetaTxBuilder {
817 let desc_content = MetaTxDescContent {
818 nonce,
819 caller,
820 gas_coin_id,
821 gas_price,
822 max_fee,
823 condition,
824 body: TypeBuffer::from(bodys),
825 };
826
827 let body_content = TxBodyContent::new(data);
828
829 MetaTxBuilder::new(desc_content, body_content)
830 }
831
832 fn verify_signature(&self, public_key: PublicKey) -> BuckyResult<bool> {
833 if self.desc().content().caller.is_miner() {
834 return Ok(true);
835 }
836 let desc_signs = self.signs().desc_signs();
837 if desc_signs.is_none() {
838 return Ok(false);
839 }
840
841 let signs = desc_signs.as_ref().unwrap();
842 if signs.len() == 0 {
843 return Ok(false);
844 }
845
846 let sign = signs.get(0).unwrap();
847 let verifier = RsaCPUObjectVerifier::new(public_key);
848
849 async_std::task::block_on(verify_object_desc_sign(&verifier, self, sign))
850 }
851
852 async fn async_verify_signature(&self, public_key: PublicKey) -> BuckyResult<bool> {
853 if self.desc().content().caller.is_miner() {
854 return Ok(true);
855 }
856 if self.desc().content().caller.is_fake() {
857 return Ok(true);
858 }
859 let desc_signs = self.signs().desc_signs();
860 if desc_signs.is_none() {
861 return Ok(false);
862 }
863
864 let signs = desc_signs.as_ref().unwrap();
865 if signs.len() == 0 {
866 return Ok(false);
867 }
868
869 let sign = signs.get(0).unwrap();
870 let verifier = RsaCPUObjectVerifier::new(public_key);
871 verify_object_desc_sign(&verifier, self, sign).await
872 }
873
874 fn sign(&mut self, secret: PrivateKey) -> BuckyResult<()> {
875 let signer = RsaCPUObjectSigner::new(secret.public(), secret);
876 async_std::task::block_on(sign_and_set_named_object(
877 &signer,
878 self,
879 &SignatureSource::RefIndex(0),
880 ))
881 }
882
883 async fn async_sign(&mut self, secret: PrivateKey) -> BuckyResult<()> {
884 let signer = RsaCPUObjectSigner::new(secret.public(), secret);
885 sign_and_set_named_object(&signer, self, &SignatureSource::RefIndex(0)).await
886 }
887}
888
889#[cfg(test)]
890mod tx_test {
891 use crate::*;
892 use cyfs_base::*;
893
894 #[test]
895 fn test() {
896 let body = TransBalanceTx {
897 ctid: CoinTokenId::Coin(0),
898 to: vec![(ObjectId::default(), 2), (ObjectId::default(), 3)],
899 };
900
901 let meta_tx = MetaTx::new(
902 1,
903 TxCaller::Miner(ObjectId::default()),
904 0,
905 0,
906 0,
907 None,
908 MetaTxBody::TransBalance(body),
909 Vec::new(),
910 )
911 .build();
912
913 let ret = meta_tx.to_vec();
914 assert!(ret.is_ok());
915
916 let ret = Tx::clone_from_slice(ret.unwrap().as_slice());
917 assert!(ret.is_ok());
918
919 let ret = ret.unwrap().to_vec();
920 assert!(ret.is_ok());
921
922 let ret = MetaTx::clone_from_slice(ret.unwrap().as_slice());
923 assert!(ret.is_ok());
924
925 let meta_tx = ret.unwrap();
926 let body = meta_tx.desc().content().body.get_obj().get(0).unwrap();
927 if let MetaTxBody::TransBalance(trans_tx) = body {
928 assert_eq!(trans_tx.to.len(), 2);
929 assert_eq!(trans_tx.to.get(0).unwrap().1, 2);
930 assert_eq!(trans_tx.to.get(1).unwrap().1, 3);
931 } else {
932 assert!(false);
933 }
934 }
935
936 const OLD_LIST: &'static [&'static str] = &[
937 "010002500e0000000000010030818902818100e0252144cac6aa8493f252c1c7d288afd9d01f04430a24f19bbd1f0fec428278b149f3b748e26a532c7e238dcdde6fb60d3820727f53b7ae090ce1bb04f637d43aea4551043a06535ded73e6a7de845e6a6187cfcd4def56b841fd098afc0671f659bfbabd1fbceb268b6fa0f47b8c7e3cb698a2d6ba120e54b6df9064c889ed0203010001000000000000000000000000000000000000000000000000000000002f3b2f6e3acd9000013f0a2045c40d30000cd65e863aa69f59d818f2090e3fa3b3d646dadc87568f773da50c120fe7bab3e696afe8b59be58d9ae4bcaf220a7374616e64616c6f6e650100ff002f3b2f6e3ad56000c661eeddb115b2b1cc8f6a0abe871b83c3108379c766303457676e1beca4836220767e72cac8fa53b3addff7686a604ee5537b4593d7ef363dcfd827dace32a51fb46c527330d6cb1a2bf37a4fcc4d6bae9ed5acf0289c7f6fa3e957c4a11362bf237746a253edd574c59acf85705d36747dd83ac65acd0995c201e76be7db5f0100ff002f3b2f6e3e09b000bb6a8d783a3be84580323e7e70b7aeb0c277c60c09705218fe77eb5a527df5cfdfe738d05c0661c9e06f59c883d7b314d4709d56675cecdde81bbb72dc692c5413c9a39f81aaf7fd928319f7bd4183132ab3c383b6e39a924a87ba1608133cbd2a6bdfeb2e613752971d24c944ed666ed5d50c9a77177ab4077143c5354f90c2",
938 ];
939
940 #[test]
941 fn test_people_codec() {
942
943 for code in OLD_LIST {
944 let code = hex::decode(code).unwrap();
945 let ret = SavedMetaObject::clone_from_slice(code.as_slice()).unwrap();
946
947 let hash = ret.hash().unwrap();
948 println!("desc hash: {}", hash);
949 }
950 }
951}