mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-utils.git
synced 2026-11-05 08:41:07 +00:00
Add light client chain specifications for Zagros (#78)
light-client/zagros.json and light-client/people-zagros.json are what the wallet's embedded light client starts from. The full specifications carry the raw genesis storage, about 3 MB each. These carry only the genesis state root, which identifies the chain: - The relay specification adds a checkpoint (lightSyncState) exported by the relay node through sync_state_genSyncSpec. It is 7.3 KB. - People has no checkpoint, because the relay chain's finality covers it. It is 732 bytes. Boot nodes put the /wss addresses on 443 first and keep the plain TCP ones. scripts/light_client_specs.py writes both files. It checks every state root by rebuilding the genesis header and comparing its hash with the chain's genesis hash. A root with one byte changed is refused. The checkpoint is a trust anchor: a client that starts from a false one can follow a false chain. It reaches the wallet inside the APK or through signed/targets.json, never from peers. Targets are re-signed (version 3, 689 files). The secret scan lets through the four public chain-data keys these files carry: stateRootHash, finalizedBlockHeader, babeEpochChanges and grandpaAuthoritySet.
This commit is contained in:
1 parent
07aa8b3dd0
commit
eb00e49a52
5 files changed
+171
-4
No files matched your search
@@ -57,8 +57,10 @@ jobs:
|
||||
FOUND=0
|
||||
|
||||
echo "Checking for private keys in config files..."
|
||||
# "account" fields hold public 32-byte account IDs (balance-test fixtures), not private keys
|
||||
if grep -rn --include="*.json" --include="*.py" -E "(0x[a-fA-F0-9]{64}|-----BEGIN.*PRIVATE)" . | grep -v node_modules | grep -v "chainId\|genesisHash\|parentId\|currencyIdScale\|typeAlias\|signedExtensions\|\"account\":"; then
|
||||
# "account" fields hold public 32-byte account IDs (balance-test fixtures), not private keys.
|
||||
# The light client specifications carry public chain data: the genesis state root and the
|
||||
# relay chain checkpoint (an encoded finalized header, BABE epochs, GRANDPA authorities).
|
||||
if grep -rn --include="*.json" --include="*.py" -E "(0x[a-fA-F0-9]{64}|-----BEGIN.*PRIVATE)" . | grep -v node_modules | grep -v "chainId\|genesisHash\|parentId\|currencyIdScale\|typeAlias\|signedExtensions\|\"account\":\|\"stateRootHash\":\|\"finalizedBlockHeader\":\|\"babeEpochChanges\":\|\"grandpaAuthoritySet\":"; then
|
||||
echo "::error::Possible private key found"
|
||||
FOUND=1
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"bootNodes": [
|
||||
"/dns/zagros-people-bootnode.pezkuwichain.io/tcp/443/wss/p2p/12D3KooWLnDS5p5bvMzfco2BR4arKRbtpqoZwRvLKgCdzgVpuEQG",
|
||||
"/ip4/217.77.6.126/tcp/30535/p2p/12D3KooWLnDS5p5bvMzfco2BR4arKRbtpqoZwRvLKgCdzgVpuEQG",
|
||||
"/ip4/164.68.110.49/tcp/30535/p2p/12D3KooW9rHfLv4za95C4fPGTUzNk531zRrjaXYJY3pijMEYd3xB"
|
||||
],
|
||||
"chainType": "Live",
|
||||
"codeSubstitutes": {},
|
||||
"genesis": {
|
||||
"stateRootHash": "0xcaffff9ce4cf02e84a963a8b2ff27834f4d2385a1dc3b01a23551da8515d6c98"
|
||||
},
|
||||
"id": "people-zagros",
|
||||
"name": "Zagros People",
|
||||
"para_id": 1004,
|
||||
"properties": {
|
||||
"ss58Format": 42,
|
||||
"tokenDecimals": 12,
|
||||
"tokenSymbol": "HEZ"
|
||||
},
|
||||
"protocolId": null,
|
||||
"relay_chain": "zagros",
|
||||
"telemetryEndpoints": null
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"badBlocks": null,
|
||||
"bootNodes": [
|
||||
"/dns/zagros-bootnode-0.pezkuwichain.io/tcp/443/wss/p2p/12D3KooWHKMr39ubvsigZXdVJzr7nnMp5YTzMywKuTzPDo3Xf1tZ",
|
||||
"/dns/zagros-bootnode-1.pezkuwichain.io/tcp/443/wss/p2p/12D3KooWH6tzPuoFeyf8n6gNmus9Q3CdEGEVUvbduUnPTqJcLRLC",
|
||||
"/dns/zagros-bootnode-0.pezkuwichain.io/tcp/30333/p2p/12D3KooWHKMr39ubvsigZXdVJzr7nnMp5YTzMywKuTzPDo3Xf1tZ",
|
||||
"/dns/zagros-bootnode-1.pezkuwichain.io/tcp/30333/p2p/12D3KooWH6tzPuoFeyf8n6gNmus9Q3CdEGEVUvbduUnPTqJcLRLC"
|
||||
],
|
||||
"chainType": "Live",
|
||||
"codeSubstitutes": {},
|
||||
"forkBlocks": null,
|
||||
"genesis": {
|
||||
"stateRootHash": "0xf34e48ee64d91316874ccb2186a111d4c5b4ff5f07a302472eb781929a42996f"
|
||||
},
|
||||
"id": "zagros",
|
||||
"lightSyncState": {
|
||||
"babeEpochChanges": "0x0484e33c00890c931035c417885ef185862d12f8e5ef1a1b2697b79d3040a6a17689300800017076d11100000000c878d1110000000004b787118322f0bc70ea799cf7970ea9af917ab3573264d58c3b90ad0cde3848358432080001c878d11100000000207bd1110000000004c1317066f50e2ad43e0b2f892dfdaa7a8148aee518235774a71ec528c26a780e7a34080001207bd11100000000787dd1110000000000000c84e33c00890c931035c417885ef185862d12f8e5ef1a1b2697b79d3040a6a176893008000193030000000000007076d1110000000058020000000000003822a5e0172444e42a1ea3e29830c83a6e0a84a33263cfe2a7008871b001a8e74b0100000000000000507fc640a1bb08b2e118846de14705579dfe58672cf38f21db5752926acd94170100000000000000ac680114b0cf7808f05deeddebd067ed520eb71f9dccca4d3290a91760950e740100000000000000620f7e55a0af1d74edfd807d77e2f125ed28a1fcd865699da5897e6cf7d8e93a01000000000000004e4977fb1f2802b5c49b59b0154ac8f5f888bb72d91a21b0b84cb896a900ff5401000000000000000c5c662c5202d3791ea8d5a19f8121d2422790dbe46420eb83d6f12d90fb6f670100000000000000c015d853b41e00914525c852fc89bad17ed90a8df1a6be9bd7e945967e59de6e01000000000000008c54eb78ec5f530317c3f74ec43e3c0d14460755377b147be26f6e25ace5f03d01000000000000002c6fd021135a0de764bd7a26bad6b5a329c00d3195182f2f29e1694b4e46ab3901000000000000006896d03c0d08da73257a98332f418dbd84dedb10515a6cb20608b065953b833f01000000000000003a35ad97f29553dbf45438c7aabb1c6703cda4edfe31a6d8e97d75e77c7e625801000000000000001e307845454d1930a44728d3a4b0c3a8a796ca7864f02337506d95bbba23a64d010000000000000026f1a959083449c89877ab91a027133806ea41a7363dccd66b751c4f31b3ab1a0100000000000000f2e648c3df9281cbe3514b6a4c244a4d3d10bcf6dcd9aa8446149d8fe5cf821a01000000000000002167c0d326e6ac3175ddecf4616bba618737717364abbc103bca86e056b1e4f30100000000000000040000000000000002b787118322f0bc70ea799cf7970ea9af917ab3573264d58c3b90ad0cde38483584320800019403000000000000c878d1110000000058020000000000003822a5e0172444e42a1ea3e29830c83a6e0a84a33263cfe2a7008871b001a8e74b0100000000000000507fc640a1bb08b2e118846de14705579dfe58672cf38f21db5752926acd94170100000000000000ac680114b0cf7808f05deeddebd067ed520eb71f9dccca4d3290a91760950e740100000000000000620f7e55a0af1d74edfd807d77e2f125ed28a1fcd865699da5897e6cf7d8e93a01000000000000004e4977fb1f2802b5c49b59b0154ac8f5f888bb72d91a21b0b84cb896a900ff5401000000000000000c5c662c5202d3791ea8d5a19f8121d2422790dbe46420eb83d6f12d90fb6f670100000000000000c015d853b41e00914525c852fc89bad17ed90a8df1a6be9bd7e945967e59de6e01000000000000008c54eb78ec5f530317c3f74ec43e3c0d14460755377b147be26f6e25ace5f03d01000000000000002c6fd021135a0de764bd7a26bad6b5a329c00d3195182f2f29e1694b4e46ab3901000000000000006896d03c0d08da73257a98332f418dbd84dedb10515a6cb20608b065953b833f01000000000000003a35ad97f29553dbf45438c7aabb1c6703cda4edfe31a6d8e97d75e77c7e625801000000000000001e307845454d1930a44728d3a4b0c3a8a796ca7864f02337506d95bbba23a64d010000000000000026f1a959083449c89877ab91a027133806ea41a7363dccd66b751c4f31b3ab1a0100000000000000f2e648c3df9281cbe3514b6a4c244a4d3d10bcf6dcd9aa8446149d8fe5cf821a01000000000000005e6e1acac124ee50f061c35e668f888f6bb3d51af94aeaad312bd3052ea797c50100000000000000040000000000000002c1317066f50e2ad43e0b2f892dfdaa7a8148aee518235774a71ec528c26a780e7a340800019503000000000000207bd1110000000058020000000000003822a5e0172444e42a1ea3e29830c83a6e0a84a33263cfe2a7008871b001a8e74b0100000000000000507fc640a1bb08b2e118846de14705579dfe58672cf38f21db5752926acd94170100000000000000ac680114b0cf7808f05deeddebd067ed520eb71f9dccca4d3290a91760950e740100000000000000620f7e55a0af1d74edfd807d77e2f125ed28a1fcd865699da5897e6cf7d8e93a01000000000000004e4977fb1f2802b5c49b59b0154ac8f5f888bb72d91a21b0b84cb896a900ff5401000000000000000c5c662c5202d3791ea8d5a19f8121d2422790dbe46420eb83d6f12d90fb6f670100000000000000c015d853b41e00914525c852fc89bad17ed90a8df1a6be9bd7e945967e59de6e01000000000000008c54eb78ec5f530317c3f74ec43e3c0d14460755377b147be26f6e25ace5f03d01000000000000002c6fd021135a0de764bd7a26bad6b5a329c00d3195182f2f29e1694b4e46ab3901000000000000006896d03c0d08da73257a98332f418dbd84dedb10515a6cb20608b065953b833f01000000000000003a35ad97f29553dbf45438c7aabb1c6703cda4edfe31a6d8e97d75e77c7e625801000000000000001e307845454d1930a44728d3a4b0c3a8a796ca7864f02337506d95bbba23a64d010000000000000026f1a959083449c89877ab91a027133806ea41a7363dccd66b751c4f31b3ab1a0100000000000000f2e648c3df9281cbe3514b6a4c244a4d3d10bcf6dcd9aa8446149d8fe5cf821a01000000000000004015e4d23a08bf3953729cdffed4287e49b959cfecf4a7056f4d725ab1d632ff0100000000000000040000000000000002",
|
||||
"babeFinalizedBlockWeight": 133663,
|
||||
"finalizedBlockHeader": "0x61d5374b2608eba8044eb6b53bbb1885f9b4f7435d748aafa3274569cb61d3fc2ed92000a7be66700b76965c09b6ed96afeee418e1ec074336b419a5466b02aa3cfc253139c855a50829b03d89a771899be7eba352bb5e73243665554fcdb7e2691cd9940c0642414245b501030d000000eb7ad11100000000f0c61d37049856397cf9983bf17937f7915b675985d6a1b76743ee86a4689b2a23036a92220bc8f2317ea673f22df1721c94e5592eab0e0e75001b3e9896580f3ba6422cae995ae9fcf59beecb51ead04b9795b515bfee87e7d65f745371470f04424545468403342ba73d049de92f20b1c8217bc2aedc3728da90c771056a18cd3804d002b2a705424142450101a68542e128a2b23d7d34f9d9a0bd190788be671a87ce8139d78c72eb3079cb6e5bfc31392d235d830802ccb35c8c64812ab64bda9c66adec99ce7df84b995781",
|
||||
"grandpaAuthoritySet": "0x38140ec6acc3d2ccfe8017c2b87a0dfe634c6de1104574059e3ba05cdbb6190f080100000000000000e78c542579cfcb4bf781268a57c7ae19abe426ed075f298f1ead033e901da882010000000000000047d1e266d0f8411dc03808acbaf330499c03a288f0dd80d0b7a558e1ee7b6e8f01000000000000001cee1e8b20ef554efaa29ac5a2c2418503df3a4449a769f3649a2add036bd38f01000000000000002600c4b144906b2dc3ba8aefca015a8532e5589b11b164439fb0b4fb004383aa01000000000000000d3be87d022659068339f82bb458976f83b7c75287b842a2dc179d556b34fbff01000000000000003e6aae6e3c55c25f0b6765818b513ccceac769d371a4bb401240282d251151e7010000000000000037cd7e2689782aa1d5f52ed24bd9c4bcf8f811effbefac2039a027a51f33a5950100000000000000b34d50cbb391e36f5820fe8d4c572b8c20e3b7ce82dfbdac08ac800b90554d4301000000000000000e96449f0667776ca4507b30fef3e4168f20da1acb0dd57e71ecca74d7e7ace50100000000000000c57688bc9175f1ea6e2cf7dd8a3593ca6b2764b1b78165c8e8c6b791f66b48a70100000000000000fb6f3bc5a49916d1917500d3ff1882c525f2d20d32f16d5429ec1595e05db18201000000000000007d4567a4100b9fd2db6d741a60aef2693f6ca1c875a588036ab2b7cd3d449b63010000000000000087f3c60d6f12aeee640840f82b9deb899d287dffc605a9a115d46dc84f4739b40100000000000000040000000000000000014b36080000100000000000000000d12a030001000000000000008d3d03000200000000000000ae6b05000300000000000000d68e0500"
|
||||
},
|
||||
"name": "Zagros",
|
||||
"properties": {
|
||||
"ss58Format": 42,
|
||||
"tokenDecimals": 12,
|
||||
"tokenSymbol": "HEZ"
|
||||
},
|
||||
"protocolId": null,
|
||||
"telemetryEndpoints": null
|
||||
}
|
||||
Executable
+112
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Chain specifications for the wallet's light client, written to light-client/.
|
||||
|
||||
The full specifications carry the raw genesis storage, about 3 MB each. The light client needs
|
||||
none of it: the genesis state root identifies the chain, and the relay chain starts from a
|
||||
checkpoint (lightSyncState) that the relay node exports with sync_state_genSyncSpec. What is
|
||||
written here is that trimmed form, with the boot nodes below.
|
||||
|
||||
The checkpoint is a trust anchor: a client that starts from a false one can follow a false
|
||||
chain. It is taken from our own relay node and reaches the wallet only inside the APK or through
|
||||
signed/targets.json, never from peers. Every state root is checked against its chain's genesis
|
||||
hash before anything is written.
|
||||
|
||||
light_client_specs.py --relay-rpc URL --people-rpc URL --people-spec FILE
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent
|
||||
OUT = REPO / "light-client"
|
||||
|
||||
# Secure WebSockets on 443 first: they look like any HTTPS WebSocket where plain libp2p TCP is
|
||||
# filtered. The TCP addresses stay for networks that filter nothing.
|
||||
ZAGROS_BOOT_NODES = [
|
||||
"/dns/zagros-bootnode-0.pezkuwichain.io/tcp/443/wss/p2p/12D3KooWHKMr39ubvsigZXdVJzr7nnMp5YTzMywKuTzPDo3Xf1tZ",
|
||||
"/dns/zagros-bootnode-1.pezkuwichain.io/tcp/443/wss/p2p/12D3KooWH6tzPuoFeyf8n6gNmus9Q3CdEGEVUvbduUnPTqJcLRLC",
|
||||
"/dns/zagros-bootnode-0.pezkuwichain.io/tcp/30333/p2p/12D3KooWHKMr39ubvsigZXdVJzr7nnMp5YTzMywKuTzPDo3Xf1tZ",
|
||||
"/dns/zagros-bootnode-1.pezkuwichain.io/tcp/30333/p2p/12D3KooWH6tzPuoFeyf8n6gNmus9Q3CdEGEVUvbduUnPTqJcLRLC",
|
||||
]
|
||||
PEOPLE_ZAGROS_BOOT_NODES = [
|
||||
"/dns/zagros-people-bootnode.pezkuwichain.io/tcp/443/wss/p2p/12D3KooWLnDS5p5bvMzfco2BR4arKRbtpqoZwRvLKgCdzgVpuEQG",
|
||||
"/ip4/217.77.6.126/tcp/30535/p2p/12D3KooWLnDS5p5bvMzfco2BR4arKRbtpqoZwRvLKgCdzgVpuEQG",
|
||||
"/ip4/164.68.110.49/tcp/30535/p2p/12D3KooW9rHfLv4za95C4fPGTUzNk531zRrjaXYJY3pijMEYd3xB",
|
||||
]
|
||||
|
||||
|
||||
def rpc(url: str, method: str, params: list):
|
||||
request = urllib.request.Request(
|
||||
url,
|
||||
json.dumps(
|
||||
{"jsonrpc": "2.0", "id": 1, "method": method, "params": params}
|
||||
).encode(),
|
||||
{"Content-Type": "application/json"},
|
||||
)
|
||||
with urllib.request.urlopen(request, timeout=120) as response:
|
||||
reply = json.load(response)
|
||||
if "error" in reply:
|
||||
sys.exit(f"{url} {method}: {reply['error']}")
|
||||
return reply["result"]
|
||||
|
||||
|
||||
def genesis_state_root(url: str) -> str:
|
||||
"""The genesis state root, checked by rebuilding the genesis header and hashing it."""
|
||||
genesis_hash = rpc(url, "chain_getBlockHash", [0])
|
||||
header = rpc(url, "chain_getHeader", [genesis_hash])
|
||||
if header["digest"]["logs"]:
|
||||
sys.exit(f"{url}: genesis header has digest logs; this check assumes none")
|
||||
encoded = (
|
||||
bytes(32) # parent hash
|
||||
+ b"\x00" # compact block number 0
|
||||
+ bytes.fromhex(header["stateRoot"][2:])
|
||||
+ bytes.fromhex(header["extrinsicsRoot"][2:])
|
||||
+ b"\x00" # empty digest
|
||||
)
|
||||
rebuilt = "0x" + hashlib.blake2b(encoded, digest_size=32).hexdigest()
|
||||
if rebuilt != genesis_hash:
|
||||
sys.exit(f"{url}: rebuilt genesis hash {rebuilt} is not {genesis_hash}")
|
||||
return header["stateRoot"]
|
||||
|
||||
|
||||
def write(name: str, spec: dict) -> None:
|
||||
path = OUT / name
|
||||
path.write_text(json.dumps(spec, indent=2) + "\n")
|
||||
print(f"{path.relative_to(REPO)}: {path.stat().st_size} bytes")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
||||
parser.add_argument("--relay-rpc", required=True)
|
||||
parser.add_argument("--people-rpc", required=True)
|
||||
parser.add_argument(
|
||||
"--people-spec", required=True, help="full People chain specification"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
OUT.mkdir(exist_ok=True)
|
||||
|
||||
relay = rpc(args.relay_rpc, "sync_state_genSyncSpec", [True])
|
||||
if not relay.get("lightSyncState"):
|
||||
sys.exit(f"{args.relay_rpc}: the exported specification has no checkpoint")
|
||||
relay["genesis"] = {"stateRootHash": genesis_state_root(args.relay_rpc)}
|
||||
relay["bootNodes"] = ZAGROS_BOOT_NODES
|
||||
|
||||
# Teyrchains have no checkpoint: the relay chain's finality covers them.
|
||||
people = json.loads(Path(args.people_spec).read_text())
|
||||
if people.get("relay_chain") != relay["id"]:
|
||||
sys.exit(
|
||||
f"People names relay chain {people.get('relay_chain')!r}, not {relay['id']!r}"
|
||||
)
|
||||
people["genesis"] = {"stateRootHash": genesis_state_root(args.people_rpc)}
|
||||
people["bootNodes"] = PEOPLE_ZAGROS_BOOT_NODES
|
||||
|
||||
write("zagros.json", relay)
|
||||
write("people-zagros.json", people)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"signed": "eyJleHBpcmVzIjoxODI1MDI5MzkzLCJmaWxlcyI6eyJhc3NldHMvZXZtL3YxL2Fzc2V0cy5qc29uIjoiYmI2ZjliYWNlMmY2Y2Q5NjBlMjYyM2Q5ZWE0MmM2OTE3MzUxOWQyZmE5YWVhNWRkMzEyNzA5Njc2ZWExMDdkYSIsImFzc2V0cy9ldm0vdjEvYXNzZXRzX2Rldi5qc29uIjoiNDJhMThhYTUxZTEwZmY0NjllOTYxMGJlMzNmOThkZjhlYWM5NjFhZTVmZDc2YWRhZTNmZThiNzhlZGVlYzIxNiIsImFzc2V0cy9ldm0vdjIvYXNzZXRzLmpzb24iOiJhZWNjZjRlZTE5ODhiOTI0OTRmMWZkZDBjYTI0OGYzYjlmYjE2NmFkZTAyNjRhM2IzZjRmYWYzZDc1MjhhYzBmIiwiYXNzZXRzL2V2bS92Mi9hc3NldHNfZGV2Lmpzb24iOiI2YmZlZDBmMzU2M2YxMDdkNDViZWM0ZjQ3MjYzYWUyYzMyMjA3ZjQ1ZGRhNmQwNmUxNDczNmFkNWM2OTYzYmYzIiwiYXNzZXRzL2V2bS92My9hc3NldHMuanNvbiI6ImM0NDc4NWRiOTkyZjE0NTA3NTFkY2FjOGI1MTVlOTg0NzRlYTA0YTMyZTE4MjgwYjBmOWEyNjNkNzNhM2RjYzUiLCJhc3NldHMvZXZtL3YzL2Fzc2V0c19kZXYuanNvbiI6ImUyMDc5Y2VjNTkxMGQ0NDE0MzBiNzc0ZmYxMjJkN2E2MGI1OTIwMDZlZjE3NmI4NDAzMTE2ZWMyMmM1YTYyNTEiLCJhc3NldHMvc2xpcDQ0Lmpzb24iOiI2MDAyM2IzN2MxMDE4NDdjNzJmMzZmMDVmNTJlNmE4Y2U0Mzk1NjU5ZDZhOTg0ZmE5YjMyYTFiMzlkYWJjODUwIiwiYmFubmVycy92Mi9jb250ZW50L2Fzc2V0cy9iYW5uZXJzLmpzb24iOiI1Yjg3NGMyZjdiNGE3YTJmZDY0Nzc2ZjVhNDI4YTljMTUzMTJjZmNjZDUyMmNlZDRjZjkzMjYxNjFjOTFiZWNiIiwiYmFubmVycy92Mi9jb250ZW50L2Fzc2V0cy9iYW5uZXJzX2Rldi5qc29uIjoiNWI4NzRjMmY3YjRhN2EyZmQ2NDc3NmY1YTQyOGE5YzE1MzEyY2ZjY2Q1MjJjZWQ0Y2Y5MzI2MTYxYzkxYmVjYiIsImJhbm5lcnMvdjIvY29udGVudC9hc3NldHMvbG9jYWxpemVkL2VuLmpzb24iOiI5OTFjOWM1ZDM5OTUyYTdhNGE2ZDk0Yjg2NzAzYTg0NWUwNDQxMTIzNjZkNzg1MDdmNmNlYjA2YzU1OGU1YWQyIiwiYmFubmVycy92Mi9jb250ZW50L2Fzc2V0cy9sb2NhbGl6ZWQva3UuanNvbiI6IjdkMTExOWY1Mzg2MWE5MTY5MzZjNmI0Njk0NDJlMDk5Mjc2ODY4OTU2NTRiYjg1NDkyZDhjNjhkNjU1NDI3MTMiLCJiYW5uZXJzL3YyL2NvbnRlbnQvYXNzZXRzL2xvY2FsaXplZC90ci5qc29uIjoiNDc2MWU3MWY5NmM1NWIwZmE2MmIxM2M2NmE0OGY1ZGM4YjU1MzhjZTcyNjNmN2JjOGVlNjVhNjg2MThlOWQ0NSIsImJhbm5lcnMvdjIvY29udGVudC9hc3NldHMvbG9jYWxpemVkX2Rldi9lbi5qc29uIjoiOTkxYzljNWQzOTk1MmE3YTRhNmQ5NGI4NjcwM2E4NDVlMDQ0MTEyMzY2ZDc4NTA3ZjZjZWIwNmM1NThlNWFkMiIsImJhbm5lcnMvdjIvY29udGVudC9hc3NldHMvbG9jYWxpemVkX2Rldi9rdS5qc29uIjoiN2QxMTE5ZjUzODYxYTkxNjkzNmM2YjQ2OTQ0MmUwOTkyNzY4Njg5NTY1NGJiODU0OTJkOGM2OGQ2NTU0MjcxMyIsImJhbm5lcnMvdjIvY29udGVudC9hc3NldHMvbG9jYWxpemVkX2Rldi90ci5qc29uIjoiNDc2MWU3MWY5NmM1NWIwZmE2MmIxM2M2NmE0OGY1ZGM4YjU1MzhjZTcyNjNmN2JjOGVlNjVhNjg2MThlOWQ0NSIsImJhbm5lcnMvdjIvY29udGVudC9kYXBwcy9iYW5uZXJzLmpzb24iOiJjZTk0NDk0ZjE3YjMzNjJjODQxOGZhYjk4OWZiMDc0NzA5YzVhMWVmYmU5Zjg0N2RjYzE0OGFiZjBkMmFjZjA5IiwiYmFubmVycy92Mi9jb250ZW50L2RhcHBzL2Jhbm5lcnNfZGV2Lmpzb24iOiJjZTk0NDk0ZjE3YjMzNjJjODQxOGZhYjk4OWZiMDc0NzA5YzVhMWVmYmU5Zjg0N2RjYzE0OGFiZjBkMmFjZjA5IiwiYmFubmVycy92Mi9jb250ZW50L2RhcHBzL2xvY2FsaXplZC9lbi5qc29uIjoiMTZhMzUyYzE0Y2QzYjMwYzVmZTlkMmI4MmY0NWYxMjhmMzUzZDEwYWZmMjExOWQwMDNjMjliNTE2MGIzNDI3YSIsImJhbm5lcnMvdjIvY29udGVudC9kYXBwcy9sb2NhbGl6ZWQva3UuanNvbiI6ImUyZjU1YTMzN2U1ZWFlMzQzOWVlNDg4ODI0NzQxMzc2OWFmMzAzNDRmMTRmMjg0Y2UxZjdlOWQ3NzA0Y2IyZDUiLCJiYW5uZXJzL3YyL2NvbnRlbnQvZGFwcHMvbG9jYWxpemVkX2Rldi9lbi5qc29uIjoiMTZhMzUyYzE0Y2QzYjMwYzVmZTlkMmI4MmY0NWYxMjhmMzUzZDEwYWZmMjExOWQwMDNjMjliNTE2MGIzNDI3YSIsImJhbm5lcnMvdjIvY29udGVudC9kYXBwcy9sb2NhbGl6ZWRfZGV2L2t1Lmpzb24iOiJlMmY1NWEzMzdlNWVhZTM0MzllZTQ4ODgyNDc0MTM3NjlhZjMwMzQ0ZjE0ZjI4NGNlMWY3ZTlkNzcwNGNiMmQ1IiwiY2hhaW5zL2NoYWlucy5qc29uIjoiMTM5OWE3Yjg2NTNhYmY3MWVkOTIxODg3ZGFmODRhN2I1ZTY0ZTcxMTUyMjA0NGFjYmQwMTk0ZWExZjRjYTYxZiIsImNoYWlucy9jaGFpbnNfZGV2Lmpzb24iOiJkNWI4NzhkNjY5NDIzODBmN2JjYWZiOTQ2YzRmYjlkOTkzNDA5NDc3YWFkMTljOTM2MDQ0N2MwNDM0NjNiY2ZjIiwiY2hhaW5zL3Blemt1d2ljaGFpbi9jaGFpbnMuanNvbiI6ImMwOWIyYmU5N2ZjMTRhOTM4ZGE1MDVhZmY2NTMyMzQxM2ExNjA2NzQwZTg1ODkxOTY4OWI5NDdkMmIyZmUxZDMiLCJjaGFpbnMvdHlwZXMvYWx0YWlyLmpzb24iOiIxNjg3ZTkyNGQyMjcxZmQ3NjhjYWI3NWQ0OTYxYTY3YzkwYTAwNTNkMTE4ZjFkOGI1YWFlY2EwM2NjOTUwMTQzIiwiY2hhaW5zL3R5cGVzL2JpZnJvc3QuanNvbiI6ImZmMmVjMjdiYzIyMzhmOTYyMWI5MTExYjExMDI1YTY1NjRiNWY2YWVhMzE4ZjE3NzVhNjAyOTUwNDliNDQ0MGEiLCJjaGFpbnMvdHlwZXMvY2FsYW1hcmkuanNvbiI6ImQ1MTUxZGRhMmQ1OWMyMjM5YTAwNjQ0YjMxMjc0NWQ2NDYyMTE0ZmE2YTQ1ZGQ1NDkxZGY4YjkyNDU4ZTE0NmIiLCJjaGFpbnMvdHlwZXMvZGVmYXVsdC5qc29uIjoiNTYxNjA5M2ZjMWI2NDY5MTZkY2E1YjljMzRjMThjZGRjMDUxMDE1NmMwYjgxNTAwOGMyODA5OGM1ZGYzYmY3MyIsImNoYWlucy90eXBlcy9lZGdld2FyZS5qc29uIjoiMjAwZTg4NTE5ZDJlMjMxOTcwMDVjODkyMzYyMGM1Zjg4NmUxMmY3NDNhYWY2YjEyOTdiNDlhOWRmMGQ2Y2NkNSIsImNoYWlucy90eXBlcy9rYXJ1cmEuanNvbiI6IjdkZTZhMjcwMWRiODQ2MmFmYmIyMmVlMGMyNmU2NGI3MDY2N2YyMTM4MTE3ZWNhMjVhNDJmMWY3Mjk1NjQ3MDQiLCJjaGFpbnMvdHlwZXMva2lsdC5qc29uIjoiYmE2N2M3OGEwNGUwYWI5YTI1ZDcxMWY2YzRjZTFiNTEyMjYyMWEyMDdiYmU1MzI1ZjdhOTE3NjlkMTkwMjMwZSIsImNoYWlucy90eXBlcy9rdXNhbWEuanNvbiI6ImZjYzE2OWRjZDQ5OThkMjM3YTAwZmE4NmI3ODI3YzM1ZjhhZTdlNDFjMDYyNmRmNjRiZmQyM2QyMTI1NGFlNWMiLCJjaGFpbnMvdHlwZXMvbW9vbmJhc2UuanNvbiI6IjFkMjVkZjc0YjNlNDIyZjcxOGYxOTdhZGUwNWNlYTZjMTdhOWM3ZWZiMmIxYjVjOTlhMGRiOWExNzAyYjlhODMiLCJjaGFpbnMvdHlwZXMvbW9vbnJpdmVyLmpzb24iOiJjY2E5OTMzNWFlMjU3MmE2ZjRmYmZhMmFhMjNkZDgxMjIxY2NmNGQ1M2M0YjNkMGE1OGUxZjAwYjRjYjRmM2MxIiwiY2hhaW5zL3R5cGVzL3BhcmFsbGVsLmpzb24iOiJiN2ZiNTIyYWFjNGZjODdkMWYyZWNkMjg4NTVlYjcyZmI3ZTEzM2Q1ZjQyYWEwNGQ1ZTJkYjI5MWUxOTdjOGVmIiwiY2hhaW5zL3R5cGVzL3Blemt1d2kuanNvbiI6IjE0NjZkOGU1NDMwNzM4ZDNmZjE1NWQ2NTdhZDlkNTE0MzUzYzIxYjMyYTBmMjc2MTg0MmE0MDkxNWU3MTJhNDMiLCJjaGFpbnMvdHlwZXMvcG9sa2Fkb3QuanNvbiI6IjNmN2ULine truncated
|
||||
"signed": "eyJleHBpcmVzIjoxODI1MTgzMDkwLCJmaWxlcyI6eyJhc3NldHMvZXZtL3YxL2Fzc2V0cy5qc29uIjoiYmI2ZjliYWNlMmY2Y2Q5NjBlMjYyM2Q5ZWE0MmM2OTE3MzUxOWQyZmE5YWVhNWRkMzEyNzA5Njc2ZWExMDdkYSIsImFzc2V0cy9ldm0vdjEvYXNzZXRzX2Rldi5qc29uIjoiNDJhMThhYTUxZTEwZmY0NjllOTYxMGJlMzNmOThkZjhlYWM5NjFhZTVmZDc2YWRhZTNmZThiNzhlZGVlYzIxNiIsImFzc2V0cy9ldm0vdjIvYXNzZXRzLmpzb24iOiJhZWNjZjRlZTE5ODhiOTI0OTRmMWZkZDBjYTI0OGYzYjlmYjE2NmFkZTAyNjRhM2IzZjRmYWYzZDc1MjhhYzBmIiwiYXNzZXRzL2V2bS92Mi9hc3NldHNfZGV2Lmpzb24iOiI2YmZlZDBmMzU2M2YxMDdkNDViZWM0ZjQ3MjYzYWUyYzMyMjA3ZjQ1ZGRhNmQwNmUxNDczNmFkNWM2OTYzYmYzIiwiYXNzZXRzL2V2bS92My9hc3NldHMuanNvbiI6ImM0NDc4NWRiOTkyZjE0NTA3NTFkY2FjOGI1MTVlOTg0NzRlYTA0YTMyZTE4MjgwYjBmOWEyNjNkNzNhM2RjYzUiLCJhc3NldHMvZXZtL3YzL2Fzc2V0c19kZXYuanNvbiI6ImUyMDc5Y2VjNTkxMGQ0NDE0MzBiNzc0ZmYxMjJkN2E2MGI1OTIwMDZlZjE3NmI4NDAzMTE2ZWMyMmM1YTYyNTEiLCJhc3NldHMvc2xpcDQ0Lmpzb24iOiI2MDAyM2IzN2MxMDE4NDdjNzJmMzZmMDVmNTJlNmE4Y2U0Mzk1NjU5ZDZhOTg0ZmE5YjMyYTFiMzlkYWJjODUwIiwiYmFubmVycy92Mi9jb250ZW50L2Fzc2V0cy9iYW5uZXJzLmpzb24iOiI1Yjg3NGMyZjdiNGE3YTJmZDY0Nzc2ZjVhNDI4YTljMTUzMTJjZmNjZDUyMmNlZDRjZjkzMjYxNjFjOTFiZWNiIiwiYmFubmVycy92Mi9jb250ZW50L2Fzc2V0cy9iYW5uZXJzX2Rldi5qc29uIjoiNWI4NzRjMmY3YjRhN2EyZmQ2NDc3NmY1YTQyOGE5YzE1MzEyY2ZjY2Q1MjJjZWQ0Y2Y5MzI2MTYxYzkxYmVjYiIsImJhbm5lcnMvdjIvY29udGVudC9hc3NldHMvbG9jYWxpemVkL2VuLmpzb24iOiI5OTFjOWM1ZDM5OTUyYTdhNGE2ZDk0Yjg2NzAzYTg0NWUwNDQxMTIzNjZkNzg1MDdmNmNlYjA2YzU1OGU1YWQyIiwiYmFubmVycy92Mi9jb250ZW50L2Fzc2V0cy9sb2NhbGl6ZWQva3UuanNvbiI6IjdkMTExOWY1Mzg2MWE5MTY5MzZjNmI0Njk0NDJlMDk5Mjc2ODY4OTU2NTRiYjg1NDkyZDhjNjhkNjU1NDI3MTMiLCJiYW5uZXJzL3YyL2NvbnRlbnQvYXNzZXRzL2xvY2FsaXplZC90ci5qc29uIjoiNDc2MWU3MWY5NmM1NWIwZmE2MmIxM2M2NmE0OGY1ZGM4YjU1MzhjZTcyNjNmN2JjOGVlNjVhNjg2MThlOWQ0NSIsImJhbm5lcnMvdjIvY29udGVudC9hc3NldHMvbG9jYWxpemVkX2Rldi9lbi5qc29uIjoiOTkxYzljNWQzOTk1MmE3YTRhNmQ5NGI4NjcwM2E4NDVlMDQ0MTEyMzY2ZDc4NTA3ZjZjZWIwNmM1NThlNWFkMiIsImJhbm5lcnMvdjIvY29udGVudC9hc3NldHMvbG9jYWxpemVkX2Rldi9rdS5qc29uIjoiN2QxMTE5ZjUzODYxYTkxNjkzNmM2YjQ2OTQ0MmUwOTkyNzY4Njg5NTY1NGJiODU0OTJkOGM2OGQ2NTU0MjcxMyIsImJhbm5lcnMvdjIvY29udGVudC9hc3NldHMvbG9jYWxpemVkX2Rldi90ci5qc29uIjoiNDc2MWU3MWY5NmM1NWIwZmE2MmIxM2M2NmE0OGY1ZGM4YjU1MzhjZTcyNjNmN2JjOGVlNjVhNjg2MThlOWQ0NSIsImJhbm5lcnMvdjIvY29udGVudC9kYXBwcy9iYW5uZXJzLmpzb24iOiJjZTk0NDk0ZjE3YjMzNjJjODQxOGZhYjk4OWZiMDc0NzA5YzVhMWVmYmU5Zjg0N2RjYzE0OGFiZjBkMmFjZjA5IiwiYmFubmVycy92Mi9jb250ZW50L2RhcHBzL2Jhbm5lcnNfZGV2Lmpzb24iOiJjZTk0NDk0ZjE3YjMzNjJjODQxOGZhYjk4OWZiMDc0NzA5YzVhMWVmYmU5Zjg0N2RjYzE0OGFiZjBkMmFjZjA5IiwiYmFubmVycy92Mi9jb250ZW50L2RhcHBzL2xvY2FsaXplZC9lbi5qc29uIjoiMTZhMzUyYzE0Y2QzYjMwYzVmZTlkMmI4MmY0NWYxMjhmMzUzZDEwYWZmMjExOWQwMDNjMjliNTE2MGIzNDI3YSIsImJhbm5lcnMvdjIvY29udGVudC9kYXBwcy9sb2NhbGl6ZWQva3UuanNvbiI6ImUyZjU1YTMzN2U1ZWFlMzQzOWVlNDg4ODI0NzQxMzc2OWFmMzAzNDRmMTRmMjg0Y2UxZjdlOWQ3NzA0Y2IyZDUiLCJiYW5uZXJzL3YyL2NvbnRlbnQvZGFwcHMvbG9jYWxpemVkX2Rldi9lbi5qc29uIjoiMTZhMzUyYzE0Y2QzYjMwYzVmZTlkMmI4MmY0NWYxMjhmMzUzZDEwYWZmMjExOWQwMDNjMjliNTE2MGIzNDI3YSIsImJhbm5lcnMvdjIvY29udGVudC9kYXBwcy9sb2NhbGl6ZWRfZGV2L2t1Lmpzb24iOiJlMmY1NWEzMzdlNWVhZTM0MzllZTQ4ODgyNDc0MTM3NjlhZjMwMzQ0ZjE0ZjI4NGNlMWY3ZTlkNzcwNGNiMmQ1IiwiY2hhaW5zL2NoYWlucy5qc29uIjoiMTM5OWE3Yjg2NTNhYmY3MWVkOTIxODg3ZGFmODRhN2I1ZTY0ZTcxMTUyMjA0NGFjYmQwMTk0ZWExZjRjYTYxZiIsImNoYWlucy9jaGFpbnNfZGV2Lmpzb24iOiJkNWI4NzhkNjY5NDIzODBmN2JjYWZiOTQ2YzRmYjlkOTkzNDA5NDc3YWFkMTljOTM2MDQ0N2MwNDM0NjNiY2ZjIiwiY2hhaW5zL3Blemt1d2ljaGFpbi9jaGFpbnMuanNvbiI6ImMwOWIyYmU5N2ZjMTRhOTM4ZGE1MDVhZmY2NTMyMzQxM2ExNjA2NzQwZTg1ODkxOTY4OWI5NDdkMmIyZmUxZDMiLCJjaGFpbnMvdHlwZXMvYWx0YWlyLmpzb24iOiIxNjg3ZTkyNGQyMjcxZmQ3NjhjYWI3NWQ0OTYxYTY3YzkwYTAwNTNkMTE4ZjFkOGI1YWFlY2EwM2NjOTUwMTQzIiwiY2hhaW5zL3R5cGVzL2JpZnJvc3QuanNvbiI6ImZmMmVjMjdiYzIyMzhmOTYyMWI5MTExYjExMDI1YTY1NjRiNWY2YWVhMzE4ZjE3NzVhNjAyOTUwNDliNDQ0MGEiLCJjaGFpbnMvdHlwZXMvY2FsYW1hcmkuanNvbiI6ImQ1MTUxZGRhMmQ1OWMyMjM5YTAwNjQ0YjMxMjc0NWQ2NDYyMTE0ZmE2YTQ1ZGQ1NDkxZGY4YjkyNDU4ZTE0NmIiLCJjaGFpbnMvdHlwZXMvZGVmYXVsdC5qc29uIjoiNTYxNjA5M2ZjMWI2NDY5MTZkY2E1YjljMzRjMThjZGRjMDUxMDE1NmMwYjgxNTAwOGMyODA5OGM1ZGYzYmY3MyIsImNoYWlucy90eXBlcy9lZGdld2FyZS5qc29uIjoiMjAwZTg4NTE5ZDJlMjMxOTcwMDVjODkyMzYyMGM1Zjg4NmUxMmY3NDNhYWY2YjEyOTdiNDlhOWRmMGQ2Y2NkNSIsImNoYWlucy90eXBlcy9rYXJ1cmEuanNvbiI6IjdkZTZhMjcwMWRiODQ2MmFmYmIyMmVlMGMyNmU2NGI3MDY2N2YyMTM4MTE3ZWNhMjVhNDJmMWY3Mjk1NjQ3MDQiLCJjaGFpbnMvdHlwZXMva2lsdC5qc29uIjoiYmE2N2M3OGEwNGUwYWI5YTI1ZDcxMWY2YzRjZTFiNTEyMjYyMWEyMDdiYmU1MzI1ZjdhOTE3NjlkMTkwMjMwZSIsImNoYWlucy90eXBlcy9rdXNhbWEuanNvbiI6ImZjYzE2OWRjZDQ5OThkMjM3YTAwZmE4NmI3ODI3YzM1ZjhhZTdlNDFjMDYyNmRmNjRiZmQyM2QyMTI1NGFlNWMiLCJjaGFpbnMvdHlwZXMvbW9vbmJhc2UuanNvbiI6IjFkMjVkZjc0YjNlNDIyZjcxOGYxOTdhZGUwNWNlYTZjMTdhOWM3ZWZiMmIxYjVjOTlhMGRiOWExNzAyYjlhODMiLCJjaGFpbnMvdHlwZXMvbW9vbnJpdmVyLmpzb24iOiJjY2E5OTMzNWFlMjU3MmE2ZjRmYmZhMmFhMjNkZDgxMjIxY2NmNGQ1M2M0YjNkMGE1OGUxZjAwYjRjYjRmM2MxIiwiY2hhaW5zL3R5cGVzL3BhcmFsbGVsLmpzb24iOiJiN2ZiNTIyYWFjNGZjODdkMWYyZWNkMjg4NTVlYjcyZmI3ZTEzM2Q1ZjQyYWEwNGQ1ZTJkYjI5MWUxOTdjOGVmIiwiY2hhaW5zL3R5cGVzL3Blemt1d2kuanNvbiI6IjE0NjZkOGU1NDMwNzM4ZDNmZjE1NWQ2NTdhZDlkNTE0MzUzYzIxYjMyYTBmMjc2MTg0MmE0MDkxNWU3MTJhNDMiLCJjaGFpbnMvdHlwZXMvcG9sa2Fkb3QuanNvbiI6IjNmN2ULine truncated
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "6066e6a8729c340989e7c150efbd63b1efb9ff1ccaa1e1f38fa015c2f1f9ab5a",
|
||||
"sig": "EEf5kGNPRK7iu5cbHlfiQ+mxYf2jg6gVmb7lSxkZUi2X1VafOKgXrKJi9ol1w6H2FpizXizgPTKgESdYt0A7Cw=="
|
||||
"sig": "hciTvg3URWpaKqhUd4MdCf9nyOcA1A48hXbCkpPFKqr9t0Wywe7PC3ftVhdDaj7Le9TrSMk59xY0zyZiNYsDBA=="
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user