Last active
November 16, 2022 18:31
-
-
Save clemensgg/579983404afd4e906a4419fe4e81d100 to your computer and use it in GitHub Desktop.
GOC_differing_valsets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Gist depracted in favour of https://github.com/clemensgg/game-of-chains/ | |
'use strict'; | |
import axios from 'axios'; | |
import { createHash } from 'crypto'; | |
import fs from 'fs/promises'; | |
/* ------------------------ CONFIG ------------------------ */ | |
const provider = { | |
"id": "provider", | |
"lcd": "http://0.0.0.0:26619", | |
"start_height": 140100, | |
"last_height": 0, | |
"valset_data": [["height", "hash","total_vp"]] | |
} | |
const consumer = { | |
"id": "sputnik", | |
"lcd": "http://0.0.0.0:26629", | |
"start_height": 86800, | |
"last_height": 0, | |
"valset_data": [["height", "hash", "total_vp"]] | |
} | |
/* -------------------------------------------------------- */ | |
// generate sha256 hash | |
function hash(string) { | |
return createHash('sha256').update(string).digest('hex'); | |
} | |
// async write file | |
async function writeFile(path, data) { | |
try { | |
await fs.writeFile(path, data); | |
} | |
catch (e) { | |
console.log('> ERROR writing blacklist to filesystem'); | |
console.log(e.data); | |
return false; | |
} | |
return true; | |
} | |
// save all valset records | |
async function dumpValsetRecords() { | |
let cc_file = './export/' + consumer.id + '_valsets_' + consumer.last_height + '.csv' | |
let pc_file = './export/' + provider.id + '_valsets_' + provider.last_height + '.csv' | |
let csvContent = "" | |
+ consumer.valset_data.map(e => e.join(",")).join("\n"); | |
let res = await writeFile(cc_file, csvContent); | |
if (res) { | |
console.log('saved CONSUMER set to file: ' + cc_file); | |
} | |
csvContent = "" | |
+ provider.valset_data.map(e => e.join(",")).join("\n"); | |
res = await writeFile(pc_file, csvContent); | |
if (res) { | |
console.log('saved PROVIDER set to file: ' + pc_file); | |
} | |
return true; | |
} | |
// fetch latest valset | |
async function fetchLatestValset(chain) { | |
try { | |
var res = await axios.get(chain.lcd + '/validatorsets/latest'); | |
} | |
catch (e) { | |
console.log(e.data); | |
return false; | |
} | |
return res.data.result; | |
} | |
// append new valset of chain | |
function appendSet(chain, set) { | |
Object.entries(set.validators).forEach(validator => { | |
const [address] = validator; | |
if (chain.valset_data.length == 0 || chain.valset_data[0].indexOf(address) == -1) { | |
chain.valset_data[0].push(address); | |
let len = chain.valset_data.length; | |
for (let i = 1; i < len; i++) { | |
chain.valset_data[i].push(0); | |
} | |
} | |
}); | |
let newRow = [set.height, set.sha256hash, set.total_vp]; | |
let len = chain.valset_data[0].length; | |
for (let i = 3; i < len; i++) { | |
Object.entries(set.validators).forEach(validator => { | |
const [address, voting_power] = validator; | |
if (chain.valset_data[0][i] == address) { | |
newRow[i] = parseFloat(voting_power); | |
} | |
else { | |
if (Object.keys(set.validators).indexOf(chain.valset_data[0][i]) == -1) { | |
newRow[i] = 0; | |
} | |
} | |
}); | |
} | |
chain.valset_data.push(newRow); | |
console.log('> new set: ' + chain.id + ' | height: ' + set.height + ' | valset_hash: ' + set.sha256hash); | |
return; | |
} | |
function completeSet(valset, height) { | |
let valset_export = []; | |
let total_vp = 0; | |
let complete_set = { | |
"validators": {} | |
}; | |
valset.forEach((validator) => { | |
valset_export.push(validator.address, validator.voting_power); | |
complete_set.validators[validator.address] = validator.voting_power; | |
total_vp = total_vp + parseFloat(validator.voting_power); | |
}); | |
complete_set.total_vp = total_vp; | |
complete_set.height = height; | |
complete_set.sha256hash = hash(valset_export.toString()); | |
return complete_set; | |
} | |
// fetch new valset | |
async function fetchNewValset(chain) { | |
let res = await fetchLatestValset(chain); | |
let height = res.block_height; | |
if (height > chain.last_height) { | |
console.log(chain.id + ' block: ' + res.block_height) | |
let valset = res.validators; | |
let complete_set = completeSet(valset, height); | |
chain.last_height = height; | |
return complete_set; | |
} | |
return false; | |
} | |
async function alertAndDumpSet(cc_new_set) { | |
// alert log | |
console.log('> DIFFERING VALSETS DETECTED!') | |
console.log('PC height: ' + provider.last_height); | |
console.log('CC height: ' + cc_new_set.height); | |
console.log('CC set ' + cc_new_set.sha256hash + ' not found in historic valsets of ' + provider.id + ' !') | |
console.log('CC dumping ' + consumer.id + ' set'); | |
console.log(JSON.stringify(cc_new_set.valset)); | |
// save valset to disk | |
dumpValsetRecords; | |
return true; | |
} | |
// poll lcd every 1s and check for new blocks/valsets | |
async function compareLiveValsets() { | |
let pc_new_set = await fetchNewValset(provider); | |
let cc_new_set = await fetchNewValset(consumer); | |
if (pc_new_set) { | |
if (isUniqueHash(provider, pc_new_set.sha256hash)) { | |
appendSet(provider, pc_new_set); | |
} | |
} | |
if (cc_new_set) { | |
if (isUniqueHash(consumer, cc_new_set.sha256hash)) { | |
appendSet(consumer, cc_new_set); | |
} | |
if (isUniqueHash(provider, cc_new_set.sha256hash)) { | |
alertAndDumpSet(cc_new_set); | |
} | |
} | |
return; | |
} | |
function isUniqueHash(chain, hash) { | |
let len = chain.valset_data.length; | |
let unique_hash = true; | |
for (var i = 0; i < len; i++) { | |
if (chain.valset_data[i][1] == hash) { | |
unique_hash = false; | |
} | |
} | |
return unique_hash; | |
} | |
// fetch historic valsets of PC | |
async function fetchHistoricValsets(chain) { | |
console.log("fetching historic valsets for chain " + chain.id + "...") | |
let block = chain.start_height; | |
let res = await fetchLatestValset(chain); | |
let last_block = res.block_height; | |
while (block <= last_block) { | |
if (block == last_block) { | |
res = await fetchLatestValset(chain); | |
if (res) { | |
last_block = res.block_height; | |
} | |
} | |
try { | |
res = await axios.get(chain.lcd + '/validatorsets/' + block); | |
} | |
catch (e) { | |
console.log(e.data); | |
return; | |
} | |
if (res) { | |
res = res.data.result; | |
let valset = res.validators; | |
let complete_set = completeSet(valset, block); | |
let unique_hash = isUniqueHash(chain, complete_set.sha256hash); | |
if (unique_hash == true) { | |
console.log('new set! height ' + block) | |
appendSet(chain, complete_set); | |
} | |
console.log("fetched " + chain.id + " block " + block); | |
// compare CC blocks | |
if (chain.id == consumer.id) { | |
let unique_hash = isUniqueHash(provider, complete_set.sha256hash); | |
if (unique_hash) { | |
await alertAndDumpSet(complete_set); | |
} | |
} | |
chain.last_height = block; | |
block++; | |
} | |
} | |
return; | |
} | |
async function main() { | |
// compare all historic valsets | |
await fetchHistoricValsets(provider); | |
await fetchHistoricValsets(consumer); | |
// save historic valset records to disk | |
dumpValsetRecords() | |
// compare live valsets | |
setInterval(compareLiveValsets, 1000); | |
compareLiveValsets(); | |
return; | |
} | |
main(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
**[EDIT 2022/11/16] code updated, differing valset theory below falsified with updated script! Gist depracted in favour of https://github.com/clemensgg/game-of-chains/** | |
### | |
PC: provider | |
CC: sputnik | |
> DIFFERING VALSETS DETECTED! | |
CC set 2665be94be5c98455ae6d196f4459f53b0722164e92121b13ecdb550278bb299 not found in last 100 blocks of PC! | |
PC height: 57206 | |
CC height: 3785 | |
dumping CONSUMER valset... | |
["cosmosvalcons1dg72e6h2tpkf4uc9zfyadle5js5rthcs892vnj","670100004","cosmosvalcons1pk34jc9vww287s2ef8k6lzz7r2dpscms7af6ny","784","cosmosvalcons1nyquekjzh9ywmhyrt76u32cxwv9fcg7dxprygj","427","cosmosvalcons172wrmvq0w0m4mp9hmlw80pal0z53c65punhf2k","310","cosmosvalcons15w5mjufgd8ezfa83709nmews88tzdrepugw2jd","300","cosmosvalcons1kke43d43wpfw9cdqpw8d0qf8ll0ltp90a4jpja","93","cosmosvalcons1e5x6sh63qdz74m9h8thddc7zceddyljnhkcdsu","39","cosmosvalcons1dkw3fgnjnwjlq2hjqw46l4wws2zd6fns063eyq","31","cosmosvalcons1z5q6n9hd24mlcew407f2ej8ptnnt0haddknugk","26","cosmosvalcons1lj2q9l6t2wutwf3yclaj3h0yj7t7736t09d42h","25","cosmosvalcons1yna32lcuhtjkq7f4nsnp9ln8wykwjepxhxsr5g","23","cosmosvalcons123zrau6pyk7mma6d3c0armpc2utqau7vm88u9x","19","cosmosvalcons1zq7v8lz7jrqyacsgh5r3dhygj4ffymhckysvw6","18","cosmosvalcons1ual79gxh0p8eeet46d0sn7an8wc9ej0t2hav6n","18","cosmosvalcons16hf7ktj7yds8sta04d7qk0z9hla3tpatsd0vf5","17","cosmosvalcons1lx9nq9909u49ezzjyc7ktg9k08ahnxuvhsj2ym","17","cosmosvalcons18wv3ddgpc5lrsq2kwc5z798z4tcztak9yny2x5","16","cosmosvalcons13feufd67xc8lrydcgjnphzz95zkkt5sgwkzccn","16","cosmosvalcons12freezz7w0f02ux50e0sgvmc2pgn2rw3pukgsc","15","cosmosvalcons1jh3lz46dmdgr7quqmx9fwmsvlprfhp60x8aaer","11","cosmosvalcons1qqlx7730mz96503pz729vu07pkv5u9ca85dhwe","10","cosmosvalcons1qwzmrx23fayrsudhhqq6jgal2wthk2gklq43vd","10","cosmosvalcons1q04tlwzqn38k9fej50tj3t929cf5q06s37z0y8","10","cosmosvalcons1q4ht5pn0kc64le4crl0nwhqumh6maw7x37696r","10","cosmosvalcons1pw8cra4g934nwzxkrykz45d4xgy7qnmvvtuaqt","10","cosmosvalcons1ze39xyf4t3ye8ldxn5scsaw2adur7ek4tt5jmp","10","cosmosvalcons1rljsrflyeuzf3we6kghkf4qjeqflsygepnzl53","10","cosmosvalcons1y022gjzdfkrggfekjzyvf59zu4k64ar98aau5k","10","cosmosvalcons19y4nwy0ygg7z73ahhevt7uh090g8wr8sgv6n2l","10","cosmosvalcons1xpgp8n9xnpnd49pzv4jf6444048j23wvtsnvak","10","cosmosvalcons1xhfftsd6wxx6jxl7xsdv8hsfk7txjgwf73uq6q","10","cosmosvalcons1xc0aszah3y7yksgy6rt63jf37d3dzuxcr8s59x","10","cosmosvalcons184pytrwcz8yjrndz5zq0kqvvhw3tj88a90hv5m","10","cosmosvalcons1gx49m7vtmw9gpxu4dfujtnepl2g96zxasea2j9","10","cosmosvalcons1g2ysa6n7nvpgjps9zdf4dkgtvse6ga6f6kmepz","10","cosmosvalcons1g4zw77yzsh34sfkm9rkx9ltsg42vcu2kgt95gy","10","cosmosvalcons1f4hpdclhmz0gmqulw95f844plqwfl9td6qcqym","10","cosmosvalcons12t4pcfx6jnr84rld03rwrzsul3rk64che77jfz","10","cosmosvalcons12h4v7ms5wfhp87tnjqmpgzrcvaqymuk2v49c7q","10","cosmosvalcons12lfvpusgm69kq0dxexm4ek2uxfvhhc6grdxfa8","10","cosmosvalcons1t8xflpfzx4rnmatmemehcc8n52wmx6q3g4mxch","10","cosmosvalcons1tg3gv86h7y5znd52qghmsptgtf89s5xre3edlr","10","cosmosvalcons1t0kswnadw2e5rh3xksmz3uh7pyt6c8trcfwe5k","10","cosmosvalcons1thhlg48txpsclg4e0rvl78yt2ge3ruw3utwd7q","10","cosmosvalcons1vr0ajahfkaytrc0sdltmdqy6xu9a8gcz76c48z","10","cosmosvalcons1v5v9hsn4awfr9gkl7ga7kn42qada457w83pqdz","10","cosmosvalcons1v6zrud945rxq6nl6eexf9rfqqafafwwnx57rvy","10","cosmosvalcons1vuwq3w64c8py9hz6xs5gnnvvqpccj0lesm3u0k","10","cosmosvalcons1w86lpg205h9gsy32yetfkrp6nc7xuh90dz5uy3","10","cosmosvalcons1wns96l4057a75jez52hlhvw2d7t5wze4ke90cz","10","cosmosvalcons1wmvevar5kc5rtecr54m3q8gl6d0cf5mt29jcy9","10","cosmosvalcons108aypezdajecj03kg66c4gfu0l5f3053x392lf","10","cosmosvalcons10f4xx96k72eypj7l4qwlv4x6hfvecrenl09tsx","10","cosmosvalcons10f6wkg5ckfkvnucvr35z5hqdugy7ud58rfsxmn","10","cosmosvalcons10vx7jlqg9tnezxfgqp873v294g0l2cpchuw6qc","10","cosmosvalcons10crq9qa7gp8paqxwwwxae3kp970duqgn0s9qcc","10","cosmosvalcons10m4u3cyxmdj98ame2nzye9xkldhs5cj7jm6yq5","10","cosmosvalcons1s7kc8tyvsj47tkyfpexlusrlz77dg26wmvt0hx","10","cosmosvalcons1sl5j5snqwqts3ru9qc0zqunmu08lvxvekpj2mt","10","cosmosvalcons133lxdszpdgqzel834x0c3uelej84nx2yhrey5d","10","cosmosvalcons13aa4rs0g2g8qh75ffmvryylyth43pc2kgmgdpf","10","cosmosvalcons1j6yyhc5af53347us6q68fq5x65dxh62rym9aq5","10","cosmosvalcons1jur4mxvvz9m3kw925zk0hl0snmks0z7fwmlc9x","10","cosmosvalcons1j7t42uegq7dm85l93rddsulsafkqnrqsnjtf5s","10","cosmosvalcons1nqz3a6w3zxpx6zsrh0wsxdx8cfr0c33k38lk8e","10","cosmosvalcons1nd2fpxeephw7tmqpgymrq3gvjpzwlr3wvjttu6","10","cosmosvalcons1njrm0dasu7d5h6qawtrtdrm3y27tqnhv0vxdyc","10","cosmosvalcons15xu5spj4r5j63wwyk4gwhmq7nvvkzx348krpn6","10","cosmosvalcons15t3h8hqgjj7qe584c75weu30r70g74tep3yuta","10","cosmosvalcons14fm6gslcf9sx5j5wk93ew5sx3sdza6j7vr96r4","10","cosmosvalcons14knt8vk78wexsmd7792rcvyazrfraskv6hpm2t","10","cosmosvalcons1k3m4krltmlsz84hzgaytm59nn7pkd2xaygdpj0","10","cosmosvalcons1kkdkxvcl6gfqezdl9e7av4l8lx4qjzsaj380nf","10","cosmosvalcons1ht8qrurx6lpngj4pjns6rdhm7mlga0suun8jwk","10","cosmosvalcons1hexe6e6hnk0fan7n9vu6kt40nz86022kmyg9qp","10","cosmosvalcons1cq35fan5z5r5csl2rddjqclun93jn3hpxh2v0g","10","cosmosvalcons1csa5vmvu8fsgtxmx5j8qk4xxv278q8a4pce87v","10","cosmosvalcons1cave3x44qrklv2wyemgjvl9rpanquspyeqvk4m","10","cosmosvalcons1eszcs2tcl30a66nhy958u9xq9xdwqp9c65dnm6","10","cosmosvalcons1ek3cslf0ppj7sjavnjpyr494luu4j8fgdf6n8d","10","cosmosvalcons16q4jna57d07rufql8qtzaqhwf3ud3hdf5yt3y2","10","cosmosvalcons16p3evw80wdns6jqna8grfazfjenm80n7cle8kj","10","cosmosvalcons1635xssr82smqqr5mxwu2tqvnh9qx4hdresz7fw","10","cosmosvalcons16etd37wqd3h3209pwf7w86ast0c4vapcvf349n","10","cosmosvalcons1m9zg6xjs0g8hjtp97nl2uqwah3r53j5z6a9ppw","10","cosmosvalcons1md008gt5q9z3tgzxaq8rze8zys2pyds596lfv6","10","cosmosvalcons1msqd5pywcs9l99fsvfnqrpqtrr6g4j99uqmckk","10","cosmosvalcons1uykcdtp8jfvuhvxvr5k9m206mcla35j09s3q49","10","cosmosvalcons1uxjga5twkestune9nc8r5c4chet0g83kdf7u68","10","cosmosvalcons1uc6e0cl5duageq3hnfedxl7h62qwsvh6ppkgc4","10","cosmosvalcons1aegqgn27upl69skvjnc6s8ftdkkuzqlt46r6tg","10","cosmosvalcons17m4ucgq6q5wzzp4x7rxetfzjeppm5nc5f9nc32","10","cosmosvalcons1lhnmnmd9arv33wsyyd06xp928n5zcpxp4t8k0t","10","cosmosvalcons1y9r49naje4wtqrkxy4eecgj25srzymgw8k5ywt","9","cosmosvalcons1efueez5q0x6m4sruhnmhe9x2q5xtfjuqazpjhc","5"] | |
dumping last PROVIDER valset... | |
["cosmosvalcons1dg72e6h2tpkf4uc9zfyadle5js5rthcs892vnj","670100004","cosmosvalcons1pk34jc9vww287s2ef8k6lzz7r2dpscms7af6ny","784","cosmosvalcons1nyquekjzh9ywmhyrt76u32cxwv9fcg7dxprygj","427","cosmosvalcons172wrmvq0w0m4mp9hmlw80pal0z53c65punhf2k","310","cosmosvalcons15w5mjufgd8ezfa83709nmews88tzdrepugw2jd","300","cosmosvalcons1kke43d43wpfw9cdqpw8d0qf8ll0ltp90a4jpja","93","cosmosvalcons1e5x6sh63qdz74m9h8thddc7zceddyljnhkcdsu","39","cosmosvalcons1dkw3fgnjnwjlq2hjqw46l4wws2zd6fns063eyq","31","cosmosvalcons1z5q6n9hd24mlcew407f2ej8ptnnt0haddknugk","26","cosmosvalcons1lj2q9l6t2wutwf3yclaj3h0yj7t7736t09d42h","25","cosmosvalcons1yna32lcuhtjkq7f4nsnp9ln8wykwjepxhxsr5g","23","cosmosvalcons123zrau6pyk7mma6d3c0armpc2utqau7vm88u9x","19","cosmosvalcons1zq7v8lz7jrqyacsgh5r3dhygj4ffymhckysvw6","18","cosmosvalcons1ual79gxh0p8eeet46d0sn7an8wc9ej0t2hav6n","18","cosmosvalcons16hf7ktj7yds8sta04d7qk0z9hla3tpatsd0vf5","17","cosmosvalcons1lx9nq9909u49ezzjyc7ktg9k08ahnxuvhsj2ym","17","cosmosvalcons18wv3ddgpc5lrsq2kwc5z798z4tcztak9yny2x5","16","cosmosvalcons13feufd67xc8lrydcgjnphzz95zkkt5sgwkzccn","16","cosmosvalcons12freezz7w0f02ux50e0sgvmc2pgn2rw3pukgsc","15","cosmosvalcons1jh3lz46dmdgr7quqmx9fwmsvlprfhp60x8aaer","11","cosmosvalcons1qqlx7730mz96503pz729vu07pkv5u9ca85dhwe","10","cosmosvalcons1qwzmrx23fayrsudhhqq6jgal2wthk2gklq43vd","10","cosmosvalcons1q04tlwzqn38k9fej50tj3t929cf5q06s37z0y8","10","cosmosvalcons1q4ht5pn0kc64le4crl0nwhqumh6maw7x37696r","10","cosmosvalcons1pw8cra4g934nwzxkrykz45d4xgy7qnmvvtuaqt","10","cosmosvalcons1ze39xyf4t3ye8ldxn5scsaw2adur7ek4tt5jmp","10","cosmosvalcons1rljsrflyeuzf3we6kghkf4qjeqflsygepnzl53","10","cosmosvalcons1y022gjzdfkrggfekjzyvf59zu4k64ar98aau5k","10","cosmosvalcons19y4nwy0ygg7z73ahhevt7uh090g8wr8sgv6n2l","10","cosmosvalcons1xpgp8n9xnpnd49pzv4jf6444048j23wvtsnvak","10","cosmosvalcons1xhfftsd6wxx6jxl7xsdv8hsfk7txjgwf73uq6q","10","cosmosvalcons1xc0aszah3y7yksgy6rt63jf37d3dzuxcr8s59x","10","cosmosvalcons184pytrwcz8yjrndz5zq0kqvvhw3tj88a90hv5m","10","cosmosvalcons1gx49m7vtmw9gpxu4dfujtnepl2g96zxasea2j9","10","cosmosvalcons1g2ysa6n7nvpgjps9zdf4dkgtvse6ga6f6kmepz","10","cosmosvalcons1g4zw77yzsh34sfkm9rkx9ltsg42vcu2kgt95gy","10","cosmosvalcons1f4hpdclhmz0gmqulw95f844plqwfl9td6qcqym","10","cosmosvalcons12t4pcfx6jnr84rld03rwrzsul3rk64che77jfz","10","cosmosvalcons12h4v7ms5wfhp87tnjqmpgzrcvaqymuk2v49c7q","10","cosmosvalcons12lfvpusgm69kq0dxexm4ek2uxfvhhc6grdxfa8","10","cosmosvalcons1t8xflpfzx4rnmatmemehcc8n52wmx6q3g4mxch","10","cosmosvalcons1tg3gv86h7y5znd52qghmsptgtf89s5xre3edlr","10","cosmosvalcons1t0kswnadw2e5rh3xksmz3uh7pyt6c8trcfwe5k","10","cosmosvalcons1thhlg48txpsclg4e0rvl78yt2ge3ruw3utwd7q","10","cosmosvalcons1vr0ajahfkaytrc0sdltmdqy6xu9a8gcz76c48z","10","cosmosvalcons1v5v9hsn4awfr9gkl7ga7kn42qada457w83pqdz","10","cosmosvalcons1v6zrud945rxq6nl6eexf9rfqqafafwwnx57rvy","10","cosmosvalcons1vuwq3w64c8py9hz6xs5gnnvvqpccj0lesm3u0k","10","cosmosvalcons1w86lpg205h9gsy32yetfkrp6nc7xuh90dz5uy3","10","cosmosvalcons1wns96l4057a75jez52hlhvw2d7t5wze4ke90cz","10","cosmosvalcons1wmvevar5kc5rtecr54m3q8gl6d0cf5mt29jcy9","10","cosmosvalcons108aypezdajecj03kg66c4gfu0l5f3053x392lf","10","cosmosvalcons10f4xx96k72eypj7l4qwlv4x6hfvecrenl09tsx","10","cosmosvalcons10f6wkg5ckfkvnucvr35z5hqdugy7ud58rfsxmn","10","cosmosvalcons10vx7jlqg9tnezxfgqp873v294g0l2cpchuw6qc","10","cosmosvalcons10crq9qa7gp8paqxwwwxae3kp970duqgn0s9qcc","10","cosmosvalcons10m4u3cyxmdj98ame2nzye9xkldhs5cj7jm6yq5","10","cosmosvalcons1s7kc8tyvsj47tkyfpexlusrlz77dg26wmvt0hx","10","cosmosvalcons1sl5j5snqwqts3ru9qc0zqunmu08lvxvekpj2mt","10","cosmosvalcons133lxdszpdgqzel834x0c3uelej84nx2yhrey5d","10","cosmosvalcons13aa4rs0g2g8qh75ffmvryylyth43pc2kgmgdpf","10","cosmosvalcons1j6yyhc5af53347us6q68fq5x65dxh62rym9aq5","10","cosmosvalcons1jur4mxvvz9m3kw925zk0hl0snmks0z7fwmlc9x","10","cosmosvalcons1j7t42uegq7dm85l93rddsulsafkqnrqsnjtf5s","10","cosmosvalcons1nqz3a6w3zxpx6zsrh0wsxdx8cfr0c33k38lk8e","10","cosmosvalcons1nd2fpxeephw7tmqpgymrq3gvjpzwlr3wvjttu6","10","cosmosvalcons1njrm0dasu7d5h6qawtrtdrm3y27tqnhv0vxdyc","10","cosmosvalcons15xu5spj4r5j63wwyk4gwhmq7nvvkzx348krpn6","10","cosmosvalcons15t3h8hqgjj7qe584c75weu30r70g74tep3yuta","10","cosmosvalcons14fm6gslcf9sx5j5wk93ew5sx3sdza6j7vr96r4","10","cosmosvalcons14knt8vk78wexsmd7792rcvyazrfraskv6hpm2t","10","cosmosvalcons1k3m4krltmlsz84hzgaytm59nn7pkd2xaygdpj0","10","cosmosvalcons1kkdkxvcl6gfqezdl9e7av4l8lx4qjzsaj380nf","10","cosmosvalcons1ht8qrurx6lpngj4pjns6rdhm7mlga0suun8jwk","10","cosmosvalcons1hexe6e6hnk0fan7n9vu6kt40nz86022kmyg9qp","10","cosmosvalcons1cq35fan5z5r5csl2rddjqclun93jn3hpxh2v0g","10","cosmosvalcons1csa5vmvu8fsgtxmx5j8qk4xxv278q8a4pce87v","10","cosmosvalcons1cave3x44qrklv2wyemgjvl9rpanquspyeqvk4m","10","cosmosvalcons1efueez5q0x6m4sruhnmhe9x2q5xtfjuqazpjhc","10","cosmosvalcons1eszcs2tcl30a66nhy958u9xq9xdwqp9c65dnm6","10","cosmosvalcons1ek3cslf0ppj7sjavnjpyr494luu4j8fgdf6n8d","10","cosmosvalcons16q4jna57d07rufql8qtzaqhwf3ud3hdf5yt3y2","10","cosmosvalcons16p3evw80wdns6jqna8grfazfjenm80n7cle8kj","10","cosmosvalcons1635xssr82smqqr5mxwu2tqvnh9qx4hdresz7fw","10","cosmosvalcons16etd37wqd3h3209pwf7w86ast0c4vapcvf349n","10","cosmosvalcons1m9zg6xjs0g8hjtp97nl2uqwah3r53j5z6a9ppw","10","cosmosvalcons1md008gt5q9z3tgzxaq8rze8zys2pyds596lfv6","10","cosmosvalcons1msqd5pywcs9l99fsvfnqrpqtrr6g4j99uqmckk","10","cosmosvalcons1uykcdtp8jfvuhvxvr5k9m206mcla35j09s3q49","10","cosmosvalcons1uxjga5twkestune9nc8r5c4chet0g83kdf7u68","10","cosmosvalcons1uc6e0cl5duageq3hnfedxl7h62qwsvh6ppkgc4","10","cosmosvalcons1aegqgn27upl69skvjnc6s8ftdkkuzqlt46r6tg","10","cosmosvalcons17m4ucgq6q5wzzp4x7rxetfzjeppm5nc5f9nc32","10","cosmosvalcons1lhnmnmd9arv33wsyyd06xp928n5zcpxp4t8k0t","10","cosmosvalcons1y9r49naje4wtqrkxy4eecgj25srzymgw8k5ywt","9"] | |
### |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Gist depcrated in favor of https://github.com/clemensgg/game-of-chains