Repository: bitcoin/bitcoin
File: contrib/asmap/asmap-tool.py (Python)

Code before:
    elif args.subcommand == "encode":
        state = load_file(args.infile)
        save_binary(args.outfile, state, fill=args.fill)
    elif args.subcommand == "decode":
        state = load_file(args.infile)
        save_text(args.outfile, state, fill=args.fill, overlapping=args.overlapping)
    elif args.subcommand == "diff":
        state1 = load_file(args.infile1)
        state2 = load_file(args.infile2)
        ipv4_changed = 0
        ipv6_changed = 0
        for prefix, old_asn, new_asn in state1.diff(state2):
            if args.ignore_unassigned and old_asn == 0:
                continue
            net = asmap.prefix_to_net(prefix)
            if isinstance(net, ipaddress.IPv4Network):
                ipv4_changed += 1 << (32 - net.prefixlen)
            elif isinstance(net, ipaddress.IPv6Network):
                ipv6_changed += 1 << (128 - net.prefixlen)
            if new_asn == 0:
                print(f"# {net} was AS{old_asn}")
            elif old_asn == 0:
                print(f"{net} AS{new_asn} # was unassigned")
            else:
                print(f"{net} AS{new_asn} # was AS{old_asn}")
        ipv4_change_str = "" if ipv4_changed == 0 else f" (2^{math.log2(ipv4_changed):.2f})"
        ipv6_change_str = "" if ipv6_changed == 0 else f" (2^{math.log2(ipv6_changed):.2f})"

        print(
            f"# {ipv4_changed}{ipv4_change_str} IPv4 addresses changed; "
            f"{ipv6_changed}{ipv6_change_str} IPv6 addresses changed"
        )
    elif args.subcommand == "diff_addrs":
        state1 = load_file(args.infile1)
        state2 = load_file(args.infile2)
        address_info = json.load(args.addrs_file)
        addrs = {a["address"] for a in address_info if a["network"] in ["ipv4", "ipv6"]}
        reassignments = defaultdict(list)
        for addr in addrs:
            net = ipaddress.ip_network(addr)
            prefix = asmap.net_to_prefix(net)
            old_asn = state1.lookup(prefix)
            new_asn = state2.lookup(prefix)
            if new_asn != old_asn:
                reassignments[(old_asn, new_asn)].append(addr)
        reassignments = sorted(reassignments.items(), key=lambda item: len(item[1]), reverse=True)
        num_reassignment_type = defaultdict(int)
        for (old_asn, new_asn), reassigned_addrs in reassignments:
            num_reassigned = len(reassigned_addrs)
            num_reassignment_type[(bool(old_asn), bool(new_asn))] += num_reassigned
            old_asn_str = f"AS{old_asn}" if old_asn else "unassigned"

Review comment (suggestion):
NIT: since we are touching the code, it would be nice to update the code to be a little bit more performant (and modern)  

```suggestion
            net = asmap.prefix_to_net(prefix)
            num_addrs = net.num_addresses
            if isinstance(net, ipaddress.IPv4Network):
                ipv4_changed += num_addrs
                ipv4_entries_changed += 1
            else:  # IPv6Network
                ipv6_changed += num_addrs
                ipv6_entries_changed += 1
            if new_asn == 0:
                print(f"# {net} was AS{old_asn}")
            elif old_asn == 0:
```

Code after:
    elif args.subcommand == "encode":
        state = load_file(args.infile)
        save_binary(args.outfile, state, fill=args.fill)
    elif args.subcommand == "decode":
        state = load_file(args.infile)
        save_text(args.outfile, state, fill=args.fill, overlapping=args.overlapping)
    elif args.subcommand == "diff":
        state1 = load_file(args.infile1)
        state2 = load_file(args.infile2)
        ipv4_changed = 0
        ipv4_entries_changed = 0
        ipv6_changed = 0
        ipv6_entries_changed = 0
        for prefix, old_asn, new_asn in state1.diff(state2):
            if args.ignore_unassigned and old_asn == 0:
                continue
            net = asmap.prefix_to_net(prefix)
            if isinstance(net, ipaddress.IPv4Network):
                ipv4_changed += net.num_addresses
                ipv4_entries_changed += 1
            elif isinstance(net, ipaddress.IPv6Network):
                ipv6_changed += net.num_addresses
                ipv6_entries_changed += 1
            if new_asn == 0:
                print(f"# {net} was AS{old_asn}")
            elif old_asn == 0:
                print(f"{net} AS{new_asn} # was unassigned")
            else:
                print(f"{net} AS{new_asn} # was AS{old_asn}")
        ipv4_change_str = "" if ipv4_changed == 0 else f" (2^{math.log2(ipv4_changed):.2f})"
        ipv6_change_str = "" if ipv6_changed == 0 else f" (2^{math.log2(ipv6_changed):.2f})"

        print(
f"""# Summary
IPv4: {ipv4_entries_changed} entries with {ipv4_changed}{ipv4_change_str} addresses changed
IPv6: {ipv6_entries_changed} entries with {ipv6_changed}{ipv6_change_str} addresses changed"""
        )
    elif args.subcommand == "diff_addrs":
        state1 = load_file(args.infile1)
        state2 = load_file(args.infile2)
        address_info = json.load(args.addrs_file)
        addrs = {a["address"] for a in address_info if a["network"] in ["ipv4", "ipv6"]}
        reassignments = defaultdict(list)
        for addr in addrs:
            net = ipaddress.ip_network(addr)
            prefix = asmap.net_to_prefix(net)
            old_asn = state1.lookup(prefix)
            new_asn = state2.lookup(prefix)
            if new_asn != old_asn:
                reassignments[(old_asn, new_asn)].append(addr)
        reassignments = sorted(reassignments.items(), key=lambda item: len(item[1]), reverse=True)