- 7 D, b; v' Y: R: S- J
- <div>from hashlib import sha256
- from datetime import datetime: o& j$ c- b. v# X. z" L
- def generate_block(oldblock, bpm, address):" }& W/ }$ Y( } J/ W
- """
- :param oldblock:
- :param bpm: O0 U5 z) O, p" U; L2 s! ~8 `9 u
- :param address:
- :return:
- """) I3 u- d" D+ K2 X% J) z! c
- newblock = {
- "Index": oldblock["Index"] + 1,
- "BPM": bpm,6 _- |. P# m% L
- "Timestamp": str(datetime.now()),
- "PrevHash": oldblock["Hash"],
- "Validator": address! F' Y: W$ m: A6 E' W* C9 P
- } ^8 O: i. Q" x5 x2 ~' Y
- newblock["Hash"] = calculate_hash(newblock)
- return newblock
- def calculate_hash(block):
- record = "".join([9 c4 L; _" P3 W
- str(block["Index"]),
- str(block["BPM"]),) N4 x" q3 L1 n# w5 F) f
- block["Timestamp"],
- block["PrevHash"]
- ])
- return sha256(record.encode()).hexdigest(), G( m/ v I. K7 }( l
- def is_block_valid(newblock, oldblock):1 T3 G+ W* M5 g
- """
- :param newblock:
- :param oldblock:7 p# ]- R6 W% o, r% h5 y
- :return:& O: ~: z- J# c* E- h
- """
- if oldblock["Index"] + 1 != newblock["Index"]:
- return False
- if oldblock["Hash"] != newblock["PrevHash"]:
- return False) `9 X% D8 h* O3 b' A: y) ?
- if calculate_hash(newblock) != newblock["Hash"]:
- return False0 M, _9 v* E4 z, }) W8 ?; R
- return True</div>
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer
- def run():
- # start a tcp server- f4 S+ t7 k" A3 N8 I. K4 v
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()</div>
- 7 N) a* x9 U' x0 g( c6 a" N% N- ]
- <div>import threading
- from queue import Queue, Empty+ M. L y& U( |4 C' U$ P/ J
- # 定义变量
- block_chain = []7 J% U Y; w2 p+ Q& I+ D
- temp_blocks = []
- candidate_blocks = Queue() # 创建队列,用于线程间通信0 Q% t q1 D, P* r$ Z8 M
- announcements = Queue()
- validators = {}
- My_Lock = threading.Lock()# j* A# p8 j+ a I1 ]& v% c
- class HandleConn(BaseRequestHandler):
- def handle(self):9 e6 S0 u- I# {7 V) _. o2 U
- print("Got connection from", self.client_address)
- # validator address8 i, I' K4 y+ V2 G
- self.request.send(b"Enter token balance:")
- balance = self.request.recv(8192)4 g! a: r% r+ t; O* u2 B" N/ m9 Q
- try:
- balance = int(balance)/ n+ G, y( U: [/ e
- except Exception as e:
- print(e)
- t = str(datetime.now())5 P$ T3 `: ~; p% k7 N
- address = sha256(t.encode()).hexdigest()* A M* r/ z+ h& t. S/ {4 d% f
- validators[address] = balance: ]3 @# u$ o/ F0 M0 H, N
- print(validators)
- while True:! g: y: d7 M2 ~$ y) X
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),6 L2 ?; p# A5 {$ d0 g4 Y
- daemon=True)
- announce_winner_t.start()- z% z0 j# C& @$ K
- self.request.send(b"\nEnter a new BPM:")
- bpm = self.request.recv(8192)
- try:- i" K) V& C0 r* ?/ z
- bpm = int(bpm)4 ]- h) {. o5 X6 [, b
- except Exception as e:! D2 D/ ~3 `1 T! N$ T5 Y2 a) {- |% _8 ?
- print(e)
- del validators[address]" _( C: F5 I8 h( ^& ?
- break
- # with My_Lock:
- last_block = block_chain[-1]
- new_block = generate_block(last_block, bpm, address)
- if is_block_valid(new_block, last_block):3 u/ `; ^6 d' w- C# R% p
- print("new block is valid!")
- candidate_blocks.put(new_block)
- self.request.send(b"\nEnter a new BPM:\n")
- annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)
- annouce_blockchain_t.start()</div>
- <div># validator address; j. Q1 Q, l3 G8 y o; M) \
- self.request.send(b"Enter token balance:")
- balance = self.request.recv(8192)
- try:1 D5 q4 |' `+ K' i/ l
- balance = int(balance)' l/ p' }' l. X1 ]! V3 N. n
- except Exception as e:
- print(e)
- t = str(datetime.now()); _. Q, m! ]9 e7 G _ {
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance
- print(validators)</div>
- " g+ z5 m1 R G" m6 W
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
- daemon=True)6 x) P* G% G: U, s9 l4 F8 D
- announce_winner_t.start()1 L/ T! L( f) \, G4 q6 o0 z3 z+ \
- def annouce_winner(announcements, request):
- """2 s8 F$ q2 D* w) O( G6 e1 `
- :param announcements:
- :param request:
- :return:( R( f% A7 j0 B2 ]9 p( Y5 u! z
- """5 b$ G" j& ^' l0 P: B
- while True:
- try:
- msg = announcements.get(block=False); F5 e, a, a$ b) Q1 ^6 n0 s/ ^
- request.send(msg.encode())
- request.send(b'\n')" t) R' j4 x1 D' m; k0 }& R
- except Empty:
- time.sleep(3)& ?/ d% k* g1 s% h0 V; p4 o
- continue</div>
- # P' O$ L* I0 y
- <div>self.request.send(b"\nEnter a new BPM:")' O6 n* g0 M: L+ y
- bpm = self.request.recv(8192)
- try:, P' E8 F$ j r) k: Y) `0 F+ ]
- bpm = int(bpm)
- except Exception as e:
- print(e)! h2 j5 Y+ T: K2 z
- del validators[address]4 n5 k) P5 ~, l4 k
- break" i1 j: W5 L4 w# F. M8 z3 o+ A
- # with My_Lock:
- last_block = block_chain[-1]
- new_block = generate_block(last_block, bpm, address)* ^& b; ^9 Y2 m& y6 Q: N$ ~
- if is_block_valid(new_block, last_block):# O7 P7 p! b7 q
- print("new block is valid!")
- candidate_blocks.put(new_block)</div>
- <div>annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)& M$ x M# r3 ?1 u5 n* h
- annouce_blockchain_t.start()
- def annouce_blockchain(request):
- """9 s" y! o- c; {' o" _3 g8 W: n5 Q
- :param request:4 k% O6 \& T) I x3 ^
- :return:9 M" g1 u. V; h4 R) n
- """- K" A. w0 E R
- while True:0 Q3 I! B4 q8 z0 A0 ?8 B, g
- time.sleep(30)( ]( A$ |6 Z8 a5 Z2 M* }
- with My_Lock:
- output = json.dumps(block_chain)! v4 e) c; u2 K3 R; X# h' b, K
- try:- v) R/ B3 x0 p/ g4 f. m1 G$ g! B
- request.send(output.encode())' h" |" T2 s* q& e' n. V
- request.send(b'\n'): i/ d8 @% E( D! F8 Z+ k
- except OSError:' r3 ^. x/ b/ }! b4 Z- ~
- pass</div>
- : \- h) G/ |/ M N$ H6 f3 v& b. |3 I
- <div>def pick_winner(announcements):" g+ G9 ~9 ^9 _& K$ e
- """
- 选择记账人$ F) y2 N7 {0 S& c( Q" O( g
- :param announcements:
- :return:, J6 s2 {- n0 h; z
- """
- time.sleep(10)
- while True:% N6 q7 a0 h. p. R
- with My_Lock:% e+ z0 s. V+ F$ o0 k
- temp = temp_blocks
- lottery_pool = [] #
- if temp:& u' s/ m4 A: }: {1 |
- for block in temp:& c+ r' o9 B& X/ T, E) ^8 I* M
- if block["Validator"] not in lottery_pool:
- set_validators = validators
- k = set_validators.get(block["Validator"])0 t6 Y% P: n9 f7 C
- if k:
- for i in range(k):& c) C4 N4 n) r6 ? R+ y
- lottery_pool.append(block["Validator"])! k0 U- G! ?; J# U% w! U0 J
- lottery_winner = choice(lottery_pool)9 d( c( q1 n+ G% T N% N+ O
- print(lottery_winner)
- # add block of winner to blockchain and let all the other nodes known4 l# K E; r* J+ m; F5 Q7 n
- for block in temp:
- if block["Validator"] == lottery_winner:4 S4 y1 |: p* x# E, M
- with My_Lock:
- block_chain.append(block)
- # write message in queue.0 v; z* u# {/ l2 b0 Q" p* W9 E
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner)
- announcements.put(msg)
- break: I0 v. D! Z# I \1 |7 f/ s
- with My_Lock:. }+ r/ C! [8 Y' o3 A. j- j! U
- temp_blocks.clear()</div>
- <div>def run():7 {1 t" D9 G7 I U- A
- # create a genesis block
- t = str(datetime.now())+ B* Y! h; I/ G; _
- genesis_block = {
- "Index": 0,
- "Timestamp": t,
- "BPM": 0,
- "PrevHash": "",
- "Validator": ""- i+ w) {! p$ i3 G" R! B
- }9 R. k3 z3 I/ M4 z
- genesis_block["Hash"] = calculate_hash(genesis_block)- Z" F9 L7 z' \2 [" |) A# l- d' H
- print(genesis_block)+ ~* ?6 X/ W; V2 }) S% @- W; ?- f
- block_chain.append(genesis_block)
- thread_canditate = threading.Thread(target=candidate, args=(candidate_blocks,), daemon=True)! G) D9 V( X U% s
- thread_pick = threading.Thread(target=pick_winner, args=(announcements,), daemon=True)0 ` V5 w3 S( Y# e
- thread_canditate.start()
- thread_pick.start()2 E6 g3 c$ M5 o5 L2 d0 D7 b
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)" a6 _5 ]- d, w1 U9 r! Q
- serv.serve_forever() y: L. V: e7 u X- [! x
- def candidate(candidate_blocks):
- """9 H3 R2 P6 f- C W9 T4 b
- :param candidate_blocks:
- :return:
- """
- while True:
- try:* i( D4 g1 i1 [ T
- candi = candidate_blocks.get(block=False)/ X: e' E5 M/ k3 ^* O3 k0 _; Z; {7 p- A
- except Empty:; \. ^. @. K. t7 P* L+ J' i
- time.sleep(5)
- continue! z5 e. \/ U) y/ N% J9 o; x% P6 u
- temp_blocks.append(candi)" R# ?3 V5 X- v, X) n
- if __name__ == '__main__':; e9 S6 N2 U8 N* c" F, h
- run()</div>