- & k& d9 A d5 Y4 _0 r/ F/ T
- <div>from hashlib import sha256
- from datetime import datetime
- def generate_block(oldblock, bpm, address):0 j- ~$ j. G5 I6 B
- """- ]) B& e) p9 \* A) _3 u- m. H9 d
- :param oldblock:
- :param bpm:- h( `2 i ~, E* m( O, J
- :param address:: p+ ?" s0 z1 w1 e! G
- :return:( }& T2 e( ~+ t* p$ S
- """1 U7 ]4 v3 |0 L- W7 r$ l
- newblock = {
- "Index": oldblock["Index"] + 1,
- "BPM": bpm,( Q5 W# [2 j2 \& y* I0 ]0 w8 k7 G
- "Timestamp": str(datetime.now()),
- "PrevHash": oldblock["Hash"],' L- |8 l$ i& i7 Q: T' t- e- k
- "Validator": address
- }8 C X8 k! W; b! A H6 e
- newblock["Hash"] = calculate_hash(newblock): {* K) {& {" ?( F
- return newblock& v5 {, }* \# j1 o4 J5 P8 r0 E
- def calculate_hash(block):
- record = "".join([- W" {0 R/ O7 ~7 j. @* ^! ]; `
- str(block["Index"]),! H! i& w& O( i- k! V0 F' w
- str(block["BPM"]),
- block["Timestamp"],
- block["PrevHash"]- J# Z# G2 o/ R7 m2 y2 R
- ])
- return sha256(record.encode()).hexdigest()
- def is_block_valid(newblock, oldblock):
- """
- :param newblock:& W: f0 C' _1 j, N/ [% k
- :param oldblock:
- :return:/ g4 D! n( D3 F% a/ j7 ]
- """$ g3 ^6 m ^# n* w' H& c( q
- if oldblock["Index"] + 1 != newblock["Index"]:
- return False
- if oldblock["Hash"] != newblock["PrevHash"]:( C" Q4 }2 W- O+ U) g$ u" U, u+ N4 ^
- return False
- if calculate_hash(newblock) != newblock["Hash"]:
- return False- n' N1 d+ J" s) A- _) c, X r
- return True</div>
- 9 K% S _$ k y
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer
- def run():
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn) B/ ?: D4 i# d& `. m' @# ~, K
- serv.serve_forever()</div>
- 2 h/ ^1 s9 H. @# H' Q( M
- <div>import threading
- from queue import Queue, Empty
- # 定义变量" W* _( J& I! b$ ^/ I
- block_chain = []
- temp_blocks = []# l4 W4 J" { b7 ?9 t' A6 t* `
- candidate_blocks = Queue() # 创建队列,用于线程间通信- C" a/ Y' @! T4 R# ~+ J3 N4 c
- announcements = Queue() \& L0 g# A4 U, L. n3 @
- validators = {}) e8 k, l6 k: g1 `
- My_Lock = threading.Lock()! l% s9 U/ D9 {3 ]6 u, j" `
- class HandleConn(BaseRequestHandler):4 j/ ]$ d. s% F8 v* ^% C
- def handle(self):
- print("Got connection from", self.client_address)
- # validator address
- self.request.send(b"Enter token balance:")) j" W9 s3 @8 }8 F, Y* r
- balance = self.request.recv(8192)
- try:: F7 }/ l! h% K' H0 \) ?
- balance = int(balance)
- except Exception as e:, u4 q6 y. s7 `. Y* m2 C9 x& Y3 ~7 h
- print(e)
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()+ b. j7 ^6 h c7 l! ^
- validators[address] = balance
- print(validators)& W7 x- T2 v( I$ r) Y
- while True:& K; b& |: n% L! |$ x# F
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
- daemon=True)
- announce_winner_t.start()) a1 m7 ~7 N. Z! {$ w- T. s
- self.request.send(b"\nEnter a new BPM:")% Q3 o. [, w3 ?. V
- bpm = self.request.recv(8192)* t( |/ [/ s" G- I3 a4 |1 e! [, o
- try:( F: O: ?0 R+ T0 X- V- d9 c
- bpm = int(bpm): \: J% `! O# ~* o. S3 p0 k
- except Exception as e:
- print(e)
- del validators[address]
- break
- # with My_Lock:, d4 o# a; h" i6 c8 @
- last_block = block_chain[-1]* F6 X/ c$ a$ }) ^- P
- new_block = generate_block(last_block, bpm, address)
- if is_block_valid(new_block, last_block):' R0 t& C5 D, w) O
- print("new block is valid!") r" C' u/ _3 ]' w' n6 X
- 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)/ s6 a9 ~5 d& s6 Z6 B% l3 h
- annouce_blockchain_t.start()</div>
- : L- {2 ]1 `2 K9 \- P K. b
- <div># validator address5 n8 U3 Z4 d2 b$ `; U( E$ a
- self.request.send(b"Enter token balance:")
- balance = self.request.recv(8192)7 c% Q- M8 K! {: o2 m) q
- try:+ \# [* n5 \; k- Q
- balance = int(balance)& L0 a4 ]5 B6 y( }- {7 B# ?
- except Exception as e:
- print(e)3 e* r, w5 s2 P5 S$ w
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance+ I" E. ^7 `/ Z/ S# F
- print(validators)</div>
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
- daemon=True)! U6 {" v2 o8 x* w* y
- announce_winner_t.start()
- def annouce_winner(announcements, request):3 g6 u" f. ~1 d/ T/ b
- """0 y* v; G3 F) M4 A, [- C
- :param announcements:
- :param request:
- :return:
- """" C- t0 A4 u$ }5 J
- while True:" ]. h) T- s# E/ g+ y& r8 B
- try:
- msg = announcements.get(block=False)- V, u/ U3 z+ ~5 k2 s
- request.send(msg.encode())
- request.send(b'\n')$ L9 Y1 J5 V" @/ {& X1 b
- except Empty:
- time.sleep(3)
- continue</div>
- <div>self.request.send(b"\nEnter a new BPM:")
- bpm = self.request.recv(8192)
- try:! Q! ]& n9 m$ B9 ^6 [; s% M z
- bpm = int(bpm)
- except Exception as e:
- print(e)4 \ t9 i3 q$ W8 O3 E, F
- del validators[address]) _ P% k) d' }2 ~" _$ ]4 K9 W
- break
- # with My_Lock:
- last_block = block_chain[-1]0 Y( {1 R* ]8 I/ b+ Q4 m
- new_block = generate_block(last_block, bpm, address)
- if is_block_valid(new_block, last_block):3 _, B Q) ^$ x
- print("new block is valid!")1 v H m9 N: p7 p* Y( J
- candidate_blocks.put(new_block)</div>
- <div>annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)" J. I: D5 _0 w+ {
- annouce_blockchain_t.start()
- def annouce_blockchain(request):9 [! ?4 t) x. R
- """/ U' k: Y' S7 L; L+ ^* F% g
- :param request:
- :return:
- """7 B2 u6 c Y1 d8 u. m6 N( C7 r
- while True:
- time.sleep(30)3 q2 Y; d' `1 s0 e- d* y2 `
- with My_Lock:6 F$ H, `" M4 e! P* `
- output = json.dumps(block_chain): @& ?( b; u5 C4 v
- try:
- request.send(output.encode())' w8 N4 n7 s5 }4 E: ]5 r
- request.send(b'\n')
- except OSError:
- pass</div>
- + E2 P d5 ~3 I; k
- <div>def pick_winner(announcements):
- """
- 选择记账人' s, B$ H B- c$ Y% ^. ?1 f2 @
- :param announcements:
- :return:7 I: N$ j# u( p, X4 j# u
- """
- time.sleep(10)6 M% {+ Q( f c0 H6 `! N( X; t
- while True:
- with My_Lock:
- temp = temp_blocks
- lottery_pool = [] #
- if temp:
- for block in temp:
- if block["Validator"] not in lottery_pool:1 e, ^, w3 d C' z! B- A: R
- set_validators = validators
- k = set_validators.get(block["Validator"])
- if k:
- for i in range(k):/ N H2 F* d, {: y* K5 V
- lottery_pool.append(block["Validator"])
- lottery_winner = choice(lottery_pool)1 t& @ R# I! I0 X2 I7 j. @
- print(lottery_winner)
- # add block of winner to blockchain and let all the other nodes known7 u& U6 e3 t; B) o) r- u( Y
- for block in temp:
- if block["Validator"] == lottery_winner:
- with My_Lock:+ c, [; {4 v8 ^) e( [' E0 @
- block_chain.append(block)
- # write message in queue.
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner)2 g% ~ p$ x& C9 p j
- announcements.put(msg)4 i) T* W/ d5 @- T% Q7 P* F4 ^5 A
- break
- with My_Lock:# P3 z+ y/ b7 x" |( f' s
- temp_blocks.clear()</div>
- <div>def run():
- # create a genesis block6 {8 O9 ]/ k; j2 q+ a$ s8 R# T4 ^
- t = str(datetime.now())% Y6 ]/ l8 G0 `$ Y
- genesis_block = {+ Y y) t3 Z: V
- "Index": 0,# e5 m T; e: u
- "Timestamp": t,
- "BPM": 0,
- "PrevHash": "",* n0 e7 d' s* i" b3 H ?
- "Validator": ""
- }
- genesis_block["Hash"] = calculate_hash(genesis_block)! w# [9 n3 B6 Z6 |8 q
- print(genesis_block)2 t. Y9 i7 x( o
- block_chain.append(genesis_block)
- 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()" @! F9 \; {* @$ Z4 D
- thread_pick.start()
- # start a tcp server7 F z+ W7 t) g3 E
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()
- def candidate(candidate_blocks):0 E9 O, n; d7 w1 c, g
- """
- :param candidate_blocks:$ f( t! G; C3 I$ s d& l$ e
- :return:
- """% S7 `: j7 J9 V* Q+ r6 x& V1 w/ P
- while True:
- try:
- candi = candidate_blocks.get(block=False)5 V4 w0 p# Y$ f, M# {* `
- except Empty:
- time.sleep(5)
- continue
- temp_blocks.append(candi)
- if __name__ == '__main__':: s' k3 |. O7 P/ p2 E) |1 b
- run()</div>