- 3 _) E* Y8 a3 ~6 V2 P; g' o
- <div>from hashlib import sha256" i9 L; o6 b m) [. A' H
- from datetime import datetime
- def generate_block(oldblock, bpm, address):* G6 D6 M2 E* y5 ?0 t& D7 g/ h
- """
- :param oldblock:
- :param bpm:
- :param address:" @/ [/ h8 ]# a0 `* A: g( e% F+ f' r
- :return:5 B8 U+ j3 J* q6 q4 k9 T( E
- """% q+ g* w) Y* t6 y) j8 _
- newblock = {
- "Index": oldblock["Index"] + 1,' ^$ e3 `2 @: \! e# k- Y
- "BPM": bpm," Z7 p$ f8 T$ Z
- "Timestamp": str(datetime.now()),
- "PrevHash": oldblock["Hash"],% L$ e" v, Q& U! s4 ]
- "Validator": address
- }, t$ f) d! P. s' A* o
- newblock["Hash"] = calculate_hash(newblock)8 l& W9 Y1 L$ I; P0 j4 v' ~5 w4 V
- return newblock- ]) H+ {" w' V' }
- def calculate_hash(block):
- record = "".join([
- str(block["Index"]),
- str(block["BPM"]),1 Q: ?# a9 q6 x3 {; V Z
- block["Timestamp"],, N0 @2 ? Z5 E0 v, t
- block["PrevHash"]
- ])" L4 T/ I+ V0 m5 @# E& z
- return sha256(record.encode()).hexdigest()" a, n Y4 B' k7 h4 b2 f
- def is_block_valid(newblock, oldblock):! o' {# Z( k7 s# i* f
- """
- :param newblock:
- :param oldblock:& c$ ?4 c* k7 R9 I* U
- :return:
- """4 [$ }& f0 D6 w1 ~; | L
- if oldblock["Index"] + 1 != newblock["Index"]:0 W8 t* C; u4 K( l% l
- return False
- if oldblock["Hash"] != newblock["PrevHash"]:0 _' G9 j/ U! q0 z
- return False
- if calculate_hash(newblock) != newblock["Hash"]:/ l" r/ i o/ r1 o e
- return False
- return True</div>
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer
- def run():
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)1 B" e) u1 {: t0 N) z, f9 r9 }
- serv.serve_forever()</div>
- 0 g/ x1 J8 `! m1 w5 ^4 p
- <div>import threading( R; K; u- c0 |/ m" H% C$ K
- from queue import Queue, Empty
- # 定义变量# u( C) ]8 J5 X( }: i/ C- x
- block_chain = []. j+ ]! {0 Z5 v. A+ E
- temp_blocks = []
- candidate_blocks = Queue() # 创建队列,用于线程间通信& @8 g7 n7 {) w# R9 ?# a
- announcements = Queue()9 }9 y3 k- M3 b( L& i: n2 X
- validators = {}. }7 K' H- H% O3 I
- My_Lock = threading.Lock()
- class HandleConn(BaseRequestHandler):
- def handle(self):- e" o! S# k; e: p1 H/ c/ w
- print("Got connection from", self.client_address)
- # validator address: p1 e/ P& J- d
- self.request.send(b"Enter token balance:"). E$ }9 n, q9 v& t2 n7 P; n. v( q: d
- balance = self.request.recv(8192)
- try:
- balance = int(balance) M( H! i" G. E
- except Exception as e:
- print(e)5 ~% [# b+ T# ^
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance
- print(validators)9 ]2 J3 i- G, q2 b" V- @
- while True:; }; g- K5 Z( [! ^% f( J- V* H
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),# J# S" w2 m( u7 R( J" k
- daemon=True)" b" C* _* t+ W+ X* j2 G
- announce_winner_t.start()+ ]# y% j" o+ C/ @( l
- self.request.send(b"\nEnter a new BPM:")0 d4 g5 T- o2 j g" d6 y
- bpm = self.request.recv(8192). X4 c; D$ w4 ]5 x
- try:$ r' {/ C: B' w* o! j9 V- B
- bpm = int(bpm)- J$ H" [% p' O& X4 {& y* p
- except Exception as e:6 ]1 Z- V! b% q" g- ~$ }7 T) N* N5 S
- print(e)
- del validators[address]/ y8 K2 o, j/ L* T; K
- break
- # with My_Lock:
- last_block = block_chain[-1]
- new_block = generate_block(last_block, bpm, address)3 L& d6 t8 o6 |7 g
- if is_block_valid(new_block, last_block):
- print("new block is valid!")
- candidate_blocks.put(new_block)
- self.request.send(b"\nEnter a new BPM:\n")1 I/ p0 Y6 [, C0 | \: l
- annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)) @- }$ D' s. k7 |& ~0 `2 y# i
- annouce_blockchain_t.start()</div>
- <div># validator address
- self.request.send(b"Enter token balance:")
- balance = self.request.recv(8192)- Y' r. `! n& q- K
- try:% ?4 v2 {! t1 t7 {; N% O% Q
- balance = int(balance)
- except Exception as e:
- print(e)
- t = str(datetime.now())+ H `( F# }! \5 Q
- address = sha256(t.encode()).hexdigest()% a' s$ O/ x7 s) D
- validators[address] = balance
- print(validators)</div>
- " u; ]1 x* X3 z+ @& O- h! m
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
- daemon=True)* n% L: ?2 ]- ^
- announce_winner_t.start()
- def annouce_winner(announcements, request):. |5 d" U9 ^" L! A1 Y, S) Z' A
- """. g) r6 B6 N5 W/ S
- :param announcements:
- :param request:
- :return: G1 y0 S, s/ Y8 q. E+ c
- """$ N+ m& q! [( \% G4 _9 Z
- while True:0 a2 @' Q; y" T. Y
- try:
- msg = announcements.get(block=False)
- request.send(msg.encode())5 w4 i9 l( h5 L2 y; p5 p3 q0 U
- request.send(b'\n')7 R. |/ C& x5 E/ ~2 I$ F
- except Empty:
- time.sleep(3)7 q0 p0 r- [8 l# `( X9 X
- continue</div>
- 5 I9 @& D, _$ w; E' H
- <div>self.request.send(b"\nEnter a new BPM:")2 g& x6 `) f* k& W0 f1 x
- bpm = self.request.recv(8192)3 s5 p6 _: {: K3 t5 A, z0 Y* j0 q6 }
- try:
- bpm = int(bpm)
- except Exception as e:3 z. E( r/ H9 [" V. \3 {7 z2 h
- print(e)
- del validators[address]7 F/ ]* z# V. I2 z
- break ~$ S7 ]) l/ ]" g& p
- # with My_Lock:, ]' N+ h- c: O; X
- last_block = block_chain[-1]
- new_block = generate_block(last_block, bpm, address)
- 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)/ |0 E- @, o% A4 k# s
- annouce_blockchain_t.start()+ T& h5 V! @, j1 s% a# t- D
- def annouce_blockchain(request):4 K4 _( O) o9 O- u- ~. H! p& R+ {+ \
- """+ Z. G- \3 G# b# I2 a
- :param request:
- :return:6 p c. ?9 t; W8 M' T3 q, U6 w
- """
- while True:. w0 M/ r. ?% j5 y
- time.sleep(30)
- with My_Lock:
- output = json.dumps(block_chain)
- try:! }5 U+ u3 E3 N! z
- request.send(output.encode())
- request.send(b'\n')
- except OSError:
- pass</div>
- <div>def pick_winner(announcements):% G: ^) N' k0 r9 z' x
- """& H8 h7 Z) t1 Y# Z; w& p
- 选择记账人5 V2 w' {: x3 g8 V: u J9 |
- :param announcements:
- :return:
- """
- time.sleep(10)8 j3 W4 k- C3 U- L( v
- while True:( }1 r* G' ^* q4 S( Z- Z5 [- V
- with My_Lock:
- temp = temp_blocks8 K& e3 E8 T3 G a) V5 ^, ?9 w. [
- lottery_pool = [] #
- if temp:4 l, F: J; t/ K1 ^
- for block in temp:
- if block["Validator"] not in lottery_pool:" v* }# E0 P3 m L7 U' j% m3 r
- set_validators = validators
- k = set_validators.get(block["Validator"])7 `- w0 _4 N% A! ?6 z5 t0 A
- if k:
- for i in range(k):& k: d( a! e+ Z- J0 I; @* x
- lottery_pool.append(block["Validator"])
- lottery_winner = choice(lottery_pool)' B* Q/ A0 J0 N3 @
- print(lottery_winner)# t# F+ v$ j, z: C/ @. G$ W
- # add block of winner to blockchain and let all the other nodes known
- for block in temp:
- if block["Validator"] == lottery_winner:$ ~! ?* h5 ?" h
- with My_Lock:# G- z; ^( C8 y+ {! `
- block_chain.append(block)) p1 q: l: u# i
- # write message in queue.
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner)' G2 g( i! g$ y
- announcements.put(msg)1 f6 |0 i v! d8 i
- break
- with My_Lock:
- temp_blocks.clear()</div>
- . d5 L/ w/ j; q P/ | D
- <div>def run():
- # create a genesis block' A1 A- s! C4 ^/ l/ g [8 s* f
- t = str(datetime.now())
- genesis_block = {
- "Index": 0,
- "Timestamp": t,* \% A( @# e( {% s8 c5 u; g5 G
- "BPM": 0,9 N+ o+ k9 H# k' d6 T. V) J
- "PrevHash": "",) U0 ^" Q6 w4 U+ K( v' C# K
- "Validator": ""
- }
- genesis_block["Hash"] = calculate_hash(genesis_block)
- print(genesis_block)
- block_chain.append(genesis_block)6 ]$ E1 s" W% f) L% }: u. z
- thread_canditate = threading.Thread(target=candidate, args=(candidate_blocks,), daemon=True)
- thread_pick = threading.Thread(target=pick_winner, args=(announcements,), daemon=True)
- thread_canditate.start()* ]; j- p4 z) j! d) h; S+ |
- thread_pick.start()
- # start a tcp server$ f- S" E$ { x( R k2 @' I* a7 c
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()
- def candidate(candidate_blocks):; n+ s' C5 _' b- h P8 B
- """( v4 D' B% ]& k) D
- :param candidate_blocks:( T% M/ i9 N2 C% v
- :return:) V3 @+ [, d( J! Q, J& m
- """
- while True:
- try:6 H( T% r. W" K9 |9 [" L0 t
- candi = candidate_blocks.get(block=False)' C; `# O* w4 x: ]% N
- except Empty:
- time.sleep(5)
- continue
- temp_blocks.append(candi)3 E9 o! `' B- o
- if __name__ == '__main__':
- run()</div>