- <div>from hashlib import sha256
- from datetime import datetime H O+ i- @" X, R3 l* U) N( N
- def generate_block(oldblock, bpm, address):
- """7 z. }+ T% C1 }+ p
- :param oldblock:; C: t" D/ K. X+ \0 C
- :param bpm:' J& M# Y' |3 H- ^) f
- :param address:2 {7 w* _1 Y* i. f/ v' P& ?# r
- :return:5 V5 k' n2 W+ P# G5 F4 [' D. {3 L
- """# Q0 `5 b" l$ G# _4 Z: j
- newblock = {
- "Index": oldblock["Index"] + 1,
- "BPM": bpm,2 R' U1 Y' B5 @
- "Timestamp": str(datetime.now()),! P2 J" `0 u- R* ]3 G2 U
- "PrevHash": oldblock["Hash"],
- "Validator": address
- }
- newblock["Hash"] = calculate_hash(newblock)
- return newblock
- def calculate_hash(block):
- record = "".join([; v( b3 p Q1 X K
- str(block["Index"]),6 S# [/ R2 _. I3 D4 D4 d
- str(block["BPM"]),
- block["Timestamp"],! _# K8 ?5 \7 v, q/ M$ I, e( H
- block["PrevHash"]
- ])& J9 x; y" y9 G& _! E
- return sha256(record.encode()).hexdigest()
- def is_block_valid(newblock, oldblock):! b; |% {: q( S/ B
- """& A" L( y" e2 h/ a: B2 \
- :param newblock:
- :param oldblock:( ?9 y" ]- p" J F) }8 @
- :return:" [) h% }, D, f, U: J- L6 _8 E
- """. m* r+ w3 Y& C3 W& j2 A# T
- if oldblock["Index"] + 1 != newblock["Index"]:+ G5 f) L2 j' J5 R! S$ C/ E! @$ V
- return False3 b2 n8 [* | H( x: s
- if oldblock["Hash"] != newblock["PrevHash"]:2 I8 d$ }+ B- D3 ~' J% i
- return False
- if calculate_hash(newblock) != newblock["Hash"]:/ T9 f. N2 x! b6 N* p
- return False
- return True</div>
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer; F( A8 l; m, a; x! e& g H6 K
- def run():
- # start a tcp server8 p7 i8 x$ ?% g. j# Z
- serv = ThreadingTCPServer(('', 9090), HandleConn)) [) e4 L. Q( B2 j% e' a1 Y
- serv.serve_forever()</div>
- ' I* y" E ~, r! [+ l( v9 x. _
- <div>import threading9 \" W) L* C; i8 j$ M. z5 V. t
- from queue import Queue, Empty: I$ C; d k' z6 g; M
- # 定义变量5 f2 [) h6 |8 i' d! u
- block_chain = []
- temp_blocks = []# F7 j4 w6 q6 o1 I1 K# F) R
- candidate_blocks = Queue() # 创建队列,用于线程间通信: q+ @+ c% P" v& w2 V9 _9 r
- announcements = Queue(). E7 b3 e6 l* ]# w, j" s
- validators = {}
- My_Lock = threading.Lock()
- class HandleConn(BaseRequestHandler):
- def handle(self):
- print("Got connection from", self.client_address)& W# Q" q* p) V& ?2 Y6 ^
- # validator address" I$ i% N) u I Y* O. y
- self.request.send(b"Enter token balance:")
- balance = self.request.recv(8192)' r/ O) {6 d) p% g
- try:2 l& q, z$ ]# H; h- t; ^; Z
- balance = int(balance)& E7 {8 X3 P- I4 f) X2 j0 J
- except Exception as e:
- print(e)
- t = str(datetime.now())8 N1 F$ Z- m `" J
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance4 w6 B; i6 d# t& r+ [# n/ r
- print(validators)
- while True:
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,), v; q6 k4 E. |, r) e
- daemon=True)4 Y% J5 F# o4 P4 [
- announce_winner_t.start()/ U1 Q/ @% e8 X0 _+ W! A, c2 s% Y: K
- self.request.send(b"\nEnter a new BPM:")' A m/ _3 \3 _, @ |- a6 G
- bpm = self.request.recv(8192)1 b" |' P) ?" {7 l
- try:* b4 k! Q: g& @2 O
- bpm = int(bpm)9 `- {" W D6 k) x' C% }
- except Exception as e:
- print(e)
- del validators[address], a3 w L7 w* b* f- @; F: R* z
- break
- # with My_Lock:
- last_block = block_chain[-1]2 a$ @ C% I, Z% B4 m4 ?- K2 n: v
- new_block = generate_block(last_block, bpm, address)
- if is_block_valid(new_block, last_block):! H1 @' ^2 g0 }+ S- b6 i
- print("new block is valid!")5 q$ X6 X4 C' @; H' j" O" x: ^
- candidate_blocks.put(new_block)
- self.request.send(b"\nEnter a new BPM:\n"). |7 u9 s- O/ n3 `
- annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)+ Q$ k0 N$ e) X- K
- annouce_blockchain_t.start()</div>
- <div># validator address
- self.request.send(b"Enter token balance:"). \& U N5 C+ ^9 Q
- balance = self.request.recv(8192)# t1 @6 l8 C% Q3 A" E* P: M* S
- try:" j2 Q, C, q' n' H9 s
- balance = int(balance)( B+ e' b) k6 T7 Y$ r1 |) {; z
- except Exception as e:# s2 t- j% n, }6 n; o% G4 D6 r( q- V
- print(e)
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest(), `, v/ V3 B* |: Z) Y: x
- validators[address] = balance' l# c3 O& {# _4 k5 j* f: i6 C+ W+ K
- print(validators)</div>
- . D: g: t) f% q' a
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),4 `" |( ~: Z6 M+ P `# B7 A# |
- daemon=True)4 i2 ~! i& j% y- d% U3 E. w: G
- announce_winner_t.start()
- def annouce_winner(announcements, request):8 x# o! ?! [$ v0 Y' O M! R7 O j
- """
- :param announcements:
- :param request:) \7 U9 x7 Z3 G& m' y7 b
- :return:1 B- Y; Q4 N3 F& w7 |* u* y
- """
- while True:, C. T. L* k0 O0 {* W* l6 A; x- J
- try:7 L# c T1 i& D) u: h
- msg = announcements.get(block=False); [7 a, D$ w" Z; A; J' d
- request.send(msg.encode())
- request.send(b'\n')
- except Empty:
- time.sleep(3)& z& g5 }: E5 ~4 k
- continue</div>
- 5 T( a) M% r4 W" u4 B! @3 L
- <div>self.request.send(b"\nEnter a new BPM:")
- bpm = self.request.recv(8192)* i: ^, p( O/ e; C1 d
- try:
- bpm = int(bpm)( B I' r6 X8 G5 h0 @7 l
- except Exception as e:
- print(e)
- del validators[address]
- break2 t) w8 u9 s2 f5 @$ s: U, H8 D" l
- # with My_Lock:
- last_block = block_chain[-1]
- new_block = generate_block(last_block, bpm, address)# r+ y( i5 P2 _
- if is_block_valid(new_block, last_block):
- print("new block is valid!")
- candidate_blocks.put(new_block)</div>
- . R3 P5 ^* x% w! u* y
- <div>annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)
- annouce_blockchain_t.start()9 {7 W1 I _3 @. k* c) g
- def annouce_blockchain(request):3 I7 P( E6 U* X! ^
- """ u/ |! g! s9 z# |7 \+ Y" r
- :param request:9 a% g# m* X. U
- :return:, O8 j+ b- w8 r0 ^
- """' @3 a* H R. X
- while True:
- time.sleep(30)
- with My_Lock:2 }* t' s( ?" {" h; H3 }) [+ I% Y
- output = json.dumps(block_chain)
- try:6 L. `; w* X, o7 h
- request.send(output.encode())+ l' t8 G5 n' p( D5 U# E
- request.send(b'\n'). V$ E; d( R/ H" Y5 Y4 l) m
- except OSError:! G. y: n* K; u4 ]; X- L9 v z9 u6 a
- pass</div>
- ) g6 q A7 Z, ~7 U8 N9 ?/ w- {" a
- <div>def pick_winner(announcements):
- """
- 选择记账人, C7 _" ^# l; [% o/ L
- :param announcements:' J( D+ |4 i+ G' f5 t( f
- :return:
- """
- time.sleep(10)* P9 a' _7 i/ i6 u% T0 A6 w7 J
- while True:/ A. K5 r3 ^( _' O
- with My_Lock:9 H# p$ p; x+ x# l- z; h. J
- temp = temp_blocks. n0 e7 r9 [8 Z2 K _4 b0 m
- lottery_pool = [] #
- if temp:
- for block in temp:: P5 A6 T$ U" q' x! b
- if block["Validator"] not in lottery_pool:
- set_validators = validators
- k = set_validators.get(block["Validator"])7 `: x* ?. o1 O: C% Q# K6 s
- if k:: y0 M+ m+ P8 ]6 {
- for i in range(k):$ R v' P$ l* o4 ~' f2 S ]
- lottery_pool.append(block["Validator"])
- lottery_winner = choice(lottery_pool)
- print(lottery_winner)5 `, p* \6 P/ q2 A- M/ @
- # add block of winner to blockchain and let all the other nodes known% P- _* W( M- r
- for block in temp:
- if block["Validator"] == lottery_winner:
- with My_Lock:
- block_chain.append(block)
- # write message in queue.1 S j) ?- I) g2 z; r
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner)
- announcements.put(msg)
- break) R, u: `5 j# I4 L$ B7 e/ b4 G
- with My_Lock:
- temp_blocks.clear()</div>
- <div>def run():( |8 K3 Y. L6 y
- # create a genesis block
- t = str(datetime.now())( r5 t+ B+ z' L% k l/ z2 `
- genesis_block = {4 h0 h& h. |3 M# ?
- "Index": 0,
- "Timestamp": t,
- "BPM": 0,8 O/ r5 o" [4 g2 l. b9 C( g
- "PrevHash": "",. `) h* o+ F6 J9 A% c7 B
- "Validator": ""
- }
- genesis_block["Hash"] = calculate_hash(genesis_block)
- print(genesis_block)6 \8 J* r3 e z0 s
- block_chain.append(genesis_block)
- thread_canditate = threading.Thread(target=candidate, args=(candidate_blocks,), daemon=True)2 E' f1 @: {! A9 q ^& k8 V" `
- thread_pick = threading.Thread(target=pick_winner, args=(announcements,), daemon=True)
- thread_canditate.start()$ [, m' }) E' j; d* ^
- thread_pick.start()
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()& t+ |& \; ~* x! x4 m
- def candidate(candidate_blocks):. r! C. ]. C* @2 R
- """
- :param candidate_blocks:
- :return:) h9 {! h9 N' T4 V2 R; \5 s1 E
- """
- while True:
- try:2 P! ?7 j# d+ Q2 r- M& q; l
- candi = candidate_blocks.get(block=False)
- except Empty:
- time.sleep(5)
- continue# l6 |* q9 \& ? m p
- temp_blocks.append(candi)
- if __name__ == '__main__':
- run()</div>