cyfs_base_meta/
tx.rs

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), //0x12 设置
17    WithdrawFromUnion(WithdrawFromUnionTx),
18    CreateDesc(CreateDescTx), //0x11 转账并创建帐号
19    UpdateDesc(UpdateDescTx), //0x20
20    RemoveDesc(RemoveDescTx), //0x21
21    BidName(BidNameTx),       //0x30
22    UpdateName(UpdateNameTx),
23    TransName(TransNameTx),
24    Contract(ContractTx), //0x70
25    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    // evm相关Tx
41    CreateContract(CreateContractTx),
42    CreateContract2(CreateContract2Tx),
43    CallContract(CallContractTx),
44
45    // 设置受益人
46    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 from: Option<ObjectId>,//from和caller可以不是同一个人
68    pub to: Vec<(ObjectId, i64)>, //必须是u64,不允许from==to?,该调用完成后可能会产生no desc account.
69}
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, // 左边账户的改变值,左右的改变值一定是数值相等,符号相反的
84    pub union: ObjectId,
85}
86
87// union_account是ffs-meta-chain 对闪电网络的的特化实现
88#[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// union_account是ffs-meta-chain 对闪电网络的的特化实现
243#[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// impl RawEncode for Data {
257//     fn raw_measure(&self, purpose: &Option<RawEncodePurpose>) -> BuckyResult<usize> {
258//         Ok(u16::raw_bytes().unwrap() + self.data.len() + self.id.raw_measure(purpose).map_err(|e|{
259//             log::error!("TxData::raw_measure/id error:{}", e);
260//             e
261//         })?)
262//     }
263//
264//     fn raw_encode<'a>(&self, buf: &'a mut [u8], _purpose: &Option<RawEncodePurpose>) -> BuckyResult<&'a mut [u8]> {
265//         if self.data.len() > u16::MAX as usize{
266//             return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, format!("raw encode able vector length more than {}", u16::MAX)));
267//         }
268//
269//         let buf = self.id.raw_encode(buf, None).map_err(|e|{
270//             log::error!("TxData::raw_encode/id error:{}", e);
271//             e
272//         })?;
273//
274//         let buf = (self.data.len() as u16).raw_encode(buf, &None).map_err(|e|{
275//             log::error!("TxData::raw_encode/data len error:{}", e);
276//             e
277//         })?;
278//
279//         if buf.len() < self.data.len() {
280//             return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, "not enough buffer"));
281//         }
282//
283//         buf[0..self.data.len()].copy_from_slice(self.data.as_slice());
284//
285//         // buf.copy_from_slice(self.data.as_slice());
286//
287//         Ok(&mut buf[self.data.len()..])
288//     }
289// }
290//
291// impl<'de> RawDecode<'de> for Data {
292//     fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> {
293//         let (id, buf) = ObjectId::raw_decode(buf).map_err(|e|{
294//             log::error!("TxData::raw_decode/id error:{}", e);
295//             e
296//         })?;
297//
298//         let (len, buf) = u16::raw_decode(buf).map_err(|e|{
299//             log::error!("TxData::raw_decode/data len error:{}", e);
300//             e
301//         })?;
302//
303//         if buf.len() < len as usize {
304//             return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, "not enough buffer"));
305//         }
306//         let data = &buf[..len as usize];
307//
308//         Ok((Data {
309//             id,
310//             data: Vec::from(data),
311//         }, &buf[(len as usize)..]))
312//     }
313// }
314
315#[derive(Clone, Debug, RawEncode, RawDecode)]
316pub enum SavedMetaObject {
317    Device(Device),             //BDT中定义
318    People(People),             //BDT中定义
319    UnionAccount(UnionAccount), //两人公有账号,用于闪电网络
320    Group(SimpleGroup),         //M*N Group,最常见的Group BDT中定义
321    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//租用Meta-Chain的空间来创建对象,操作已创建对象不需要再在Tx中带Desc
404//有一些Object的操作,会强制要求对象先创建。
405//租用需要持续扣费,这些扣费操作需要作为类似CoinBase的操作保留在区块里么?
406//TODO:考虑租用系统如何实现
407#[derive(Clone, Debug, RawEncode, RawDecode)]
408pub struct CreateDescTx {
409    pub coin_id: u8,
410    pub from: Option<ObjectId>, //from和op可以不是同一个人
411    //pub to: ObjectId,//TODO:可以从desc中算出来,不用带
412    pub value: i64,
413    pub desc_hash: HashValue,
414    pub price: u32, //租金,租金太低可能不会被meta-chain接受
415}
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 id : ObjectId,//TODO:可以从desc中算出来
426    pub write_flag: u8, //为了减少手续费,可以指定更新方式
427    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//名字体系是ffs-meta的核心功能,目的是取代dns
437//买了一级的名字,那么在2级名字没有出售的情况下,可以在DescBody中定义2级名字而不需要购买(类似DNS)
438//名字的价格体系和Id不完全相同,但其核心依旧是租用系统
439#[derive(Clone, Debug, RawEncode, RawDecode)]
440pub struct BidNameTx {
441    pub name: String,
442    pub owner: Option<ObjectId>, //opid可以和owner不同
443    pub name_price: u64,         //name的购买价格,coin_id有meta指定
444    pub price: u32,              //租金,coin_id meta指定
445}
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, //起始拍卖价
458}
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//TODO: 下面两个先不做 通过该TX可以创建2级域名
471#[derive(Clone, Debug, RawEncode, RawDecode)]
472pub struct TransNameTx {
473    pub sub_name: Option<String>,
474    pub new_owner: ObjectId,
475}
476
477//---------- 合约的先不做 ---------
478#[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, //instance id
487    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/// 交易对象
776/// ====
777/// new 传入 TxBody,注意 TxBody不是 Tx.body(),这个地方的命名有点冲突
778/// new_multi_body 传入 Vec<TxBody>
779///
780#[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}