1 | package org.cardanofoundation.explorer.api.service.impl; | |
2 | ||
3 | import java.util.ArrayList; | |
4 | import java.util.Arrays; | |
5 | import java.util.Comparator; | |
6 | import java.util.Date; | |
7 | import java.util.List; | |
8 | import java.util.Map; | |
9 | import java.util.function.BinaryOperator; | |
10 | import java.util.function.Function; | |
11 | import java.util.stream.Collectors; | |
12 | ||
13 | import lombok.RequiredArgsConstructor; | |
14 | ||
15 | import org.springframework.data.domain.Page; | |
16 | import org.springframework.data.domain.Pageable; | |
17 | import org.springframework.data.util.Pair; | |
18 | import org.springframework.stereotype.Service; | |
19 | ||
20 | import org.cardanofoundation.explorer.api.common.enumeration.CommitteeStatus; | |
21 | import org.cardanofoundation.explorer.api.exception.BusinessCode; | |
22 | import org.cardanofoundation.explorer.api.model.response.BaseFilterResponse; | |
23 | import org.cardanofoundation.explorer.api.model.response.committee.CommitteeMemberResponse; | |
24 | import org.cardanofoundation.explorer.api.model.response.committee.CommitteeOverviewResponse; | |
25 | import org.cardanofoundation.explorer.api.model.response.drep.VotingProcedureChartResponse; | |
26 | import org.cardanofoundation.explorer.api.projection.VotingProcedureProjection; | |
27 | import org.cardanofoundation.explorer.api.repository.ledgersync.*; | |
28 | import org.cardanofoundation.explorer.api.service.CCommitteeService; | |
29 | import org.cardanofoundation.explorer.api.service.ProtocolParamService; | |
30 | import org.cardanofoundation.explorer.common.entity.enumeration.CommitteeState; | |
31 | import org.cardanofoundation.explorer.common.entity.enumeration.GovActionType; | |
32 | import org.cardanofoundation.explorer.common.entity.enumeration.Vote; | |
33 | import org.cardanofoundation.explorer.common.entity.ledgersync.CommitteeMember; | |
34 | import org.cardanofoundation.explorer.common.entity.ledgersync.CommitteeRegistration; | |
35 | import org.cardanofoundation.explorer.common.entity.ledgersync.EpochParam; | |
36 | import org.cardanofoundation.explorer.common.exception.BusinessException; | |
37 | ||
38 | @Service | |
39 | @RequiredArgsConstructor | |
40 | public class CCommitteeServiceImpl implements CCommitteeService { | |
41 | ||
42 | private final CommitteeMemberRepository committeeMemberRepository; | |
43 | private final GovernanceActionRepository governanceActionRepository; | |
44 | private final LatestVotingProcedureRepository latestVotingProcedureRepository; | |
45 | private final CommitteeRegistrationRepository committeeRegistrationRepository; | |
46 | private final EpochParamRepository epochParamRepository; | |
47 | private final EpochRepository epochRepository; | |
48 | private final VotingProcedureRepository votingProcedureRepository; | |
49 | private final CommitteeDeRegistrationRepository committeeDeRegistrationRepository; | |
50 | private final CommitteeRepository committeeRepository; | |
51 | private final ProtocolParamService protocolParamService; | |
52 | ||
53 | @Override | |
54 | public CommitteeOverviewResponse getCommitteeOverview() { | |
55 | EpochParam currentEpochParam = epochParamRepository.findCurrentEpochParam(); | |
56 | long activeMembers = | |
57 | committeeMemberRepository.countActiveMembersByExpiredEpochGreaterThan( | |
58 | currentEpochParam.getEpochNo()); | |
59 | ||
60 | CommitteeState committeeState = | |
61 |
2
1. getCommitteeOverview : negated conditional → NO_COVERAGE 2. getCommitteeOverview : changed conditional boundary → NO_COVERAGE |
activeMembers >= currentEpochParam.getCommitteeMinSize().intValue() |
62 | ? CommitteeState.CONFIDENCE | |
63 | : CommitteeState.NO_CONFIDENCE; | |
64 | ||
65 | Double latestCCThreshold = | |
66 | committeeRepository | |
67 | .getLatestCCThreshold() | |
68 | .orElseGet(protocolParamService::getCCThresholdFromConwayGenesis); | |
69 | ||
70 | // TODO: get activeEpoch from lsv2 once implemented | |
71 | Integer activeEpoch = | |
72 | committeeMemberRepository.getMinExpireEpochOfActiveMembers(currentEpochParam.getEpochNo()) | |
73 |
1
1. getCommitteeOverview : Replaced integer subtraction with addition → NO_COVERAGE |
- currentEpochParam.getCommitteeMaxTermLength().intValue(); |
74 | ||
75 | Long activeEpochSecondTime = epochRepository.getEpochSecondTimeByEpochNo(activeEpoch); | |
76 | ||
77 | List<GovActionType> govActionTypeList = new ArrayList<>(Arrays.asList(GovActionType.values())); | |
78 | govActionTypeList.removeAll( | |
79 | List.of(GovActionType.NO_CONFIDENCE, GovActionType.UPDATE_COMMITTEE)); | |
80 | ||
81 | Long governanceVotes = | |
82 | governanceActionRepository.countGovThatAllowedToVoteByBlockTimeGreaterThanAndGovType( | |
83 | activeEpochSecondTime, govActionTypeList); | |
84 | ||
85 | // TODO: get from lsv2 once implemented | |
86 | String proposalPolicy = null; | |
87 | ||
88 | // TODO: get from lsv2 once implemented | |
89 | Long lastUpdate = activeEpochSecondTime; | |
90 | ||
91 |
1
1. getCommitteeOverview : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::getCommitteeOverview → NO_COVERAGE |
return CommitteeOverviewResponse.builder() |
92 | .currentState(committeeState) | |
93 | .proposalPolicy(proposalPolicy) | |
94 | .activeMembers(activeMembers) | |
95 | .threshold(latestCCThreshold) | |
96 | .governanceVotes(governanceVotes) | |
97 |
2
1. getCommitteeOverview : Replaced long multiplication with division → NO_COVERAGE 2. getCommitteeOverview : negated conditional → NO_COVERAGE |
.lastUpdate(lastUpdate == null ? null : new Date(lastUpdate * 1000)) |
98 | .build(); | |
99 | } | |
100 | ||
101 | @Override | |
102 | public BaseFilterResponse<CommitteeMemberResponse> getCommitteeMembers(Pageable pageable) { | |
103 | EpochParam currentEpochParam = epochParamRepository.findCurrentEpochParam(); | |
104 | ||
105 | Page<CommitteeMember> committeeMemberPages = committeeMemberRepository.findAll(pageable); | |
106 | List<String> coldKeys = committeeMemberPages.map(CommitteeMember::getHash).getContent(); | |
107 | ||
108 | Map<String, String> hotKeyMap = | |
109 | committeeRegistrationRepository.getHotKeyOfCommitteeMemberByColdKeyIn(coldKeys).stream() | |
110 | .collect( | |
111 | Collectors.toMap( | |
112 | CommitteeRegistration::getColdKey, CommitteeRegistration::getHotKey)); | |
113 | ||
114 | Page<CommitteeMemberResponse> committeeMemberResponses = | |
115 | committeeMemberPages.map( | |
116 | committeeMember -> { | |
117 | CommitteeMemberResponse committeeMemberResponse = new CommitteeMemberResponse(); | |
118 |
1
1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setScriptHash → NO_COVERAGE |
committeeMemberResponse.setScriptHash(committeeMember.getHash()); |
119 |
1
1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setPublicKey → NO_COVERAGE |
committeeMemberResponse.setPublicKey(hotKeyMap.get(committeeMember.getHash())); |
120 |
1
1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setStatus → NO_COVERAGE |
committeeMemberResponse.setStatus( |
121 |
2
1. lambda$getCommitteeMembers$0 : changed conditional boundary → NO_COVERAGE 2. lambda$getCommitteeMembers$0 : negated conditional → NO_COVERAGE |
committeeMember.getExpiredEpoch() > currentEpochParam.getEpochNo() |
122 | ? CommitteeStatus.ACTIVE | |
123 | : CommitteeStatus.EXPIRED); | |
124 |
1
1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setExpiredEpoch → NO_COVERAGE |
committeeMemberResponse.setExpiredEpoch(committeeMember.getExpiredEpoch()); |
125 | // TODO: get from lsv2 once implemented | |
126 |
1
1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setActiveEpoch → NO_COVERAGE |
committeeMemberResponse.setActiveEpoch( |
127 | committeeMember.getExpiredEpoch() | |
128 |
1
1. lambda$getCommitteeMembers$0 : Replaced integer subtraction with addition → NO_COVERAGE |
- currentEpochParam.getCommitteeMaxTermLength().intValue()); |
129 |
1
1. lambda$getCommitteeMembers$0 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getCommitteeMembers$0 → NO_COVERAGE |
return committeeMemberResponse; |
130 | }); | |
131 | ||
132 |
1
1. getCommitteeMembers : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::getCommitteeMembers → NO_COVERAGE |
return new BaseFilterResponse<>(committeeMemberResponses); |
133 | } | |
134 | ||
135 | @Override | |
136 | public CommitteeMemberResponse getCommitteeMemberDetail(String publicKey) { | |
137 | CommitteeRegistration committeeRegistration = | |
138 | committeeRegistrationRepository.getCommitteeRegistrationByHotKey(publicKey); | |
139 | ||
140 |
1
1. getCommitteeMemberDetail : negated conditional → NO_COVERAGE |
if (committeeRegistration == null) { |
141 | throw new BusinessException(BusinessCode.COMMITTEE_MEMBER_NOT_FOUND); | |
142 | } | |
143 | ||
144 | CommitteeMember committeeMember = | |
145 | committeeMemberRepository | |
146 | .findById(committeeRegistration.getColdKey()) | |
147 |
1
1. lambda$getCommitteeMemberDetail$1 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getCommitteeMemberDetail$1 → NO_COVERAGE |
.orElseThrow(() -> new BusinessException(BusinessCode.COMMITTEE_MEMBER_NOT_FOUND)); |
148 | ||
149 | EpochParam currentEpochParam = epochParamRepository.findCurrentEpochParam(); | |
150 | ||
151 | // TODO: get activeEpoch from lsv2 once implemented | |
152 | Integer activeEpoch = | |
153 | committeeMemberRepository.getMinExpireEpochOfActiveMembers(currentEpochParam.getEpochNo()) | |
154 |
1
1. getCommitteeMemberDetail : Replaced integer subtraction with addition → NO_COVERAGE |
- currentEpochParam.getCommitteeMaxTermLength().intValue(); |
155 | Long activeEpochSecondTime = epochRepository.getEpochSecondTimeByEpochNo(activeEpoch); | |
156 | ||
157 | Long resignedBlockTime = | |
158 | committeeDeRegistrationRepository.getResignationBlockTimeByColdKey( | |
159 | committeeMember.getHash()); | |
160 | ||
161 | Long votedGovCount = | |
162 | latestVotingProcedureRepository.countVoteByVoterHash( | |
163 | committeeRegistration.getHotKey(), activeEpochSecondTime); | |
164 | ||
165 | List<GovActionType> govActionTypeList = new ArrayList<>(Arrays.asList(GovActionType.values())); | |
166 | govActionTypeList.removeAll( | |
167 | List.of(GovActionType.NO_CONFIDENCE, GovActionType.UPDATE_COMMITTEE)); | |
168 | ||
169 | Long govAllowedToVote = | |
170 | governanceActionRepository.countGovThatAllowedToVoteByBlockTimeGreaterThanAndGovType( | |
171 | activeEpochSecondTime, govActionTypeList); | |
172 | Float votingParticipation = | |
173 |
2
1. getCommitteeMemberDetail : Replaced float division with multiplication → NO_COVERAGE 2. getCommitteeMemberDetail : negated conditional → NO_COVERAGE |
govAllowedToVote == 0 ? 0 : (float) votedGovCount / govAllowedToVote; |
174 | ||
175 |
1
1. getCommitteeMemberDetail : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::getCommitteeMemberDetail → NO_COVERAGE |
return CommitteeMemberResponse.builder() |
176 | .scriptHash(committeeRegistration.getColdKey()) | |
177 | .publicKey(committeeRegistration.getHotKey()) | |
178 | .status( | |
179 |
2
1. getCommitteeMemberDetail : negated conditional → NO_COVERAGE 2. getCommitteeMemberDetail : changed conditional boundary → NO_COVERAGE |
committeeMember.getExpiredEpoch() > currentEpochParam.getEpochNo() |
180 | ? CommitteeStatus.ACTIVE | |
181 | : CommitteeStatus.EXPIRED) | |
182 |
1
1. getCommitteeMemberDetail : Replaced long multiplication with division → NO_COVERAGE |
.registeredAt(new Date(activeEpochSecondTime * 1000)) |
183 |
2
1. getCommitteeMemberDetail : negated conditional → NO_COVERAGE 2. getCommitteeMemberDetail : Replaced long multiplication with division → NO_COVERAGE |
.resignedAt(resignedBlockTime == null ? null : new Date(resignedBlockTime * 1000)) |
184 | .activeEpoch(activeEpoch) | |
185 | .expiredEpoch(committeeMember.getExpiredEpoch()) | |
186 | .termDuration(currentEpochParam.getCommitteeMaxTermLength().intValue()) | |
187 | .votingParticipation(votingParticipation) | |
188 | .build(); | |
189 | } | |
190 | ||
191 | @Override | |
192 | public VotingProcedureChartResponse getVoteProcedureChart( | |
193 | String publicKey, GovActionType govActionType) { | |
194 | CommitteeRegistration committeeRegistration = | |
195 | committeeRegistrationRepository.getCommitteeRegistrationByHotKey(publicKey); | |
196 | ||
197 |
1
1. getVoteProcedureChart : negated conditional → NO_COVERAGE |
if (committeeRegistration == null) { |
198 | throw new BusinessException(BusinessCode.COMMITTEE_MEMBER_NOT_FOUND); | |
199 | } | |
200 | ||
201 | EpochParam currentEpochParam = epochParamRepository.findCurrentEpochParam(); | |
202 | // TODO: get activeEpoch from lsv2 once implemented | |
203 | Integer activeEpoch = | |
204 | committeeMemberRepository.getMinExpireEpochOfActiveMembers(currentEpochParam.getEpochNo()) | |
205 |
1
1. getVoteProcedureChart : Replaced integer subtraction with addition → NO_COVERAGE |
- currentEpochParam.getCommitteeMaxTermLength().intValue(); |
206 | Long activeEpochSecondTime = epochRepository.getEpochSecondTimeByEpochNo(activeEpoch); | |
207 | ||
208 | List<VotingProcedureProjection> votingProcedureProjections = | |
209 | votingProcedureRepository.findVotingProcedureByVoterHashAndGovActionType( | |
210 | publicKey, | |
211 |
1
1. getVoteProcedureChart : negated conditional → NO_COVERAGE |
govActionType.equals(GovActionType.ALL) ? null : govActionType, |
212 | activeEpochSecondTime); | |
213 | List<VotingProcedureProjection> votingProcedureProjectionListResponse = | |
214 | votingProcedureProjections.stream() | |
215 | .collect( | |
216 | Collectors.toMap( | |
217 |
1
1. lambda$getVoteProcedureChart$2 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getVoteProcedureChart$2 → NO_COVERAGE |
e -> Pair.of(e.getGovActionTxHash(), e.getGovActionIndex()), |
218 | Function.identity(), | |
219 | BinaryOperator.maxBy( | |
220 | Comparator.comparing(VotingProcedureProjection::getBlockTime)))) | |
221 | .values() | |
222 | .stream() | |
223 | .toList(); | |
224 | Map<Vote, Long> counted = | |
225 | votingProcedureProjectionListResponse.stream() | |
226 | .collect( | |
227 | Collectors.groupingBy(VotingProcedureProjection::getVote, Collectors.counting())); | |
228 | ||
229 |
1
1. getVoteProcedureChart : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::getVoteProcedureChart → NO_COVERAGE |
return VotingProcedureChartResponse.builder() |
230 | .dRepHash(publicKey) | |
231 | .govActionType(govActionType) | |
232 | .numberOfYesVote(counted.getOrDefault(Vote.YES, 0L)) | |
233 | .numberOfNoVotes(counted.getOrDefault(Vote.NO, 0L)) | |
234 | .numberOfAbstainVotes(counted.getOrDefault(Vote.ABSTAIN, 0L)) | |
235 | .build(); | |
236 | } | |
237 | } | |
Mutations | ||
61 |
1.1 2.2 |
|
73 |
1.1 |
|
91 |
1.1 |
|
97 |
1.1 2.2 |
|
118 |
1.1 |
|
119 |
1.1 |
|
120 |
1.1 |
|
121 |
1.1 2.2 |
|
124 |
1.1 |
|
126 |
1.1 |
|
128 |
1.1 |
|
129 |
1.1 |
|
132 |
1.1 |
|
140 |
1.1 |
|
147 |
1.1 |
|
154 |
1.1 |
|
173 |
1.1 2.2 |
|
175 |
1.1 |
|
179 |
1.1 2.2 |
|
182 |
1.1 |
|
183 |
1.1 2.2 |
|
197 |
1.1 |
|
205 |
1.1 |
|
211 |
1.1 |
|
217 |
1.1 |
|
229 |
1.1 |