Coverage for silkaj/blockchain/blocks.py: 20%

79 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-20 12:29 +0000

1# Copyright 2016-2025 Maël Azimi <m.a@moul.re> 

2# 

3# Silkaj is free software: you can redistribute it and/or modify 

4# it under the terms of the GNU Affero General Public License as published by 

5# the Free Software Foundation, either version 3 of the License, or 

6# (at your option) any later version. 

7# 

8# Silkaj is distributed in the hope that it will be useful, 

9# but WITHOUT ANY WARRANTY; without even the implied warranty of 

10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

11# GNU Affero General Public License for more details. 

12# 

13# You should have received a copy of the GNU Affero General Public License 

14# along with Silkaj. If not, see <https://www.gnu.org/licenses/>. 

15 

16import time 

17from operator import itemgetter 

18from urllib.error import HTTPError 

19 

20import arrow 

21import rich_click as click 

22from duniterpy.api import bma 

23 

24from silkaj import tui 

25from silkaj.blockchain.tools import get_head_block 

26from silkaj.constants import ALL, BMA_SLEEP 

27from silkaj.network import client_instance 

28from silkaj.wot.tools import identity_of 

29 

30 

31@click.command("blocks", help="Display blocks: default: 0 for current window size") 

32@click.argument("number", default=0, type=click.IntRange(0, 5000)) 

33@click.option( 

34 "--detailed", 

35 "-d", 

36 is_flag=True, 

37 help="Force detailed view. Compact view happen over 30 blocks", 

38) 

39def list_blocks(number: int, detailed: bool) -> None: 

40 head_block = get_head_block() 

41 current_nbr = head_block["number"] 

42 if number == 0: 

43 number = head_block["issuersFrame"] 

44 client = client_instance() 

45 blocks = client(bma.blockchain.blocks, number, current_nbr - number + 1) 

46 issuers = [] 

47 issuers_dict = {} 

48 for block in blocks: 

49 issuer = {} 

50 issuer["pubkey"] = block["issuer"] 

51 if detailed or number <= 30: 

52 issuer["block"] = block["number"] 

53 issuer["gentime"] = arrow.get(block["time"]).to("local").format(ALL) 

54 issuer["mediantime"] = ( 

55 arrow.get(block["medianTime"]).to("local").format(ALL) 

56 ) 

57 issuer["hash"] = block["hash"][:10] 

58 issuer["powMin"] = block["powMin"] 

59 issuers_dict[issuer["pubkey"]] = issuer 

60 issuers.append(issuer) 

61 for pubkey in issuers_dict.items(): 

62 issuer = issuers_dict[pubkey[0]] 

63 time.sleep(BMA_SLEEP) 

64 try: 

65 idty = identity_of(issuer["pubkey"]) 

66 except HTTPError: 

67 idty = None 

68 for issuer2 in issuers: 

69 if ( 

70 issuer2.get("pubkey") is not None 

71 and issuer.get("pubkey") is not None 

72 and issuer2["pubkey"] == issuer["pubkey"] 

73 ): 

74 issuer2["uid"] = idty["uid"] if idty else None 

75 issuer2.pop("pubkey") 

76 print_blocks_views(issuers, current_nbr, number, detailed) 

77 

78 

79def print_blocks_views(issuers, current_nbr, number, detailed): 

80 header = ( 

81 f"Last {number} blocks from n°{current_nbr - number + 1} to n°{current_nbr}" 

82 ) 

83 print(header, end=" ") 

84 if detailed or number <= 30: 

85 sorted_list = sorted(issuers, key=itemgetter("block"), reverse=True) 

86 

87 table = tui.Table(style="columns") 

88 table.set_cols_align(["r", "r", "r", "r", "r", "l"]) 

89 table.set_cols_dtype(["i", "t", "t", "t", "i", "t"]) 

90 table.fill_from_dict_list(sorted_list) 

91 table.set_cols_align(["r", "r", "r", "r", "r", "l"]) 

92 table.set_cols_dtype(["i", "t", "t", "t", "i", "t"]) 

93 print(f"\n{table.draw()}") 

94 

95 else: 

96 list_issued = [] 

97 for issuer in issuers: 

98 found = False 

99 for issued in list_issued: 

100 if issued.get("uid") is not None and issued["uid"] == issuer["uid"]: 

101 issued["blocks"] += 1 

102 found = True 

103 break 

104 if not found: 

105 issued = {} 

106 issued["uid"] = issuer["uid"] 

107 issued["blocks"] = 1 

108 list_issued.append(issued) 

109 for issued in list_issued: 

110 issued["percent"] = round(issued["blocks"] / number * 100) 

111 sorted_list = sorted(list_issued, key=itemgetter("blocks"), reverse=True) 

112 table = tui.Table(style="columns") 

113 table.fill_from_dict_list(sorted_list) 

114 table.set_cols_align(["l", "r", "r"]) 

115 table.set_cols_dtype(["t", "i", "i"]) 

116 print(f"from {len(list_issued)} issuers\n{table.draw()}")