diff --git a/CHANGELOG.md b/CHANGELOG.md index 97c807e8..d44adc51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,9 +33,15 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Unreleased +### Improvements + * Updated Prov Protos to 1.19.0-rc2 [#522](https://github.com/provenance-io/explorer-service/pull/522) * Updated gRPC query to use `query` field instead of `events` field [#523](https://github.com/provenance-io/explorer-service/pull/523) +### Bug Fixes + +* Fixed issue with Proto deserialization incorrectly matching `cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal` as `cosmos.upgrade.v1beta1.SoftwareUpgradeProposal`, ensuring accurate type URL handling. [#524](https://github.com/provenance-io/explorer-service/pull/524) + ## [v5.10.0](https://github.com/provenance-io/explorer-service/releases/tag/v5.10.0) - 2024-06-11 ### Release Name: Fridtjof Nansen diff --git a/service/src/main/kotlin/io/provenance/explorer/service/ExplorerService.kt b/service/src/main/kotlin/io/provenance/explorer/service/ExplorerService.kt index d90ace12..72a8befe 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/ExplorerService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/ExplorerService.kt @@ -208,7 +208,9 @@ class ExplorerService( val typeUrl = govService.getUpgradeProtoType() val scheduledName = runBlocking { govClient.getIfUpgradeScheduled()?.plan?.name } val proposals = GovProposalRecord.findByProposalType(typeUrl) - .filter { it.status == Gov.ProposalStatus.PROPOSAL_STATUS_PASSED.name } + .filter { + it.status == Gov.ProposalStatus.PROPOSAL_STATUS_PASSED.name && it.getUpgradePlan() != null + } val knownReleases = CacheUpdateRecord.fetchCacheByKey(CacheKeys.CHAIN_RELEASES.key)?.cacheValue?.let { VANILLA_MAPPER.readValue>(it) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/GovService.kt b/service/src/main/kotlin/io/provenance/explorer/service/GovService.kt index 1b73b150..220eaa5f 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/GovService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/GovService.kt @@ -3,6 +3,7 @@ package io.provenance.explorer.service import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.module.kotlin.readValue import com.google.protobuf.Any +import com.google.protobuf.InvalidProtocolBufferException import com.google.protobuf.util.JsonFormat import cosmos.gov.v1.Gov import cosmos.gov.v1.Gov.VoteOption @@ -15,6 +16,7 @@ import cosmos.gov.v1.weightedVoteOption import cosmos.gov.v1beta1.textProposal import cosmos.params.v1beta1.paramChange import cosmos.params.v1beta1.parameterChangeProposal +import cosmos.upgrade.v1beta1.Upgrade import cosmos.upgrade.v1beta1.cancelSoftwareUpgradeProposal import cosmos.upgrade.v1beta1.plan import cosmos.upgrade.v1beta1.softwareUpgradeProposal @@ -769,24 +771,42 @@ fun List.getProposalTypeList() = this.joinToString(", ") { msg -> msg.getPr fun String.toProposalTypeList() = this.split(", ") -fun GovProposalRecord?.getUpgradePlan() = - this?.contentV1?.list - ?.mapNotNull { msg -> - when { - msg.typeUrl.contains("MsgSoftwareUpgrade") -> msg.toMsgSoftwareUpgrade().plan - msg.typeUrl.contains("gov.v1.MsgExecLegacyContent") -> - msg.toMsgExecLegacyContent().content.let { - if (it.typeUrl.contains("SoftwareUpgradeProposal")) { - it.toSoftwareUpgradeProposal().plan - } else { - null - } - } +fun GovProposalRecord?.getUpgradePlan(): Upgrade.Plan? { + return this?.let { + getUpgradePlanFromContentV1(it) ?: getUpgradePlanFromDataV1beta1(it) + } +} + +private fun getUpgradePlanFromContentV1(record: GovProposalRecord): Upgrade.Plan? { + return record.contentV1?.list + ?.mapNotNull { msg -> processUpgradeProposalMessage(msg) } + ?.firstOrNull() +} + +private fun getUpgradePlanFromDataV1beta1(record: GovProposalRecord): Upgrade.Plan? { + return try { + record.dataV1beta1?.content?.toSoftwareUpgradeProposal()?.plan + } catch (e: InvalidProtocolBufferException) { + logger().error("unable to unpack ${record.dataV1beta1?.content} to SoftwareUpgradeProposal") + null + } +} - else -> null +private fun processUpgradeProposalMessage(msg: Any): Upgrade.Plan? { + return when { + msg.typeUrl.contains("cosmos.upgrade.v1beta1.MsgSoftwareUpgrade") -> msg.toMsgSoftwareUpgrade().plan + msg.typeUrl.contains("cosmos.gov.v1.MsgExecLegacyContent") -> { + msg.toMsgExecLegacyContent().content.let { + if (it.typeUrl.contains("cosmos.upgrade.v1beta1.SoftwareUpgradeProposal")) { + it.toSoftwareUpgradeProposal().plan + } else { + null + } } - }?.first() - ?: this?.dataV1beta1?.content?.toSoftwareUpgradeProposal()?.plan + } + else -> null + } +} fun String.toVoteMetadata() = if (this.isBlank()) { diff --git a/service/src/main/kotlin/io/provenance/explorer/service/NotificationService.kt b/service/src/main/kotlin/io/provenance/explorer/service/NotificationService.kt index 52afde58..aca5dfd0 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/NotificationService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/NotificationService.kt @@ -47,7 +47,7 @@ class NotificationService( val currentHeight = blockService.getLatestBlockHeightIndexOrFromChain() val upgrades = GovProposalRecord.findByProposalType(govService.getUpgradeProtoType()) - .filter { it.status == Gov.ProposalStatus.PROPOSAL_STATUS_PASSED.name } + .filter { it.status == Gov.ProposalStatus.PROPOSAL_STATUS_PASSED.name && it.getUpgradePlan() != null } .filter { proposal -> val name = proposal.getUpgradePlan()!!.name govClient.getIfUpgradeApplied(name).height == 0L &&