cyfs_base/objects/
tx.rs

1use crate::codec as cyfs_base;
2use crate::*;
3
4use serde::{Deserialize, Serialize};
5use std::convert::TryFrom;
6
7#[derive(Clone, Debug, RawEncode, RawDecode)]
8pub enum TxCondition {
9    //时间
10//BTC 交易确认
11}
12
13#[derive(Copy, Clone, Debug, Serialize, Deserialize, RawEncode, RawDecode, Eq, PartialEq)]
14pub enum CoinTokenId {
15    Coin(u8),
16    Token(ObjectId),
17}
18
19impl ProtobufTransform<CoinTokenId> for Vec<u8> {
20    fn transform(value: CoinTokenId) -> BuckyResult<Self> {
21        value.to_vec()
22    }
23}
24
25impl ProtobufTransform<&CoinTokenId> for Vec<u8> {
26    fn transform(value: &CoinTokenId) -> BuckyResult<Self> {
27        value.to_vec()
28    }
29}
30
31impl ProtobufTransform<Vec<u8>> for CoinTokenId {
32    fn transform(value: Vec<u8>) -> BuckyResult<Self> {
33        CoinTokenId::clone_from_slice(value.as_slice())
34    }
35}
36
37#[derive(Clone, Debug, RawEncode, RawDecode)]
38pub enum TxCaller {
39    People(PeopleDesc),
40    Device(DeviceDesc),
41    Group(SimpleGroupDesc),
42    Union(UnionAccountDesc),
43    Miner(ObjectId),
44    Id(ObjectId),
45}
46
47impl TryFrom<&StandardObject> for TxCaller {
48    type Error = BuckyError;
49    fn try_from(obj: &StandardObject) -> Result<Self, Self::Error> {
50        match obj {
51            StandardObject::People(desc) => Ok(Self::People(desc.desc().clone())),
52            StandardObject::Device(desc) => Ok(Self::Device(desc.desc().clone())),
53            StandardObject::SimpleGroup(desc) => Ok(Self::Group(desc.desc().clone())),
54            StandardObject::UnionAccount(desc) => Ok(Self::Union(desc.desc().clone())),
55            _ => Err(BuckyError::new(BuckyErrorCode::Failed, "Failed")),
56        }
57    }
58}
59
60impl TxCaller {
61    pub fn id(&self) -> BuckyResult<ObjectId> {
62        let id = match self {
63            Self::People(desc) => desc.calculate_id(),
64            Self::Device(desc) => desc.calculate_id(),
65            Self::Group(desc) => desc.calculate_id(),
66            Self::Union(desc) => desc.calculate_id(),
67            Self::Miner(id) => id.clone(),
68            Self::Id(id) => id.clone(),
69        };
70        Ok(id)
71    }
72
73    pub fn get_public_key(&self) -> BuckyResult<&PublicKey> {
74        match self {
75            Self::People(desc) => Ok(desc.public_key()),
76            Self::Device(desc) => Ok(desc.public_key()),
77            Self::Group(_desc) => Err(BuckyError::new(BuckyErrorCode::Failed, "Failed")),
78            Self::Union(_desc) => Err(BuckyError::new(BuckyErrorCode::Failed, "Failed")),
79            Self::Miner(_) => Err(BuckyError::new(BuckyErrorCode::Failed, "Failed")),
80            Self::Id(id) => {
81                if id.is_default() {
82                    Ok(&PublicKey::Invalid)
83                } else {
84                    Err(BuckyError::new(BuckyErrorCode::Failed, "Failed"))
85                }
86            },
87        }
88    }
89
90    pub fn is_miner(&self) -> bool {
91        match self {
92            Self::Miner(_) => true,
93            _ => false,
94        }
95    }
96
97    pub fn is_fake(&self) -> bool {
98        match self {
99            Self::Id(id) => {
100                id.is_default()
101            },
102            _ => false
103        }
104    }
105}
106
107#[derive(Clone, Debug, RawEncode, RawDecode)]
108pub struct TxDescContent<T> {
109    pub nonce: i64,
110    pub caller: TxCaller,
111    pub gas_coin_id: u8, //用哪种coin来支付手续费
112    pub gas_price: u16,  //
113    pub max_fee: u32,
114    pub condition: Option<TxCondition>, //Tx的生效条件,用于创建上链后不立刻生效的TX,
115    pub body: T,
116    // pub tx_body_buf: Vec<u8>,
117    // pub bodys: Vec<TxBody> //定义参考旧代码
118}
119
120impl<T> DescContent for TxDescContent<T> {
121    fn obj_type() -> u16 {
122        ObjectTypeCode::Tx.into()
123    }
124
125    type OwnerType = SubDescNone;
126    type AreaType = SubDescNone;
127    type AuthorType = SubDescNone;
128    type PublicKeyType = SubDescNone;
129}
130
131#[derive(Clone, Debug)]
132pub struct TxBodyContent {
133    pub data: Vec<u8>,
134}
135
136impl BodyContent for TxBodyContent {
137    fn format(&self) -> u8 {
138        OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF
139    }
140}
141
142impl TxBodyContent {
143    pub fn new(data: Vec<u8>) -> Self {
144        Self { data }
145    }
146}
147
148// body使用protobuf编解码
149impl TryFrom<protos::TxBodyContent> for TxBodyContent {
150    type Error = BuckyError;
151
152    fn try_from(mut value: protos::TxBodyContent) -> BuckyResult<Self> {
153        Ok(Self {
154            data: value.take_data(),
155        })
156    }
157}
158
159impl TryFrom<&TxBodyContent> for protos::TxBodyContent {
160    type Error = BuckyError;
161
162    fn try_from(value: &TxBodyContent) -> BuckyResult<Self> {
163        let mut ret = Self::new();
164
165        ret.set_data(value.data.to_owned());
166
167        Ok(ret)
168    }
169}
170
171crate::inner_impl_default_protobuf_raw_codec!(TxBodyContent);
172
173#[derive(Clone, Debug, RawEncode, RawDecode)]
174pub struct TxBody {
175    body: Vec<u8>,
176}
177
178pub type TxDesc = NamedObjectDesc<TxDescContent<TxBody>>;
179pub type TxType = NamedObjType<TxDescContent<TxBody>, TxBodyContent>;
180pub type TxId = NamedObjectId<TxType>;
181pub type Tx = NamedObjectBase<TxType>;
182pub type TxBuilder = NamedObjectBuilder<TxDescContent<TxBody>, TxBodyContent>;
183
184impl NamedObjectDesc<TxDescContent<Vec<u8>>> {
185    pub fn tx_id(&self) -> TxId {
186        TxId::try_from(self.calculate_id()).unwrap()
187    }
188}
189
190/// 交易对象
191/// ====
192/// new 传入 TxBody,注意 TxBody不是 Tx.body(),这个地方的命名有点冲突
193/// new_multi_body 传入 Vec<TxBody>
194///
195impl NamedObjectBase<TxType> {
196    pub fn new(
197        nonce: i64,
198        caller: TxCaller,
199        gas_coin_id: u8,
200        gas_price: u16,
201        max_fee: u32,
202        condition: Option<TxCondition>,
203        body: Vec<u8>,
204        data: Vec<u8>,
205    ) -> TxBuilder {
206        let desc_content = TxDescContent {
207            nonce,
208            caller,
209            gas_coin_id,
210            gas_price,
211            max_fee,
212            condition,
213            body: TxBody { body },
214        };
215
216        let body_content = TxBodyContent { data };
217
218        TxBuilder::new(desc_content, body_content)
219    }
220
221    pub fn verify_signature(&self, public_key: PublicKey) -> BuckyResult<bool> {
222        if self.desc().content().caller.is_miner() {
223            return Ok(true);
224        }
225        let desc_signs = self.signs().desc_signs();
226        if desc_signs.is_none() {
227            return Ok(false);
228        }
229
230        let signs = desc_signs.as_ref().unwrap();
231        if signs.len() == 0 {
232            return Ok(false);
233        }
234
235        let sign = signs.get(0).unwrap();
236        let verifier = RsaCPUObjectVerifier::new(public_key);
237
238        async_std::task::block_on(verify_object_desc_sign(&verifier, self, sign))
239    }
240
241    pub async fn async_verify_signature(&self, public_key: PublicKey) -> BuckyResult<bool> {
242        if self.desc().content().caller.is_miner() {
243            return Ok(true);
244        }
245        let desc_signs = self.signs().desc_signs();
246        if desc_signs.is_none() {
247            return Ok(false);
248        }
249
250        let signs = desc_signs.as_ref().unwrap();
251        if signs.len() == 0 {
252            return Ok(false);
253        }
254
255        let sign = signs.get(0).unwrap();
256        let verifier = RsaCPUObjectVerifier::new(public_key);
257        verify_object_desc_sign(&verifier, self, sign).await
258    }
259
260    pub fn sign(&mut self, secret: &PrivateKey) -> BuckyResult<()> {
261        let signer = RsaCPUObjectSigner::new(secret.public(), secret.clone());
262        async_std::task::block_on(sign_and_set_named_object(
263            &signer,
264            self,
265            &SignatureSource::RefIndex(0),
266        ))
267    }
268}