whisky_csl/tx_parser/
votes.rs1use whisky_common::{
2 Anchor, Credential, RefTxIn, ScriptSource, ScriptVote, SimpleScriptSource, SimpleScriptVote,
3 Vote, VoteKind, VoteType, Voter, VotingProcedure, WError,
4};
5
6use super::{
7 context::{ParserContext, RedeemerIndex, Script},
8 CSLParser,
9};
10use cardano_serialization_lib as csl;
11
12impl CSLParser {
13 pub fn get_votes(&self) -> &Vec<Vote> {
14 &self.tx_body.votes
15 }
16
17 pub(super) fn extract_votes(&mut self) -> Result<(), WError> {
18 let votes = self.csl_tx_body.voting_procedures();
19 if let Some(votes) = votes {
20 self.tx_body.votes = csl_votes_to_votes(&votes, &self.context)?;
21 }
22 Ok(())
23 }
24}
25
26pub fn csl_votes_to_votes(
27 votes: &csl::VotingProcedures,
28 context: &ParserContext,
29) -> Result<Vec<Vote>, WError> {
30 let mut result = Vec::new();
31 let voters = votes.get_voters();
32 let len = voters.len();
33
34 for i in 0..len {
35 let csl_voter = voters.get(i).ok_or_else(|| {
36 WError::new(
37 "csl_votes_to_votes",
38 &format!("Failed to get voter at index {}", i),
39 )
40 })?;
41 let voter_kind = csl_voter.kind();
42 let governance_action_ids = votes.get_governance_action_ids_by_voter(&csl_voter);
43 let len = governance_action_ids.len();
44
45 let voter_script_hash: Option<csl::ScriptHash>;
46
47 let voter = match voter_kind {
48 csl::VoterKind::ConstitutionalCommitteeHotKeyHash => {
49 let key_hash = csl_voter
50 .to_constitutional_committee_hot_credential()
51 .ok_or_else(|| {
52 WError::new(
53 "csl_votes_to_votes",
54 "Failed to get constitutional committee hot credential",
55 )
56 })?
57 .to_keyhash()
58 .ok_or_else(|| WError::new("csl_votes_to_votes", "Failed to get key hash"))?;
59 voter_script_hash = None;
60 Voter::ConstitutionalCommitteeHotCred(Credential::KeyHash(key_hash.to_hex()))
61 }
62 csl::VoterKind::ConstitutionalCommitteeHotScriptHash => {
63 let script_hash = csl_voter
64 .to_constitutional_committee_hot_credential()
65 .ok_or_else(|| {
66 WError::new(
67 "csl_votes_to_votes",
68 "Failed to get constitutional committee hot credential",
69 )
70 })?
71 .to_scripthash()
72 .ok_or_else(|| {
73 WError::new("csl_votes_to_votes", "Failed to get script hash")
74 })?;
75 voter_script_hash = Some(script_hash.clone());
76 Voter::ConstitutionalCommitteeHotCred(Credential::ScriptHash(script_hash.to_hex()))
77 }
78 csl::VoterKind::DRepKeyHash => {
79 let credential = csl_voter.to_drep_credential().ok_or_else(|| {
80 WError::new("csl_votes_to_votes", "Failed to get drep credential")
81 })?;
82 let csl_drep_credential = csl::DRep::new_from_credential(&credential);
83 voter_script_hash = None;
84 Voter::DRepId(csl_drep_credential.to_bech32(true).map_err(|e| {
85 WError::new(
86 "csl_votes_to_votes",
87 &format!("Failed to convert drep to bech32: {:?}", e),
88 )
89 })?)
90 }
91 csl::VoterKind::DRepScriptHash => {
92 let credential = csl_voter.to_drep_credential().ok_or_else(|| {
93 WError::new("csl_votes_to_votes", "Failed to get drep credential")
94 })?;
95 let csl_drep_credential = csl::DRep::new_from_credential(&credential);
96 voter_script_hash = csl_drep_credential.to_script_hash();
97 Voter::DRepId(csl_drep_credential.to_bech32(true).map_err(|e| {
98 WError::new(
99 "csl_votes_to_votes",
100 &format!("Failed to convert drep to bech32: {:?}", e),
101 )
102 })?)
103 }
104 csl::VoterKind::StakingPoolKeyHash => {
105 let key_hash = csl_voter.to_stake_pool_key_hash().ok_or_else(|| {
106 WError::new("csl_votes_to_votes", "Failed to get stake pool key hash")
107 })?;
108 voter_script_hash = None;
109 Voter::StakingPoolKeyHash(key_hash.to_hex())
110 }
111 };
112
113 for j in 0..len {
114 let gov_action_id = governance_action_ids.get(j).ok_or_else(|| {
115 WError::new(
116 "csl_votes_to_votes",
117 &format!("Failed to get governance action ID at index {}", j),
118 )
119 })?;
120 let voting_procedure = votes.get(&csl_voter, &gov_action_id).ok_or_else(|| {
121 WError::new(
122 "csl_votes_to_votes",
123 &format!(
124 "Failed to get voting procedure for governance action ID: {:?}",
125 gov_action_id
126 ),
127 )
128 })?;
129
130 let gov_action_id = RefTxIn {
131 tx_hash: gov_action_id.transaction_id().to_hex(),
132 tx_index: gov_action_id.index(),
133 script_size: None,
134 };
135
136 let vote_kind = match voting_procedure.vote_kind() {
137 csl::VoteKind::No => VoteKind::No,
138 csl::VoteKind::Yes => VoteKind::Yes,
139 csl::VoteKind::Abstain => VoteKind::Abstain,
140 };
141
142 let anchor = if let Some(anchor) = voting_procedure.anchor() {
143 Some(Anchor {
144 anchor_url: anchor.url().url(),
145 anchor_data_hash: anchor.anchor_data_hash().to_hex(),
146 })
147 } else {
148 None
149 };
150
151 let voting_procedure = VotingProcedure { vote_kind, anchor };
152
153 let vote_type = VoteType {
154 voter: voter.clone(),
155 gov_action_id,
156 voting_procedure,
157 };
158
159 if let Some(script_hash) = &voter_script_hash {
160 if let Some(script) = context.script_witness.scripts.get(&script_hash) {
161 match script {
162 Script::ProvidedNative(native_script) => {
163 result.push(Vote::SimpleScriptVote(SimpleScriptVote {
164 vote: vote_type,
165 simple_script_source: Some(
166 SimpleScriptSource::ProvidedSimpleScriptSource(
167 native_script.clone(),
168 ),
169 ),
170 }));
171 }
172 Script::ProvidedPlutus(plutus_script) => {
173 let redeemer = context
174 .script_witness
175 .redeemers
176 .get(&RedeemerIndex::Vote(i))
177 .cloned();
178 result.push(Vote::ScriptVote(ScriptVote {
179 vote: vote_type,
180 redeemer,
181 script_source: Some(ScriptSource::ProvidedScriptSource(
182 plutus_script.clone(),
183 )),
184 }));
185 }
186 Script::ReferencedNative(inline_script) => {
187 result.push(Vote::SimpleScriptVote(SimpleScriptVote {
188 vote: vote_type,
189 simple_script_source: Some(
190 SimpleScriptSource::InlineSimpleScriptSource(
191 inline_script.clone(),
192 ),
193 ),
194 }));
195 }
196 Script::ReferencedPlutus(inline_script) => {
197 let redeemer = context
198 .script_witness
199 .redeemers
200 .get(&RedeemerIndex::Vote(i))
201 .cloned();
202 result.push(Vote::ScriptVote(ScriptVote {
203 vote: vote_type,
204 redeemer,
205 script_source: Some(ScriptSource::InlineScriptSource(
206 inline_script.clone(),
207 )),
208 }));
209 }
210 }
211 } else {
212 result.push(Vote::BasicVote(vote_type));
213 }
214 } else {
215 result.push(Vote::BasicVote(vote_type));
216 }
217 }
218 }
219 Ok(result)
220}