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 }
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, pub gas_price: u16, pub max_fee: u32,
114 pub condition: Option<TxCondition>, pub body: T,
116 }
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
148impl 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
190impl 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}