Skip to content

Commit 5725e8e

Browse files
authored
Merge pull request #1189 from HathorNetwork/chore/update-checkpoints
chore: update mainnet and testnet checkpoints and include helper script
2 parents cf3fa8b + f2fb42a commit 5725e8e

File tree

5 files changed

+194
-0
lines changed

5 files changed

+194
-0
lines changed

extras/update_checkpoints.py

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#!/usr/bin/env python
2+
"""
3+
Usage: update_checkpoints.py [-h] [-n NETWORK]
4+
5+
Helper script to update the config checkpoint list.
6+
7+
options:
8+
-h, --help show this help message and exit
9+
-n NETWORK, --network NETWORK
10+
The network to update (default: mainnet)
11+
12+
For example:
13+
14+
$ ./extras/update_checkpoints.py
15+
New checkpoints to add for mainnet:
16+
17+
4_800_000: 00000000000000000716b8d9e96591ba7cb2d02c3d2d1d98d514f41c240fdff7
18+
4_900_000: 0000000000000000079b1c1ebf48d351a7d31dcc55c5b4cf79ade79089a20f5a
19+
5_000_000: 000000000000000006c9167db1cc7e93fcf1c3014da6c6221390d03d1640c9b3
20+
21+
cp(4_800_000, bytes.fromhex('00000000000000000716b8d9e96591ba7cb2d02c3d2d1d98d514f41c240fdff7')),
22+
cp(4_900_000, bytes.fromhex('0000000000000000079b1c1ebf48d351a7d31dcc55c5b4cf79ade79089a20f5a')),
23+
cp(5_000_000, bytes.fromhex('000000000000000006c9167db1cc7e93fcf1c3014da6c6221390d03d1640c9b3')),
24+
25+
The output can then be copied and pasted into `hathor/conf/mainnet.yml` and `hathor/conf/mainnet.py`
26+
"""
27+
28+
import requests
29+
import yaml
30+
import argparse
31+
32+
# Built-in network configurations
33+
NETWORKS: dict[str, dict[str, str]] = {
34+
'mainnet': {
35+
'config_file': 'hathor/conf/mainnet.yml',
36+
'node_url': 'https://node1.mainnet.hathor.network/v1a',
37+
},
38+
'testnet': {
39+
'config_file': 'hathor/conf/testnet.yml',
40+
'node_url': 'https://node1.golf.testnet.hathor.network/v1a',
41+
},
42+
# Add more networks as needed
43+
}
44+
45+
CHECKPOINT_INTERVAL: int = 100_000
46+
47+
48+
def get_latest_height(node_url: str) -> int:
49+
"""Fetch the latest block height."""
50+
response = requests.get(f'{node_url}/transaction?type=block&count=1')
51+
response.raise_for_status()
52+
return response.json()['transactions'][0]['height']
53+
54+
55+
def get_hash_for_height(node_url: str, height: int) -> str:
56+
"""Fetch the hash for a given block height."""
57+
response = requests.get(f'{node_url}/block_at_height?height={height}')
58+
response.raise_for_status()
59+
return response.json()['block']['tx_id']
60+
61+
62+
def load_checkpoints(config_file: str) -> dict[str, int]:
63+
"""Load the checkpoints from the specified YAML config file."""
64+
with open(config_file, 'r') as file:
65+
data = yaml.safe_load(file)
66+
return data.get('CHECKPOINTS', {})
67+
68+
69+
def print_new_checkpoints(network_name: str) -> None:
70+
"""Print new checkpoints for the specified network."""
71+
if network_name not in NETWORKS:
72+
print(f'Error: Unknown network {network_name}. Available networks: {", ".join(NETWORKS.keys())}')
73+
return
74+
75+
# Get the network configuration
76+
network_config = NETWORKS[network_name]
77+
config_file = network_config['config_file']
78+
node_url = network_config['node_url']
79+
80+
# Load existing checkpoints from the YAML file
81+
current_checkpoints = load_checkpoints(config_file)
82+
83+
# Get the latest block height
84+
latest_height = get_latest_height(node_url)
85+
86+
# Determine missing checkpoints
87+
new_checkpoints = {}
88+
for height in range(CHECKPOINT_INTERVAL, latest_height + 1, CHECKPOINT_INTERVAL):
89+
if height not in current_checkpoints:
90+
block_hash = get_hash_for_height(node_url, height)
91+
new_checkpoints[height] = block_hash
92+
93+
# Print new checkpoints
94+
if new_checkpoints:
95+
print(f'New checkpoints to add for {network_name}:\n')
96+
for height, block_hash in sorted(new_checkpoints.items()):
97+
print(f' {height:_}: {block_hash}')
98+
print()
99+
for height, block_hash in sorted(new_checkpoints.items()):
100+
print(f''' cp({height:_}, bytes.fromhex('{block_hash}')),''')
101+
else:
102+
print(f'No new checkpoints needed for {network_name}. All up to date.')
103+
104+
105+
if __name__ == '__main__':
106+
# Parse command-line arguments
107+
parser = argparse.ArgumentParser(description='Helper script to update the config checkpoint list.')
108+
parser.add_argument('-n', '--network', default='mainnet', help='The network to update (default: mainnet)')
109+
args = parser.parse_args()
110+
111+
# Print new checkpoints for the specified network
112+
print_new_checkpoints(args.network)

hathor/conf/mainnet.py

+14
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@
7272
cp(3_400_000, bytes.fromhex('000000000000000077242c961a0c6f708bc671a8372eb8b095311f091fddc6c3')),
7373
cp(3_500_000, bytes.fromhex('000000000000000a34ba20552c3cae9549b9c5ca07f644cf005328c948aa54d8')),
7474
cp(3_600_000, bytes.fromhex('000000000000000011031d9ff030cd9e6fe8a3766bbeda6f6337c40dd30fa65f')),
75+
cp(3_700_000, bytes.fromhex('0000000000000006c6e7295efcf0929173cc47ece41afc652410b72f36cbeeda')),
76+
cp(3_800_000, bytes.fromhex('00000000000000122f57d59c7f6736a83483dcf71c34978102d7e04ce4dc9a5d')),
77+
cp(3_900_000, bytes.fromhex('00000000000000069edf3300d6c41451485d7aabdbea34425a2411b880e8a976')),
78+
cp(4_000_000, bytes.fromhex('00000000000000043b11a6c86c3cdaf773a5183737f136e196e816f862e1e3ba')),
79+
cp(4_100_000, bytes.fromhex('0000000000000020822d529b6fcd8611f5a174b1f44a6c478a2fec64a80233ad')),
80+
cp(4_200_000, bytes.fromhex('00000000000000052ffc34875fab4e545bc9dc76f1212c4fdafab3b6d7a026cd')),
81+
cp(4_300_000, bytes.fromhex('000000000000000e1ea2af0e25087c0977e944dd0ffdae5fdff54dda85ed95be')),
82+
cp(4_400_000, bytes.fromhex('0000000000000000020dab883c57e21829b590ef61ff5230f5fdc9d572300945')),
83+
cp(4_500_000, bytes.fromhex('00000000000000034d5ddf802a8ac8fbf17cf50747041e433d28d9f2bcb6ef02')),
84+
cp(4_600_000, bytes.fromhex('000000000000000055bb4e5b6d942da13cb631f318cfdc292793f28ef8a338ca')),
85+
cp(4_700_000, bytes.fromhex('000000000000000002ae1d75811b1050fc98ee7ef30c48cde117ebbb42f47e22')),
86+
cp(4_800_000, bytes.fromhex('00000000000000000716b8d9e96591ba7cb2d02c3d2d1d98d514f41c240fdff7')),
87+
cp(4_900_000, bytes.fromhex('0000000000000000079b1c1ebf48d351a7d31dcc55c5b4cf79ade79089a20f5a')),
88+
cp(5_000_000, bytes.fromhex('000000000000000006c9167db1cc7e93fcf1c3014da6c6221390d03d1640c9b3')),
7589
],
7690
SOFT_VOIDED_TX_IDS=list(map(bytes.fromhex, [
7791
'0000000012a922a6887497bed9c41e5ed7dc7213cae107db295602168266cd02',

hathor/conf/mainnet.yml

+14
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ CHECKPOINTS:
5353
3_400_000: 000000000000000077242c961a0c6f708bc671a8372eb8b095311f091fddc6c3
5454
3_500_000: 000000000000000a34ba20552c3cae9549b9c5ca07f644cf005328c948aa54d8
5555
3_600_000: 000000000000000011031d9ff030cd9e6fe8a3766bbeda6f6337c40dd30fa65f
56+
3_700_000: 0000000000000006c6e7295efcf0929173cc47ece41afc652410b72f36cbeeda
57+
3_800_000: 00000000000000122f57d59c7f6736a83483dcf71c34978102d7e04ce4dc9a5d
58+
3_900_000: 00000000000000069edf3300d6c41451485d7aabdbea34425a2411b880e8a976
59+
4_000_000: 00000000000000043b11a6c86c3cdaf773a5183737f136e196e816f862e1e3ba
60+
4_100_000: 0000000000000020822d529b6fcd8611f5a174b1f44a6c478a2fec64a80233ad
61+
4_200_000: 00000000000000052ffc34875fab4e545bc9dc76f1212c4fdafab3b6d7a026cd
62+
4_300_000: 000000000000000e1ea2af0e25087c0977e944dd0ffdae5fdff54dda85ed95be
63+
4_400_000: 0000000000000000020dab883c57e21829b590ef61ff5230f5fdc9d572300945
64+
4_500_000: 00000000000000034d5ddf802a8ac8fbf17cf50747041e433d28d9f2bcb6ef02
65+
4_600_000: 000000000000000055bb4e5b6d942da13cb631f318cfdc292793f28ef8a338ca
66+
4_700_000: 000000000000000002ae1d75811b1050fc98ee7ef30c48cde117ebbb42f47e22
67+
4_800_000: 00000000000000000716b8d9e96591ba7cb2d02c3d2d1d98d514f41c240fdff7
68+
4_900_000: 0000000000000000079b1c1ebf48d351a7d31dcc55c5b4cf79ade79089a20f5a
69+
5_000_000: 000000000000000006c9167db1cc7e93fcf1c3014da6c6221390d03d1640c9b3
5670

5771
SOFT_VOIDED_TX_IDS:
5872
- 0000000012a922a6887497bed9c41e5ed7dc7213cae107db295602168266cd02

hathor/conf/testnet.py

+27
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,33 @@
5353
cp(1_400_000, bytes.fromhex('000000000df9cb786c68a643a52a67c22ab54e8b8e41cbe9b761133f6c8abbfe')),
5454
cp(1_500_000, bytes.fromhex('000000000c3591805f4748480b59ac1788f754fc004930985a487580e2b5de8f')),
5555
cp(1_600_000, bytes.fromhex('00000000060adfdfd7d488d4d510b5779cf35a3c50df7bcff941fbb6957be4d2')),
56+
cp(1_700_000, bytes.fromhex('0000000007afc04aebad15b14fcd93c1b5193dc503b190433f55be8c218b6d12')),
57+
cp(1_800_000, bytes.fromhex('00000000126f16af2ba934a60cf8f2da32d3ed2688c56ce8ff477e483a3ffc42')),
58+
cp(1_900_000, bytes.fromhex('0000000005d2a2ba2231663187b460396189af0ffca7b2e93fccc85cde04cbdc')),
59+
cp(2_000_000, bytes.fromhex('000000000009a8451ff2d5ec54951d717da2766aedb3131485466cc993879ee1')),
60+
cp(2_100_000, bytes.fromhex('0000000009f961804cd7f43da05f08a94a2fa09f82c7d605afc5982ab242a7e4')),
61+
cp(2_200_000, bytes.fromhex('0000000002e260b970846a89c23e754a763e7c5f1578b6ec4e67bdb94c667997')),
62+
cp(2_300_000, bytes.fromhex('0000000006e0894c8f7fd029fe446a42433875647759183ba3fbb0ff0b7ceb64')),
63+
cp(2_400_000, bytes.fromhex('0000000011ab28f3be17e3a098307fa73750cc8d74f1f60cfb44b524a60c94ec')),
64+
cp(2_500_000, bytes.fromhex('00000000045d2bcc10c896bfc7d1f28788e3530a81f50ee096f386eec772634f')),
65+
cp(2_600_000, bytes.fromhex('000000000766b9ac25e2ece5685effa834e61284e38f368c841210606bb1fdfc')),
66+
cp(2_700_000, bytes.fromhex('0000000005d0ee31d0f47f6ff9aa570b9f25b9d44a8a59cea0e0f8a1729b9c90')),
67+
cp(2_800_000, bytes.fromhex('000000000a5bd4f266fa13d2c0594cabf6465758f7f5814bde626032706b81e5')),
68+
cp(2_900_000, bytes.fromhex('000000000b11b0a09ff0d7c2cfd9228f31c53008e700532e439d3a3d9c63fb8e')),
69+
cp(3_000_000, bytes.fromhex('00000000013289569569cd51580183a2c870dfe5a395adaa00ae66fefe51af3d')),
70+
cp(3_100_000, bytes.fromhex('00000000170c55e6ec207400bfc42786c1e0c32fe045a1d815f930daf2bf3020')),
71+
cp(3_200_000, bytes.fromhex('00000000149986cb99c202136bd388fb2a7fcba4bdfd6ac049069ac5e08a587f')),
72+
cp(3_300_000, bytes.fromhex('000000000e16f87ac7133639cb52a99574944b8457939396e7faf1615fcfdb0f')),
73+
cp(3_400_000, bytes.fromhex('000000000f551f6224a459904436072f5ff10fd3db17f2d7e25b1ef9b149c121')),
74+
cp(3_500_000, bytes.fromhex('0000000006572b8cf41130e88776adf8583e970905df2afe593ca31c91ab0c4c')),
75+
cp(3_600_000, bytes.fromhex('000000000215fcc7018cc31bbfb943ca43c6297529fa008bf34665f3ac64d340')),
76+
cp(3_700_000, bytes.fromhex('000000000dbf5e8ab4f90f2187db6db429c9d0cb8169051ce8a9e79b810509d7')),
77+
cp(3_800_000, bytes.fromhex('00000000030411ec36c7f5386a94e147460d86592f85459e0eadd5cd0e3da7b4')),
78+
cp(3_900_000, bytes.fromhex('000000000bc2c7078a3c59d878196f1491aad45a0df9d312909d85482ac8d714')),
79+
cp(4_000_000, bytes.fromhex('000000000eba0dae3ec27cf5596ef49731744edebadb9fbae42160b6aa2e2461')),
80+
cp(4_100_000, bytes.fromhex('00000000052aa77fd8db71d5306257f9fe068c3401d95b17fcedcccfc9b76c82')),
81+
cp(4_200_000, bytes.fromhex('00000000010a8dae043c84fcb2cef6a2b42a28279b95af20ab5a098acf2a3565')),
82+
cp(4_300_000, bytes.fromhex('000000000019da781ef75fa5f59c5537d8ed18b64c589c3e036109cfb1d84f7d')),
5683
],
5784
FEATURE_ACTIVATION=FeatureActivationSettings(
5885
default_threshold=15_120, # 15120 = 75% of evaluation_interval (20160)

hathor/conf/testnet.yml

+27
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,33 @@ CHECKPOINTS:
3535
1_400_000: 000000000df9cb786c68a643a52a67c22ab54e8b8e41cbe9b761133f6c8abbfe
3636
1_500_000: 000000000c3591805f4748480b59ac1788f754fc004930985a487580e2b5de8f
3737
1_600_000: 00000000060adfdfd7d488d4d510b5779cf35a3c50df7bcff941fbb6957be4d2
38+
1_700_000: 0000000007afc04aebad15b14fcd93c1b5193dc503b190433f55be8c218b6d12
39+
1_800_000: 00000000126f16af2ba934a60cf8f2da32d3ed2688c56ce8ff477e483a3ffc42
40+
1_900_000: 0000000005d2a2ba2231663187b460396189af0ffca7b2e93fccc85cde04cbdc
41+
2_000_000: 000000000009a8451ff2d5ec54951d717da2766aedb3131485466cc993879ee1
42+
2_100_000: 0000000009f961804cd7f43da05f08a94a2fa09f82c7d605afc5982ab242a7e4
43+
2_200_000: 0000000002e260b970846a89c23e754a763e7c5f1578b6ec4e67bdb94c667997
44+
2_300_000: 0000000006e0894c8f7fd029fe446a42433875647759183ba3fbb0ff0b7ceb64
45+
2_400_000: 0000000011ab28f3be17e3a098307fa73750cc8d74f1f60cfb44b524a60c94ec
46+
2_500_000: 00000000045d2bcc10c896bfc7d1f28788e3530a81f50ee096f386eec772634f
47+
2_600_000: 000000000766b9ac25e2ece5685effa834e61284e38f368c841210606bb1fdfc
48+
2_700_000: 0000000005d0ee31d0f47f6ff9aa570b9f25b9d44a8a59cea0e0f8a1729b9c90
49+
2_800_000: 000000000a5bd4f266fa13d2c0594cabf6465758f7f5814bde626032706b81e5
50+
2_900_000: 000000000b11b0a09ff0d7c2cfd9228f31c53008e700532e439d3a3d9c63fb8e
51+
3_000_000: 00000000013289569569cd51580183a2c870dfe5a395adaa00ae66fefe51af3d
52+
3_100_000: 00000000170c55e6ec207400bfc42786c1e0c32fe045a1d815f930daf2bf3020
53+
3_200_000: 00000000149986cb99c202136bd388fb2a7fcba4bdfd6ac049069ac5e08a587f
54+
3_300_000: 000000000e16f87ac7133639cb52a99574944b8457939396e7faf1615fcfdb0f
55+
3_400_000: 000000000f551f6224a459904436072f5ff10fd3db17f2d7e25b1ef9b149c121
56+
3_500_000: 0000000006572b8cf41130e88776adf8583e970905df2afe593ca31c91ab0c4c
57+
3_600_000: 000000000215fcc7018cc31bbfb943ca43c6297529fa008bf34665f3ac64d340
58+
3_700_000: 000000000dbf5e8ab4f90f2187db6db429c9d0cb8169051ce8a9e79b810509d7
59+
3_800_000: 00000000030411ec36c7f5386a94e147460d86592f85459e0eadd5cd0e3da7b4
60+
3_900_000: 000000000bc2c7078a3c59d878196f1491aad45a0df9d312909d85482ac8d714
61+
4_000_000: 000000000eba0dae3ec27cf5596ef49731744edebadb9fbae42160b6aa2e2461
62+
4_100_000: 00000000052aa77fd8db71d5306257f9fe068c3401d95b17fcedcccfc9b76c82
63+
4_200_000: 00000000010a8dae043c84fcb2cef6a2b42a28279b95af20ab5a098acf2a3565
64+
4_300_000: 000000000019da781ef75fa5f59c5537d8ed18b64c589c3e036109cfb1d84f7d
3865

3966
FEATURE_ACTIVATION:
4067
default_threshold: 15_120 # 15120 = 75% of evaluation_interval (20160)

0 commit comments

Comments
 (0)