diff --git a/extras/update_checkpoints.py b/extras/update_checkpoints.py new file mode 100755 index 000000000..e83538b5c --- /dev/null +++ b/extras/update_checkpoints.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +""" +Usage: update_checkpoints.py [-h] [-n NETWORK] + +Helper script to update the config checkpoint list. + +options: + -h, --help show this help message and exit + -n NETWORK, --network NETWORK + The network to update (default: mainnet) + +For example: + +$ ./extras/update_checkpoints.py +New checkpoints to add for mainnet: + + 4_800_000: 00000000000000000716b8d9e96591ba7cb2d02c3d2d1d98d514f41c240fdff7 + 4_900_000: 0000000000000000079b1c1ebf48d351a7d31dcc55c5b4cf79ade79089a20f5a + 5_000_000: 000000000000000006c9167db1cc7e93fcf1c3014da6c6221390d03d1640c9b3 + + cp(4_800_000, bytes.fromhex('00000000000000000716b8d9e96591ba7cb2d02c3d2d1d98d514f41c240fdff7')), + cp(4_900_000, bytes.fromhex('0000000000000000079b1c1ebf48d351a7d31dcc55c5b4cf79ade79089a20f5a')), + cp(5_000_000, bytes.fromhex('000000000000000006c9167db1cc7e93fcf1c3014da6c6221390d03d1640c9b3')), + +The output can then be copied and pasted into `hathor/conf/mainnet.yml` and `hathor/conf/mainnet.py` +""" + +import requests +import yaml +import argparse + +# Built-in network configurations +NETWORKS: dict[str, dict[str, str]] = { + 'mainnet': { + 'config_file': 'hathor/conf/mainnet.yml', + 'node_url': 'https://node1.mainnet.hathor.network/v1a', + }, + 'testnet': { + 'config_file': 'hathor/conf/testnet.yml', + 'node_url': 'https://node1.golf.testnet.hathor.network/v1a', + }, + # Add more networks as needed +} + +CHECKPOINT_INTERVAL: int = 100_000 + + +def get_latest_height(node_url: str) -> int: + """Fetch the latest block height.""" + response = requests.get(f'{node_url}/transaction?type=block&count=1') + response.raise_for_status() + return response.json()['transactions'][0]['height'] + + +def get_hash_for_height(node_url: str, height: int) -> str: + """Fetch the hash for a given block height.""" + response = requests.get(f'{node_url}/block_at_height?height={height}') + response.raise_for_status() + return response.json()['block']['tx_id'] + + +def load_checkpoints(config_file: str) -> dict[str, int]: + """Load the checkpoints from the specified YAML config file.""" + with open(config_file, 'r') as file: + data = yaml.safe_load(file) + return data.get('CHECKPOINTS', {}) + + +def print_new_checkpoints(network_name: str) -> None: + """Print new checkpoints for the specified network.""" + if network_name not in NETWORKS: + print(f'Error: Unknown network {network_name}. Available networks: {", ".join(NETWORKS.keys())}') + return + + # Get the network configuration + network_config = NETWORKS[network_name] + config_file = network_config['config_file'] + node_url = network_config['node_url'] + + # Load existing checkpoints from the YAML file + current_checkpoints = load_checkpoints(config_file) + + # Get the latest block height + latest_height = get_latest_height(node_url) + + # Determine missing checkpoints + new_checkpoints = {} + for height in range(CHECKPOINT_INTERVAL, latest_height + 1, CHECKPOINT_INTERVAL): + if height not in current_checkpoints: + block_hash = get_hash_for_height(node_url, height) + new_checkpoints[height] = block_hash + + # Print new checkpoints + if new_checkpoints: + print(f'New checkpoints to add for {network_name}:\n') + for height, block_hash in sorted(new_checkpoints.items()): + print(f' {height:_}: {block_hash}') + print() + for height, block_hash in sorted(new_checkpoints.items()): + print(f''' cp({height:_}, bytes.fromhex('{block_hash}')),''') + else: + print(f'No new checkpoints needed for {network_name}. All up to date.') + + +if __name__ == '__main__': + # Parse command-line arguments + parser = argparse.ArgumentParser(description='Helper script to update the config checkpoint list.') + parser.add_argument('-n', '--network', default='mainnet', help='The network to update (default: mainnet)') + args = parser.parse_args() + + # Print new checkpoints for the specified network + print_new_checkpoints(args.network) diff --git a/hathor/conf/mainnet.py b/hathor/conf/mainnet.py index f580f9481..c5614e34b 100644 --- a/hathor/conf/mainnet.py +++ b/hathor/conf/mainnet.py @@ -72,6 +72,20 @@ cp(3_400_000, bytes.fromhex('000000000000000077242c961a0c6f708bc671a8372eb8b095311f091fddc6c3')), cp(3_500_000, bytes.fromhex('000000000000000a34ba20552c3cae9549b9c5ca07f644cf005328c948aa54d8')), cp(3_600_000, bytes.fromhex('000000000000000011031d9ff030cd9e6fe8a3766bbeda6f6337c40dd30fa65f')), + cp(3_700_000, bytes.fromhex('0000000000000006c6e7295efcf0929173cc47ece41afc652410b72f36cbeeda')), + cp(3_800_000, bytes.fromhex('00000000000000122f57d59c7f6736a83483dcf71c34978102d7e04ce4dc9a5d')), + cp(3_900_000, bytes.fromhex('00000000000000069edf3300d6c41451485d7aabdbea34425a2411b880e8a976')), + cp(4_000_000, bytes.fromhex('00000000000000043b11a6c86c3cdaf773a5183737f136e196e816f862e1e3ba')), + cp(4_100_000, bytes.fromhex('0000000000000020822d529b6fcd8611f5a174b1f44a6c478a2fec64a80233ad')), + cp(4_200_000, bytes.fromhex('00000000000000052ffc34875fab4e545bc9dc76f1212c4fdafab3b6d7a026cd')), + cp(4_300_000, bytes.fromhex('000000000000000e1ea2af0e25087c0977e944dd0ffdae5fdff54dda85ed95be')), + cp(4_400_000, bytes.fromhex('0000000000000000020dab883c57e21829b590ef61ff5230f5fdc9d572300945')), + cp(4_500_000, bytes.fromhex('00000000000000034d5ddf802a8ac8fbf17cf50747041e433d28d9f2bcb6ef02')), + cp(4_600_000, bytes.fromhex('000000000000000055bb4e5b6d942da13cb631f318cfdc292793f28ef8a338ca')), + cp(4_700_000, bytes.fromhex('000000000000000002ae1d75811b1050fc98ee7ef30c48cde117ebbb42f47e22')), + cp(4_800_000, bytes.fromhex('00000000000000000716b8d9e96591ba7cb2d02c3d2d1d98d514f41c240fdff7')), + cp(4_900_000, bytes.fromhex('0000000000000000079b1c1ebf48d351a7d31dcc55c5b4cf79ade79089a20f5a')), + cp(5_000_000, bytes.fromhex('000000000000000006c9167db1cc7e93fcf1c3014da6c6221390d03d1640c9b3')), ], SOFT_VOIDED_TX_IDS=list(map(bytes.fromhex, [ '0000000012a922a6887497bed9c41e5ed7dc7213cae107db295602168266cd02', diff --git a/hathor/conf/mainnet.yml b/hathor/conf/mainnet.yml index d32845449..d05a07e08 100644 --- a/hathor/conf/mainnet.yml +++ b/hathor/conf/mainnet.yml @@ -53,6 +53,20 @@ CHECKPOINTS: 3_400_000: 000000000000000077242c961a0c6f708bc671a8372eb8b095311f091fddc6c3 3_500_000: 000000000000000a34ba20552c3cae9549b9c5ca07f644cf005328c948aa54d8 3_600_000: 000000000000000011031d9ff030cd9e6fe8a3766bbeda6f6337c40dd30fa65f + 3_700_000: 0000000000000006c6e7295efcf0929173cc47ece41afc652410b72f36cbeeda + 3_800_000: 00000000000000122f57d59c7f6736a83483dcf71c34978102d7e04ce4dc9a5d + 3_900_000: 00000000000000069edf3300d6c41451485d7aabdbea34425a2411b880e8a976 + 4_000_000: 00000000000000043b11a6c86c3cdaf773a5183737f136e196e816f862e1e3ba + 4_100_000: 0000000000000020822d529b6fcd8611f5a174b1f44a6c478a2fec64a80233ad + 4_200_000: 00000000000000052ffc34875fab4e545bc9dc76f1212c4fdafab3b6d7a026cd + 4_300_000: 000000000000000e1ea2af0e25087c0977e944dd0ffdae5fdff54dda85ed95be + 4_400_000: 0000000000000000020dab883c57e21829b590ef61ff5230f5fdc9d572300945 + 4_500_000: 00000000000000034d5ddf802a8ac8fbf17cf50747041e433d28d9f2bcb6ef02 + 4_600_000: 000000000000000055bb4e5b6d942da13cb631f318cfdc292793f28ef8a338ca + 4_700_000: 000000000000000002ae1d75811b1050fc98ee7ef30c48cde117ebbb42f47e22 + 4_800_000: 00000000000000000716b8d9e96591ba7cb2d02c3d2d1d98d514f41c240fdff7 + 4_900_000: 0000000000000000079b1c1ebf48d351a7d31dcc55c5b4cf79ade79089a20f5a + 5_000_000: 000000000000000006c9167db1cc7e93fcf1c3014da6c6221390d03d1640c9b3 SOFT_VOIDED_TX_IDS: - 0000000012a922a6887497bed9c41e5ed7dc7213cae107db295602168266cd02 diff --git a/hathor/conf/testnet.py b/hathor/conf/testnet.py index 2334a7d7e..f2d322489 100644 --- a/hathor/conf/testnet.py +++ b/hathor/conf/testnet.py @@ -53,6 +53,33 @@ cp(1_400_000, bytes.fromhex('000000000df9cb786c68a643a52a67c22ab54e8b8e41cbe9b761133f6c8abbfe')), cp(1_500_000, bytes.fromhex('000000000c3591805f4748480b59ac1788f754fc004930985a487580e2b5de8f')), cp(1_600_000, bytes.fromhex('00000000060adfdfd7d488d4d510b5779cf35a3c50df7bcff941fbb6957be4d2')), + cp(1_700_000, bytes.fromhex('0000000007afc04aebad15b14fcd93c1b5193dc503b190433f55be8c218b6d12')), + cp(1_800_000, bytes.fromhex('00000000126f16af2ba934a60cf8f2da32d3ed2688c56ce8ff477e483a3ffc42')), + cp(1_900_000, bytes.fromhex('0000000005d2a2ba2231663187b460396189af0ffca7b2e93fccc85cde04cbdc')), + cp(2_000_000, bytes.fromhex('000000000009a8451ff2d5ec54951d717da2766aedb3131485466cc993879ee1')), + cp(2_100_000, bytes.fromhex('0000000009f961804cd7f43da05f08a94a2fa09f82c7d605afc5982ab242a7e4')), + cp(2_200_000, bytes.fromhex('0000000002e260b970846a89c23e754a763e7c5f1578b6ec4e67bdb94c667997')), + cp(2_300_000, bytes.fromhex('0000000006e0894c8f7fd029fe446a42433875647759183ba3fbb0ff0b7ceb64')), + cp(2_400_000, bytes.fromhex('0000000011ab28f3be17e3a098307fa73750cc8d74f1f60cfb44b524a60c94ec')), + cp(2_500_000, bytes.fromhex('00000000045d2bcc10c896bfc7d1f28788e3530a81f50ee096f386eec772634f')), + cp(2_600_000, bytes.fromhex('000000000766b9ac25e2ece5685effa834e61284e38f368c841210606bb1fdfc')), + cp(2_700_000, bytes.fromhex('0000000005d0ee31d0f47f6ff9aa570b9f25b9d44a8a59cea0e0f8a1729b9c90')), + cp(2_800_000, bytes.fromhex('000000000a5bd4f266fa13d2c0594cabf6465758f7f5814bde626032706b81e5')), + cp(2_900_000, bytes.fromhex('000000000b11b0a09ff0d7c2cfd9228f31c53008e700532e439d3a3d9c63fb8e')), + cp(3_000_000, bytes.fromhex('00000000013289569569cd51580183a2c870dfe5a395adaa00ae66fefe51af3d')), + cp(3_100_000, bytes.fromhex('00000000170c55e6ec207400bfc42786c1e0c32fe045a1d815f930daf2bf3020')), + cp(3_200_000, bytes.fromhex('00000000149986cb99c202136bd388fb2a7fcba4bdfd6ac049069ac5e08a587f')), + cp(3_300_000, bytes.fromhex('000000000e16f87ac7133639cb52a99574944b8457939396e7faf1615fcfdb0f')), + cp(3_400_000, bytes.fromhex('000000000f551f6224a459904436072f5ff10fd3db17f2d7e25b1ef9b149c121')), + cp(3_500_000, bytes.fromhex('0000000006572b8cf41130e88776adf8583e970905df2afe593ca31c91ab0c4c')), + cp(3_600_000, bytes.fromhex('000000000215fcc7018cc31bbfb943ca43c6297529fa008bf34665f3ac64d340')), + cp(3_700_000, bytes.fromhex('000000000dbf5e8ab4f90f2187db6db429c9d0cb8169051ce8a9e79b810509d7')), + cp(3_800_000, bytes.fromhex('00000000030411ec36c7f5386a94e147460d86592f85459e0eadd5cd0e3da7b4')), + cp(3_900_000, bytes.fromhex('000000000bc2c7078a3c59d878196f1491aad45a0df9d312909d85482ac8d714')), + cp(4_000_000, bytes.fromhex('000000000eba0dae3ec27cf5596ef49731744edebadb9fbae42160b6aa2e2461')), + cp(4_100_000, bytes.fromhex('00000000052aa77fd8db71d5306257f9fe068c3401d95b17fcedcccfc9b76c82')), + cp(4_200_000, bytes.fromhex('00000000010a8dae043c84fcb2cef6a2b42a28279b95af20ab5a098acf2a3565')), + cp(4_300_000, bytes.fromhex('000000000019da781ef75fa5f59c5537d8ed18b64c589c3e036109cfb1d84f7d')), ], FEATURE_ACTIVATION=FeatureActivationSettings( default_threshold=15_120, # 15120 = 75% of evaluation_interval (20160) diff --git a/hathor/conf/testnet.yml b/hathor/conf/testnet.yml index 336794a22..f8dcf5290 100644 --- a/hathor/conf/testnet.yml +++ b/hathor/conf/testnet.yml @@ -35,6 +35,33 @@ CHECKPOINTS: 1_400_000: 000000000df9cb786c68a643a52a67c22ab54e8b8e41cbe9b761133f6c8abbfe 1_500_000: 000000000c3591805f4748480b59ac1788f754fc004930985a487580e2b5de8f 1_600_000: 00000000060adfdfd7d488d4d510b5779cf35a3c50df7bcff941fbb6957be4d2 + 1_700_000: 0000000007afc04aebad15b14fcd93c1b5193dc503b190433f55be8c218b6d12 + 1_800_000: 00000000126f16af2ba934a60cf8f2da32d3ed2688c56ce8ff477e483a3ffc42 + 1_900_000: 0000000005d2a2ba2231663187b460396189af0ffca7b2e93fccc85cde04cbdc + 2_000_000: 000000000009a8451ff2d5ec54951d717da2766aedb3131485466cc993879ee1 + 2_100_000: 0000000009f961804cd7f43da05f08a94a2fa09f82c7d605afc5982ab242a7e4 + 2_200_000: 0000000002e260b970846a89c23e754a763e7c5f1578b6ec4e67bdb94c667997 + 2_300_000: 0000000006e0894c8f7fd029fe446a42433875647759183ba3fbb0ff0b7ceb64 + 2_400_000: 0000000011ab28f3be17e3a098307fa73750cc8d74f1f60cfb44b524a60c94ec + 2_500_000: 00000000045d2bcc10c896bfc7d1f28788e3530a81f50ee096f386eec772634f + 2_600_000: 000000000766b9ac25e2ece5685effa834e61284e38f368c841210606bb1fdfc + 2_700_000: 0000000005d0ee31d0f47f6ff9aa570b9f25b9d44a8a59cea0e0f8a1729b9c90 + 2_800_000: 000000000a5bd4f266fa13d2c0594cabf6465758f7f5814bde626032706b81e5 + 2_900_000: 000000000b11b0a09ff0d7c2cfd9228f31c53008e700532e439d3a3d9c63fb8e + 3_000_000: 00000000013289569569cd51580183a2c870dfe5a395adaa00ae66fefe51af3d + 3_100_000: 00000000170c55e6ec207400bfc42786c1e0c32fe045a1d815f930daf2bf3020 + 3_200_000: 00000000149986cb99c202136bd388fb2a7fcba4bdfd6ac049069ac5e08a587f + 3_300_000: 000000000e16f87ac7133639cb52a99574944b8457939396e7faf1615fcfdb0f + 3_400_000: 000000000f551f6224a459904436072f5ff10fd3db17f2d7e25b1ef9b149c121 + 3_500_000: 0000000006572b8cf41130e88776adf8583e970905df2afe593ca31c91ab0c4c + 3_600_000: 000000000215fcc7018cc31bbfb943ca43c6297529fa008bf34665f3ac64d340 + 3_700_000: 000000000dbf5e8ab4f90f2187db6db429c9d0cb8169051ce8a9e79b810509d7 + 3_800_000: 00000000030411ec36c7f5386a94e147460d86592f85459e0eadd5cd0e3da7b4 + 3_900_000: 000000000bc2c7078a3c59d878196f1491aad45a0df9d312909d85482ac8d714 + 4_000_000: 000000000eba0dae3ec27cf5596ef49731744edebadb9fbae42160b6aa2e2461 + 4_100_000: 00000000052aa77fd8db71d5306257f9fe068c3401d95b17fcedcccfc9b76c82 + 4_200_000: 00000000010a8dae043c84fcb2cef6a2b42a28279b95af20ab5a098acf2a3565 + 4_300_000: 000000000019da781ef75fa5f59c5537d8ed18b64c589c3e036109cfb1d84f7d FEATURE_ACTIVATION: default_threshold: 15_120 # 15120 = 75% of evaluation_interval (20160)