bucky_objects/objects/
tx.rs

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