- * \4 i- f9 s4 }; v9 W, k
- <div>from hashlib import sha256# o7 b3 e. u }- q' t* k2 E
- from datetime import datetime0 a9 s# h7 s3 y% O9 m" N% _! V
- def generate_block(oldblock, bpm, address):
- """
- :param oldblock:8 I; g7 ]6 m" U7 _3 u" K
- :param bpm:
- :param address:4 s [6 X& s1 P& d) t0 o
- :return:! c7 x1 F3 ^% v: G4 T$ Y2 z% M! b7 m
- """9 U& r5 H& c" }$ H! M; @
- newblock = {
- "Index": oldblock["Index"] + 1,
- "BPM": bpm,; [, g( Q" L' I6 x2 k1 `, Y' ^" _/ E
- "Timestamp": str(datetime.now()),7 F' e1 m3 _) E& h3 u3 _% l
- "PrevHash": oldblock["Hash"],9 U: v7 {4 `3 p4 \5 L% V# G
- "Validator": address
- }
- newblock["Hash"] = calculate_hash(newblock)
- return newblock
- def calculate_hash(block):
- record = "".join([
- str(block["Index"]),
- str(block["BPM"]),
- block["Timestamp"],) T- O* T& h m4 H
- block["PrevHash"]1 m/ B1 O4 @4 U5 h' S$ l2 R/ B
- ])1 {4 K2 k' @+ I" j
- return sha256(record.encode()).hexdigest()
- def is_block_valid(newblock, oldblock):6 j& ?" \" a# _/ l
- """
- :param newblock:
- :param oldblock:6 |3 Z* [8 [$ y" [2 q. Z; d. y" R
- :return:
- """
- if oldblock["Index"] + 1 != newblock["Index"]:
- return False: ?" T) D+ F$ O2 d, }1 f
- if oldblock["Hash"] != newblock["PrevHash"]:3 Y3 k6 o3 Z( w5 u7 v* M9 ?3 Y/ y
- return False
- if calculate_hash(newblock) != newblock["Hash"]:
- return False
- return True</div>
- + |& O/ t: c, n. t( v- [
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer
- def run():0 _' q% C1 N7 K9 o, G+ b
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()</div>
- 2 t8 M: Y' C; w8 a
- <div>import threading
- from queue import Queue, Empty
- # 定义变量
- block_chain = []
- temp_blocks = []
- candidate_blocks = Queue() # 创建队列,用于线程间通信) r& m$ ^: r/ q3 c+ ^9 O0 Q
- announcements = Queue()
- validators = {}* g1 d, ~ K6 y- W/ {& q
- My_Lock = threading.Lock()
- class HandleConn(BaseRequestHandler):- X8 |( S9 s$ Z) {. B# b5 Y
- def handle(self):
- print("Got connection from", self.client_address)
- # validator address4 B- p/ v, x- [4 Q- R. H2 q
- self.request.send(b"Enter token balance:")+ A: Q r6 e* d' i, c
- balance = self.request.recv(8192)
- try:
- balance = int(balance)9 j4 R0 n1 u) s7 x$ F6 R
- except Exception as e:% n Q( C1 o$ @; C# X! `
- print(e)
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance0 s+ n' [- {/ {! V7 C
- print(validators)
- while True:3 |0 s, @7 x: L! u
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),; v- ]' l) w+ i+ N" e+ f4 ^
- daemon=True), S7 F: k8 c/ s; r
- announce_winner_t.start()
- self.request.send(b"\nEnter a new BPM:")9 G0 P& Q/ n$ n' W) Q$ }
- bpm = self.request.recv(8192)
- try:* x. Q$ s7 x6 v9 x- t0 Q, R0 K" d
- bpm = int(bpm)' Z2 \) }, P- V
- except Exception as e:) G/ O, x( F0 @( _, y; E
- print(e)
- del validators[address]
- break
- # with My_Lock:
- last_block = block_chain[-1]1 W$ k# e: Z0 `& V2 z
- new_block = generate_block(last_block, bpm, address)% U- U( B D: X. e
- if is_block_valid(new_block, last_block):, }0 r. u1 x5 [: n/ [* k: ^+ [0 [
- 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>
- . s8 c* Q7 j0 `2 X; F' R2 u8 X% @
- <div># validator address$ m3 U" X, @. v1 H u& T
- self.request.send(b"Enter token balance:")1 w% ?' y: _3 t0 M2 x, s( l6 _ J
- balance = self.request.recv(8192)
- try:
- balance = int(balance)! o0 V( O8 A3 S( g
- except Exception as e:
- print(e)
- t = str(datetime.now())% f$ p) E* ]5 w& A0 L% @
- address = sha256(t.encode()).hexdigest(), n, c/ x$ V, e( ], u
- validators[address] = balance
- print(validators)</div>
- ; z5 e. A: |! D& j2 ^
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),, h; z/ P7 P& R9 M [ ?( _
- daemon=True)
- announce_winner_t.start()
- def annouce_winner(announcements, request):
- """: v$ x @& z! c, w
- :param announcements: V7 W' s: H( q+ ^' ^
- :param request:8 I( | c. X' R- J$ b4 J0 U1 X: S Q
- :return:1 ]' I+ A, L4 e$ y
- """
- while True:
- try:
- msg = announcements.get(block=False)
- request.send(msg.encode())6 C' P! l! `7 _7 w
- request.send(b'\n')
- except Empty:( ~& L5 F! k" q& n: F4 O
- time.sleep(3) s1 g3 ^; x2 c1 `6 z8 L: ~: M) C) r6 s
- continue</div>
- <div>self.request.send(b"\nEnter a new BPM:")
- bpm = self.request.recv(8192), n* r. E, U* ^: R. i7 H
- try:0 U8 o% l( a* n3 h, q1 o
- bpm = int(bpm)3 c6 Q. |) `5 g3 G
- except Exception as e:( F2 ^- f( Z P0 ]2 m/ `+ v6 i. Q4 y
- print(e)9 L) S( b; F, h6 v1 q
- del validators[address]
- break
- # with My_Lock:
- last_block = block_chain[-1]
- new_block = generate_block(last_block, bpm, address)( a) |+ }! T) [/ Z8 j* ^! ]+ k7 R
- if is_block_valid(new_block, last_block):
- 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)2 Q# t. W: a! q4 O' X W1 F
- annouce_blockchain_t.start()
- def annouce_blockchain(request):0 R+ f2 I% `) U* X6 D, ^
- """. t4 x' V: K0 P( q" k0 D' s7 M( n
- :param request:
- :return:
- """
- while True:8 O9 C$ x3 j7 }7 M0 }# m
- time.sleep(30)! M3 D* e( E6 U3 q" ?: a
- with My_Lock:2 J: \& W0 Q) V: V% Z
- output = json.dumps(block_chain)2 g, X" Y) m, S0 l! x0 c
- try:
- request.send(output.encode()): ]1 H% T' k: g
- request.send(b'\n'); o& N1 Q( \; J. c) l$ @
- except OSError:) Z! d: Q/ e" g0 y: i' l- n
- pass</div>
- <div>def pick_winner(announcements):
- """
- 选择记账人1 u" v7 E4 q0 @, a2 b. N; U" c
- :param announcements:3 V) g# ?* w* }4 `. z+ F
- :return:
- """2 E3 d; r: R/ E9 T
- time.sleep(10)
- while True:
- with My_Lock:: K% G. t" B& N' S( t' W( L& S+ C
- temp = temp_blocks
- lottery_pool = [] #! b/ E0 f" Y7 F7 D" b
- if temp:
- for block in temp:
- if block["Validator"] not in lottery_pool:" j) {! z7 b* L! l) I. c
- set_validators = validators
- k = set_validators.get(block["Validator"])
- if k: G9 Z# O/ S, P: Y* T4 n
- for i in range(k):; K9 ~7 C) Y/ V) I. ^2 A
- lottery_pool.append(block["Validator"])
- lottery_winner = choice(lottery_pool)4 h9 o( ^: e2 p7 o# r
- print(lottery_winner)7 V' ]- b, m% C
- # add block of winner to blockchain and let all the other nodes known$ A( D k0 f3 I. J5 j
- for block in temp:/ s; X" w1 {7 a9 J
- if block["Validator"] == lottery_winner:0 C1 {2 D- B% y4 @& T; H
- with My_Lock:: ^! H/ \2 G1 I i
- block_chain.append(block)
- # write message in queue.5 q" C$ o' [( W0 K
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner)
- announcements.put(msg)( q" |9 f$ {5 y. \$ D' W1 X
- break
- with My_Lock:; ^" E. `5 Q T% ^! y
- temp_blocks.clear()</div>
- <div>def run():
- # create a genesis block& r1 }8 l. f& o" F) P, g. n
- t = str(datetime.now())" H, r7 M0 i( J+ {' m' T: \
- genesis_block = {
- "Index": 0,! d/ u+ V [ m& y! Q
- "Timestamp": t,+ r5 p+ H4 m$ s5 ]
- "BPM": 0,, z9 X. h1 o/ H. q( A+ l5 m5 U
- "PrevHash": "",% E' H+ |+ ^" L; K- ]& J" F
- "Validator": ""
- }
- genesis_block["Hash"] = calculate_hash(genesis_block)( G; C# ^8 T5 l+ I: V6 F c
- print(genesis_block)4 _' s1 E, o: ~% x* S- R
- block_chain.append(genesis_block)% x8 m3 v0 @- H$ B7 Y, e
- thread_canditate = threading.Thread(target=candidate, args=(candidate_blocks,), daemon=True)6 e D# A O, N: u4 F ?
- thread_pick = threading.Thread(target=pick_winner, args=(announcements,), daemon=True)
- thread_canditate.start()# @+ G- K! n, M! w( q X, f0 H
- thread_pick.start()
- # start a tcp server( P7 P+ p+ ~3 F* P
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()/ }5 h' u6 \4 C& ?
- def candidate(candidate_blocks):. |1 H- D7 e$ _ z1 U. Z3 D% `
- """8 O8 ?4 l( L" F; ~
- :param candidate_blocks:
- :return:
- """, X: g2 M! M! N+ W
- while True:5 c0 E8 F' f, D# T( F6 X1 B* ?! U( I
- try:& P$ r4 |3 I% l% |/ G
- candi = candidate_blocks.get(block=False)
- except Empty:
- time.sleep(5): K& T6 ~2 U/ R# f0 A
- continue% K/ C$ a1 ~! j+ a1 X5 e, J/ j
- temp_blocks.append(candi)
- if __name__ == '__main__':
- run()</div>