forked from cerc-io/cosmos-explorer
Loaded Rotated Keys for consumer chain
This commit is contained in:
parent
62a2d8f927
commit
1e3eb6c56e
@ -190,4 +190,8 @@ export const DEFAULT: RequestRegistry = {
|
||||
url: '/ibc/core/connection/v1/connections/{connection_id}/client_state',
|
||||
adapter,
|
||||
},
|
||||
interchain_security_ccv_provider_validator_consumer_addr: {
|
||||
url: '/interchain_security/ccv/provider/validator_consumer_addr?provider_address={provider_address}&chain_id={chain_id}',
|
||||
adapter,
|
||||
},
|
||||
};
|
||||
|
@ -326,4 +326,7 @@ export class CosmosRestClient extends BaseRestClient<RequestRegistry> {
|
||||
port_id,
|
||||
});
|
||||
}
|
||||
async getInterchainSecurityValidatorRotatedKey(chain_id: string, provider_address: string) {
|
||||
return this.request(this.registry.interchain_security_ccv_provider_validator_consumer_addr, {chain_id, provider_address});
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ export interface RequestRegistry extends AbstractRegistry {
|
||||
ibc_core_connection_connections: Request<PaginatedIBCConnections>;
|
||||
ibc_core_connection_connections_connection_id: Request<ConnectionWithProof>;
|
||||
ibc_core_connection_connections_connection_id_client_state: Request<ClientStateWithProof>;
|
||||
interchain_security_ccv_provider_validator_consumer_addr: Request<{consumer_address: string}>
|
||||
}
|
||||
|
||||
export function adapter<T>(source: any): T {
|
||||
|
@ -93,9 +93,9 @@ async function onChange () {
|
||||
}
|
||||
|
||||
async function fetchPosition() {
|
||||
let dumpurl = rpc.value.replace('consensus_state', 'dump_consensus_state');
|
||||
// let dumpurl = rpc.value.replace('consensus_state', 'dump_consensus_state');
|
||||
try {
|
||||
const response = await fetch(dumpurl);
|
||||
const response = await fetch(rpc.value);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error: ${response.status}`);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from '@/stores';
|
||||
import UptimeBar from '@/components/UptimeBar.vue';
|
||||
import type { Commit, SlashingParam, SigningInfo } from '@/types';
|
||||
import { consensusPubkeyToHexAddress, valconsToBase64 } from '@/libs';
|
||||
import { consensusPubkeyToHexAddress, pubKeyToValcons, valconsToBase64 } from '@/libs';
|
||||
|
||||
const props = defineProps(['chain']);
|
||||
|
||||
@ -25,7 +25,6 @@ const slashingParam = ref({} as SlashingParam);
|
||||
|
||||
const signingInfo = ref({} as Record<string, SigningInfo>);
|
||||
|
||||
const filterOptout = ref(false);
|
||||
// filter validators by keywords
|
||||
const validators = computed(() => {
|
||||
if (keyword)
|
||||
@ -36,6 +35,27 @@ const validators = computed(() => {
|
||||
});
|
||||
|
||||
const list = computed(() => {
|
||||
if(chainStore.isConsumerChain) {
|
||||
stakingStore.loadKeyRotationFromLocalstorage(baseStore.latest?.block?.header?.chain_id)
|
||||
|
||||
const window = Number(slashingParam.value.signed_blocks_window || 0);
|
||||
const vset = validators.value.map((v) => {
|
||||
|
||||
const hexAddress = stakingStore.findRotatedHexAddress(v.consensus_pubkey)
|
||||
const signing =
|
||||
signingInfo.value[hexAddress];
|
||||
return {
|
||||
v,
|
||||
signing,
|
||||
hex: toBase64(fromHex(hexAddress)),
|
||||
uptime:
|
||||
signing && window > 0
|
||||
? (window - Number(signing.missed_blocks_counter)) / window
|
||||
: undefined,
|
||||
};
|
||||
});
|
||||
return vset;
|
||||
} else {
|
||||
const window = Number(slashingParam.value.signed_blocks_window || 0);
|
||||
const vset = validators.value.map((v) => {
|
||||
const signing =
|
||||
@ -50,12 +70,12 @@ const list = computed(() => {
|
||||
: undefined,
|
||||
};
|
||||
});
|
||||
return filterOptout.value ? vset.filter((x) => x.signing) : vset;
|
||||
return vset;
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
live.value = true;
|
||||
|
||||
baseStore.fetchLatest().then((l) => {
|
||||
let b = l;
|
||||
if (
|
||||
@ -113,6 +133,10 @@ const tab = ref('2');
|
||||
function changeTab(v: string) {
|
||||
tab.value = v;
|
||||
}
|
||||
|
||||
function fetchAllKeyRotation() {
|
||||
stakingStore.fetchAllKeyRotation(baseStore.latest?.block?.header?.chain_id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -136,16 +160,19 @@ function changeTab(v: string) {
|
||||
</div>
|
||||
<div class="bg-base-100 px-5 pt-5">
|
||||
<div class="flex items-center gap-x-4">
|
||||
<label v-if="chainStore.isConsumerChain" class="text-center">
|
||||
<input type="checkbox" v-model="filterOptout" class="checkbox" />
|
||||
{{ $t('uptime.only_consumer_set') }}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
v-model="keyword"
|
||||
placeholder="Keywords to filter validators"
|
||||
class="input input-sm w-full flex-1 border border-gray-200 dark:border-gray-600"
|
||||
/>
|
||||
<button v-if="chainStore.isConsumerChain" class="btn btn-sm btn-primary" @click="fetchAllKeyRotation">Load Rotated Keys</button>
|
||||
</div>
|
||||
|
||||
<div v-if="chainStore.isConsumerChain && Object.keys(stakingStore.keyRotation).length === 0"
|
||||
class="alert alert-warning my-4"
|
||||
>
|
||||
Note: Please load rotated keys to see the correct uptime
|
||||
</div>
|
||||
<!-- grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-x-4 mt-4 -->
|
||||
<div
|
||||
|
@ -4,8 +4,9 @@ import { useBlockchain } from './useBlockchain';
|
||||
import { get } from '@/libs/http';
|
||||
import type { StakingParam, StakingPool, Validator } from '@/types';
|
||||
import { CosmosRestClient } from '@/libs/client';
|
||||
import { consensusPubkeyToHexAddress, valconsToBase64 } from '@/libs';
|
||||
import { toHex, fromBase64 } from '@cosmjs/encoding';
|
||||
import { consensusPubkeyToHexAddress, pubKeyToValcons, valconsToBase64 } from '@/libs';
|
||||
import { toHex, fromBase64, toBase64, fromHex, fromBech32 } from '@cosmjs/encoding';
|
||||
import { useBaseStore } from './useBaseStore';
|
||||
|
||||
export const useStakingStore = defineStore('stakingStore', {
|
||||
state: () => {
|
||||
@ -24,6 +25,7 @@ export const useStakingStore = defineStore('stakingStore', {
|
||||
bonded_tokens: string;
|
||||
not_bonded_tokens: string;
|
||||
},
|
||||
keyRotation: {} as Record<string, string>,
|
||||
};
|
||||
},
|
||||
getters: {
|
||||
@ -78,11 +80,60 @@ export const useStakingStore = defineStore('stakingStore', {
|
||||
delegatorAddr
|
||||
);
|
||||
},
|
||||
async fetchKeyRotation(chain_id: string, validatorAddr: string ) : Promise<string> {
|
||||
if(this.blockchain.isConsumerChain) {
|
||||
if(this.blockchain.current?.providerChain.api && this.blockchain.current.providerChain.api.length > 0) {
|
||||
const signatures = useBaseStore().latest?.block?.last_commit.signatures
|
||||
if(signatures) {
|
||||
// console.log(signatures)
|
||||
const key = toBase64(fromHex(valconsToBase64(validatorAddr)))
|
||||
const exists = signatures.findIndex((x) => x.validator_address === key)
|
||||
if(exists < 0) {
|
||||
|
||||
const client = CosmosRestClient.newDefault(this.blockchain.current.providerChain.api[0].address)
|
||||
const res = await client.getInterchainSecurityValidatorRotatedKey(chain_id, validatorAddr);
|
||||
if(res.consumer_address) {
|
||||
this.keyRotation[validatorAddr] = res.consumer_address
|
||||
localStorage.setItem(`key-rotation-${chain_id}`, JSON.stringify(this.keyRotation))
|
||||
}
|
||||
return res.consumer_address
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
},
|
||||
|
||||
async loadKeyRotationFromLocalstorage(chain_id: string) {
|
||||
const keyRotation = localStorage.getItem(`key-rotation-${chain_id}`)
|
||||
this.keyRotation = keyRotation ? JSON.parse(keyRotation) : {}
|
||||
},
|
||||
|
||||
findRotatedHexAddress(key: {
|
||||
"@type": string;
|
||||
key: string;
|
||||
}) {
|
||||
|
||||
const prefix = "cosmos"
|
||||
const conskey = pubKeyToValcons(key, prefix)
|
||||
const rotated = this.keyRotation[conskey]
|
||||
if(rotated) {
|
||||
return valconsToBase64(rotated)
|
||||
}
|
||||
return consensusPubkeyToHexAddress(key)
|
||||
|
||||
},
|
||||
async fetchAllKeyRotation(chain_id: string) {
|
||||
for(const val of this.validators) {
|
||||
const { prefix } = fromBech32(val.operator_address)
|
||||
await this.fetchKeyRotation(chain_id, pubKeyToValcons(val.consensus_pubkey, prefix.replace('valoper','')))
|
||||
}
|
||||
},
|
||||
async fetchValidators(status: string) {
|
||||
if(this.blockchain.isConsumerChain) {
|
||||
if(this.blockchain.current?.providerChain.api && this.blockchain.current.providerChain.api.length > 0) {
|
||||
const client = CosmosRestClient.newDefault(this.blockchain.current.providerChain.api[0].address)
|
||||
// const vals = await client.getBaseValidatorsetLatest(0)
|
||||
// provider validators
|
||||
const res = await client.getStakingValidators(status)
|
||||
const proVals = res.validators.sort(
|
||||
(a, b) => Number(b.delegator_shares) - Number(a.delegator_shares)
|
||||
@ -90,6 +141,7 @@ export const useStakingStore = defineStore('stakingStore', {
|
||||
if (status === 'BOND_STATUS_BONDED') {
|
||||
this.validators = proVals;
|
||||
}
|
||||
|
||||
return proVals
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user