forked from LaconicNetwork/cosmos-explorer
improve consumer uptime
This commit is contained in:
parent
1243306c69
commit
fac4c1a543
@ -11,7 +11,7 @@
|
||||
{"provider": "Allnodes", "address": "https://neutron-rpc.publicnode.com:443"}
|
||||
],
|
||||
"provider_chain": {
|
||||
"api": ["https://api-cosmoshub-ia.cosmosia.notional.ventures"]
|
||||
"api": ["https://rest.cosmos.directory/cosmoshub"]
|
||||
},
|
||||
"features": ["dashboard", "blocks", "ibc", "cosmwasm", "uptime", "parameters", "state-sync", "consensus", "supply", "widget"],
|
||||
"sdk_version": "0.45.1",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import {
|
||||
fromBase64,
|
||||
fromBech32,
|
||||
toBase64,
|
||||
toBech32,
|
||||
toHex,
|
||||
} from '@cosmjs/encoding';
|
||||
@ -42,6 +43,23 @@ export function consensusPubkeyToHexAddress(consensusPubkey?: {
|
||||
return raw;
|
||||
}
|
||||
|
||||
// not work as expected, will fix later or remove
|
||||
export function consumerKeyToBase64Address(consumerKey?: Record<string, string>) {
|
||||
|
||||
if (!consumerKey) return '';
|
||||
let raw = '';
|
||||
if (consumerKey.ed25519) {
|
||||
const pubkey = fromBase64(consumerKey.ed25519);
|
||||
if (pubkey) return toBase64(sha256(pubkey)).slice(0, 40);
|
||||
}
|
||||
|
||||
if (consumerKey.secp256k1) {
|
||||
const pubkey = fromBase64(consumerKey.secp256k1);
|
||||
if (pubkey) return toBase64(new Ripemd160().update(sha256(pubkey)).digest());
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
export function pubKeyToValcons(
|
||||
consensusPubkey: { '@type': string; key: string },
|
||||
prefix: string
|
||||
@ -57,7 +75,7 @@ export function pubKeyToValcons(
|
||||
}
|
||||
|
||||
export function valconsToBase64(address: string) {
|
||||
if (address) return toHex(fromBech32(address).data).toUpperCase();
|
||||
if (address) return toBase64(fromBech32(address).data);
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
@ -199,4 +199,8 @@ export const DEFAULT: RequestRegistry = {
|
||||
url: '/interchain_security/ccv/provider/opted_in_validators/{chain_id}',
|
||||
adapter,
|
||||
},
|
||||
interchain_security_consumer_validators: {
|
||||
url: '/interchain_security/ccv/provider/consumer_validators/{chain_id}',
|
||||
adapter,
|
||||
},
|
||||
};
|
||||
|
||||
@ -153,6 +153,7 @@ export interface RequestRegistry extends AbstractRegistry {
|
||||
ibc_core_connection_connections_connection_id_client_state: Request<ClientStateWithProof>;
|
||||
interchain_security_ccv_provider_validator_consumer_addr: Request<{consumer_address: string}>
|
||||
interchain_security_provider_opted_in_validators: Request<{validators_provider_addresses: string[]}>
|
||||
interchain_security_consumer_validators: Request<{validators: {provider_address: string, consumer_key: {ed25519: string}, power: string}[]}>
|
||||
}
|
||||
|
||||
export function adapter<T>(source: any): Promise<T> {
|
||||
|
||||
@ -365,4 +365,7 @@ export class CosmosRestClient extends BaseRestClient<RequestRegistry> {
|
||||
async getInterchainSecurityProviderOptedInValidators(chain_id: string) {
|
||||
return this.request(this.registry.interchain_security_provider_opted_in_validators, {chain_id});
|
||||
}
|
||||
async getInterchainSecurityConsumerValidators(chain_id: string) {
|
||||
return this.request(this.registry.interchain_security_consumer_validators, {chain_id});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, computed, onUnmounted } from 'vue';
|
||||
import { fromHex, toBase64 } from '@cosmjs/encoding';
|
||||
import { fromHex, toBase64, fromBase64, toHex } from '@cosmjs/encoding';
|
||||
import {
|
||||
useStakingStore,
|
||||
useBaseStore,
|
||||
@ -22,6 +22,7 @@ const keyword = ref('');
|
||||
const live = ref(true);
|
||||
const slashingParam = ref({} as SlashingParam);
|
||||
const signingInfo = ref({} as Record<string, SigningInfo>);
|
||||
const consumerValidators = ref([] as {moniker: string, base64: string}[]);
|
||||
|
||||
interface BlockColor {
|
||||
height: string;
|
||||
@ -43,11 +44,20 @@ function padding(blocks: BlockColor[] = []) {
|
||||
}
|
||||
|
||||
const validatorSet = computed(() => {
|
||||
if (chainStore.isConsumerChain) {
|
||||
return consumerValidators.value.map((v) => {
|
||||
const b64 = valconsToBase64(v.moniker)
|
||||
const moniker = stakingStore.validators.find((x) => toBase64(fromHex(consensusPubkeyToHexAddress(x.consensus_pubkey))) === b64)?.description.moniker;
|
||||
return {
|
||||
moniker: moniker || v.moniker,
|
||||
base64: v.base64
|
||||
};
|
||||
});
|
||||
};
|
||||
return stakingStore.validators.map((v) => {
|
||||
const hex = consensusPubkeyToHexAddress(v.consensus_pubkey)
|
||||
return {
|
||||
moniker: v.description.moniker,
|
||||
hex,
|
||||
base64: toBase64(fromHex(hex))
|
||||
};
|
||||
});
|
||||
@ -62,13 +72,12 @@ const grid = computed(() => {
|
||||
|
||||
const window = Number(slashingParam.value.signed_blocks_window || 0);
|
||||
return validators.map((v) => {
|
||||
const signing = signingInfo.value[v.hex];
|
||||
const signing = signingInfo.value[v.base64];
|
||||
const uptime = signing && window > 0
|
||||
? (window - Number(signing.missed_blocks_counter)) / window
|
||||
: undefined
|
||||
return {
|
||||
moniker: v.moniker,
|
||||
hex: v.hex,
|
||||
base64: v.base64,
|
||||
blocks: padding(blockColors.value[v.base64] || []),
|
||||
uptime,
|
||||
@ -88,6 +97,21 @@ baseStore.$subscribe((_, state) => {
|
||||
preFill();
|
||||
preload.value = true;
|
||||
}
|
||||
|
||||
// reset the consumer validators
|
||||
if (newHeight > 0 && consumerValidators.value.length === 0) {
|
||||
const chain_id = state.latest.block.header.chain_id;
|
||||
Promise.resolve().then(async () =>{
|
||||
await stakingStore.getConsumerValidators(chain_id).then((x) => {
|
||||
x.validators.forEach(v => {
|
||||
const base64 = toBase64(fromHex(consensusPubkeyToHexAddress({"@type": "/cosmos.crypto.ed25519.PubKey", key: v.consumer_key.ed25519 })));
|
||||
const moniker = v.provider_address;
|
||||
consumerValidators.value.push({ moniker, base64});
|
||||
});
|
||||
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
if (Number(state.latest.block.header.height) % 7 === 0) updateTotalSigningInfo();
|
||||
fillblock(state.latest);
|
||||
@ -97,7 +121,6 @@ baseStore.$subscribe((_, state) => {
|
||||
onMounted(() => {
|
||||
live.value = true;
|
||||
|
||||
|
||||
// fill the recent blocks
|
||||
baseStore.recents?.forEach((b) => {
|
||||
fillblock(b, 'start');
|
||||
@ -172,9 +195,6 @@ function changeTab(v: string) {
|
||||
tab.value = v;
|
||||
}
|
||||
|
||||
function fetchAllKeyRotation() {
|
||||
stakingStore.fetchAllKeyRotation(baseStore.latest?.block?.header?.chain_id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -192,14 +212,8 @@ function fetchAllKeyRotation() {
|
||||
<div class="flex items-center gap-x-4">
|
||||
<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 :class="tab === '2' ? '' : 'hidden'">
|
||||
<div class="flex flex-row flex-wrap gap-x-4 mt-4 justify-center">
|
||||
|
||||
@ -146,7 +146,9 @@ export const useBlockchain = defineStore('blockchain', {
|
||||
// global.current
|
||||
// }
|
||||
useWalletStore().$reset();
|
||||
await useStakingStore().init();
|
||||
if (!this.isConsumerChain) {
|
||||
await useStakingStore().init();
|
||||
}
|
||||
useBankStore().initial();
|
||||
useBaseStore().initial();
|
||||
useGovStore().initial();
|
||||
|
||||
@ -130,11 +130,21 @@ export const useStakingStore = defineStore('stakingStore', {
|
||||
return consensusPubkeyToHexAddress(key)
|
||||
|
||||
},
|
||||
async getConsumerValidators(chain_id: string) {
|
||||
if(this.blockchain.current?.providerChain?.api && this.blockchain.current.providerChain.api.length > 0) {
|
||||
const client = CosmosRestClient.newDefault(this.blockchain.current.providerChain.api[0].address)
|
||||
await client.getStakingValidators('BOND_STATUS_BONDED', 500).then((res) => { this.validators = res.validators });
|
||||
return client.getInterchainSecurityConsumerValidators(chain_id)
|
||||
} else {
|
||||
return { validators: [] }
|
||||
}
|
||||
},
|
||||
async fetchAllKeyRotation(chain_id: string) {
|
||||
let vs = []
|
||||
for(const val of this.validators) {
|
||||
const { prefix } = fromBech32(val.operator_address)
|
||||
console.log(val, prefix)
|
||||
await this.fetchKeyRotation(chain_id, pubKeyToValcons(val.consensus_pubkey, prefix.replace('valoper','valcons')))
|
||||
const cons = pubKeyToValcons(val.consensus_pubkey, prefix.replace('valoper','valcons'))
|
||||
vs.push(cons)
|
||||
}
|
||||
},
|
||||
async fetchValidators(status: string, limit = 300) {
|
||||
@ -142,15 +152,24 @@ export const useStakingStore = defineStore('stakingStore', {
|
||||
if(this.blockchain.current?.providerChain.api && this.blockchain.current.providerChain.api.length > 0) {
|
||||
const client = CosmosRestClient.newDefault(this.blockchain.current.providerChain.api[0].address)
|
||||
// provider validators
|
||||
const res = await client.getStakingValidators(status, limit)
|
||||
const proVals = res.validators.sort(
|
||||
(a, b) => Number(b.delegator_shares) - Number(a.delegator_shares)
|
||||
)
|
||||
if (status === 'BOND_STATUS_BONDED') {
|
||||
this.validators = proVals;
|
||||
}
|
||||
|
||||
return proVals
|
||||
// const baseStore = useBaseStore();
|
||||
// let chain_id = baseStore.latest?.block?.header?.chain_id
|
||||
// // fetch chain id if not available
|
||||
// if (chain_id === undefined) {
|
||||
// await baseStore.fetchLatest();
|
||||
// chain_id = baseStore.latest?.block?.header?.chain_id || "unknown";
|
||||
// }
|
||||
// const res = await client.getInterchainSecurityConsumerValidators(chain_id)
|
||||
// const consumerValidators = res.validators.sort(
|
||||
// (a, b) => Number(b.power) - Number(a.power)
|
||||
// )
|
||||
const providerValidators = await client.getStakingValidators(status, limit);
|
||||
// return consumerValidators.map((val) => {
|
||||
// providerValidators.validators.find((v) => v.consensus_pubkey === val.provider_address)
|
||||
// })
|
||||
return providerValidators;
|
||||
} else {
|
||||
console.error("Please provide provider chain api in your chain configuration")
|
||||
}
|
||||
}
|
||||
return this.blockchain.rpc?.getStakingValidators(status, limit).then((res) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user