cfx_rpc_cfx_types/pos/
transaction.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use cfx_types::{H256, U64};
6use diem_types::{
7    transaction::{ConflictSignature, TransactionPayload, TransactionStatus},
8    vm_status::KeptVMStatus,
9};
10use rustc_hex::ToHex;
11use serde::{ser::SerializeStruct, Serialize, Serializer};
12
13#[derive(Debug, Clone)]
14pub struct Transaction {
15    pub hash: H256,
16    pub from: H256,
17    pub block_hash: Option<H256>,
18    pub block_number: Option<U64>,
19    pub timestamp: Option<U64>,
20    pub number: U64,
21    pub payload: Option<RpcTransactionPayload>,
22    pub status: Option<RpcTransactionStatus>,
23    pub tx_type: RpcTransactionType,
24}
25
26#[derive(Debug, Serialize, Clone, Copy)]
27pub enum RpcTransactionStatus {
28    Executed,
29    Failed,
30    Discard,
31}
32
33#[derive(Debug, Serialize, Clone, Copy)]
34pub enum RpcTransactionType {
35    BlockMetadata,
36    Election,
37    Retire,
38    Register,
39    UpdateVotingPower,
40    PivotDecision,
41    Dispute,
42    Other,
43}
44
45#[derive(Debug, Clone)]
46pub enum RpcTransactionPayload {
47    ///
48    Register(RegisterPayload),
49    ///
50    Election(ElectionPayload),
51    ///
52    UpdateVotingPower(UpdateVotingPowerPayload),
53    ///
54    PivotDecision(PivotDecisionPayload),
55    ///
56    Retire(RetirePayload),
57    ///
58    Dispute(DisputePayload),
59    ///
60    Other,
61}
62
63impl From<TransactionPayload> for RpcTransactionPayload {
64    fn from(payload: TransactionPayload) -> Self {
65        match payload {
66            TransactionPayload::Election(e) => {
67                RpcTransactionPayload::Election(ElectionPayload {
68                    public_key: format!("0x{}", e.public_key),
69                    target_term: U64::from(e.target_term),
70                    vrf_proof: format!("0x{}", e.vrf_proof),
71                    vrf_public_key: format!("0x{}", e.vrf_public_key),
72                })
73            }
74            TransactionPayload::Retire(r) => {
75                RpcTransactionPayload::Retire(RetirePayload {
76                    address: H256::from(r.node_id.to_u8()),
77                    voting_power: U64::from(r.votes),
78                })
79            }
80            TransactionPayload::Register(r) => {
81                RpcTransactionPayload::Register(RegisterPayload {
82                    vrf_public_key: format!("0x{}", r.vrf_public_key),
83                    public_key: format!("0x{}", r.public_key),
84                })
85            }
86            TransactionPayload::UpdateVotingPower(u) => {
87                RpcTransactionPayload::UpdateVotingPower(
88                    UpdateVotingPowerPayload {
89                        address: H256::from(u.node_address.to_u8()),
90                        voting_power: U64::from(u.voting_power),
91                    },
92                )
93            }
94            TransactionPayload::PivotDecision(p) => {
95                RpcTransactionPayload::PivotDecision(PivotDecisionPayload {
96                    height: U64::from(p.height),
97                    block_hash: H256::from(p.block_hash),
98                })
99            }
100            TransactionPayload::Dispute(d) => {
101                let conflicting_votes = match d.conflicting_votes {
102                    ConflictSignature::Proposal((first, second)) => {
103                        ConflictingVotes {
104                            conflict_vote_type: "proposal".into(),
105                            first: format!("0x{}", first.to_hex::<String>()),
106                            second: format!("0x{}", second.to_hex::<String>()),
107                        }
108                    }
109                    ConflictSignature::Vote((first, second)) => {
110                        ConflictingVotes {
111                            conflict_vote_type: "vote".into(),
112                            first: format!("0x{}", first.to_hex::<String>()),
113                            second: format!("0x{}", second.to_hex::<String>()),
114                        }
115                    }
116                };
117                RpcTransactionPayload::Dispute(DisputePayload {
118                    address: H256::from(d.address.to_u8()),
119                    bls_public_key: format!("0x{}", d.bls_pub_key),
120                    vrf_public_key: format!("0x{}", d.vrf_pub_key),
121                    conflicting_votes,
122                })
123            }
124            _ => RpcTransactionPayload::Other,
125        }
126    }
127}
128
129#[derive(Debug, Serialize, Clone)]
130#[serde(rename_all = "camelCase")]
131pub struct RegisterPayload {
132    pub vrf_public_key: String,
133    pub public_key: String,
134}
135
136#[derive(Debug, Serialize, Clone)]
137#[serde(rename_all = "camelCase")]
138pub struct ElectionPayload {
139    pub public_key: String,
140    pub target_term: U64,
141    pub vrf_proof: String,
142    pub vrf_public_key: String,
143}
144
145#[derive(Debug, Serialize, Clone)]
146#[serde(rename_all = "camelCase")]
147pub struct UpdateVotingPowerPayload {
148    pub address: H256,
149    pub voting_power: U64,
150}
151
152#[derive(Debug, Serialize, Clone)]
153#[serde(rename_all = "camelCase")]
154pub struct PivotDecisionPayload {
155    pub height: U64,
156    pub block_hash: H256,
157}
158
159#[derive(Debug, Serialize, Clone)]
160#[serde(rename_all = "camelCase")]
161pub struct RetirePayload {
162    pub address: H256,
163    pub voting_power: U64,
164}
165
166#[derive(Debug, Serialize, Clone)]
167#[serde(rename_all = "camelCase")]
168pub struct DisputePayload {
169    pub address: H256,
170    pub bls_public_key: String,
171    pub vrf_public_key: String,
172    pub conflicting_votes: ConflictingVotes,
173}
174
175#[derive(Debug, Serialize, Clone)]
176#[serde(rename_all = "camelCase")]
177pub struct ConflictingVotes {
178    pub conflict_vote_type: String,
179    pub first: String,
180    pub second: String,
181}
182
183impl Serialize for Transaction {
184    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185    where S: Serializer {
186        let mut struc = serializer.serialize_struct("Transaction", 9)?;
187        struc.serialize_field("hash", &self.hash)?;
188        struc.serialize_field("from", &self.from)?;
189        struc.serialize_field("number", &self.number)?;
190        struc.serialize_field("blockHash", &self.block_hash)?;
191        struc.serialize_field("blockNumber", &self.block_number)?;
192        struc.serialize_field("timestamp", &self.timestamp)?;
193        struc.serialize_field("status", &self.status)?;
194        struc.serialize_field("type", &self.tx_type)?;
195        if self.payload.is_some() {
196            match &self.payload.as_ref().unwrap() {
197                RpcTransactionPayload::Election(e) => {
198                    struc.serialize_field("payload", e)?;
199                }
200                RpcTransactionPayload::Retire(r) => {
201                    struc.serialize_field("payload", r)?;
202                }
203                RpcTransactionPayload::Register(r) => {
204                    struc.serialize_field("payload", r)?;
205                }
206                RpcTransactionPayload::UpdateVotingPower(u) => {
207                    struc.serialize_field("payload", u)?;
208                }
209                RpcTransactionPayload::PivotDecision(p) => {
210                    struc.serialize_field("payload", p)?;
211                }
212                RpcTransactionPayload::Dispute(d) => {
213                    struc.serialize_field("payload", d)?;
214                }
215                _ => {}
216            }
217        } else {
218            let empty: Option<TransactionPayload> = None;
219            struc.serialize_field("payload", &empty)?
220        }
221        struc.end()
222    }
223}
224
225pub fn tx_type(payload: TransactionPayload) -> RpcTransactionType {
226    match payload {
227        TransactionPayload::Election(_) => RpcTransactionType::Election,
228        TransactionPayload::Retire(_) => RpcTransactionType::Retire,
229        TransactionPayload::Register(_) => RpcTransactionType::Register,
230        TransactionPayload::UpdateVotingPower(_) => {
231            RpcTransactionType::UpdateVotingPower
232        }
233        TransactionPayload::PivotDecision(_) => {
234            RpcTransactionType::PivotDecision
235        }
236        TransactionPayload::Dispute(_) => RpcTransactionType::Dispute,
237        _ => RpcTransactionType::Other,
238    }
239}
240
241impl From<TransactionStatus> for RpcTransactionStatus {
242    fn from(status: TransactionStatus) -> Self {
243        match status {
244            TransactionStatus::Discard(_) => RpcTransactionStatus::Discard,
245            TransactionStatus::Keep(keep_status) => match keep_status {
246                KeptVMStatus::Executed => RpcTransactionStatus::Executed,
247                _ => RpcTransactionStatus::Failed,
248            },
249            TransactionStatus::Retry => RpcTransactionStatus::Failed,
250        }
251    }
252}
253
254impl From<KeptVMStatus> for RpcTransactionStatus {
255    fn from(status: KeptVMStatus) -> Self {
256        match status {
257            KeptVMStatus::Executed => RpcTransactionStatus::Executed,
258            _ => RpcTransactionStatus::Failed,
259        }
260    }
261}