- <div>from hashlib import sha256
- from datetime import datetime4 m3 D3 |. @( D, L
- def generate_block(oldblock, bpm, address):
- """
- :param oldblock:
- :param bpm: r2 X/ L' A) X- P) T3 ~
- :param address:8 B% N" u# X# d! X$ ^
- :return:5 B1 C7 d' q2 h* G
- """3 ^' ^) g) A; B0 M3 S
- newblock = {
- "Index": oldblock["Index"] + 1,
- "BPM": bpm,
- "Timestamp": str(datetime.now()),8 Z8 k% q. _/ c3 }+ \7 V( A
- "PrevHash": oldblock["Hash"],9 L' p4 v4 N& `' R
- "Validator": address) A q4 ]2 U) {7 X/ I3 v" H
- }. e, m0 Z! U! I" I. z
- newblock["Hash"] = calculate_hash(newblock)4 e) {. ?' `/ I
- return newblock* V% {5 `2 i; \$ r% z* u# U
- def calculate_hash(block):
- record = "".join([- l( b& v- g( T2 X: m
- str(block["Index"]),3 ?# U" H% s, K# n1 Y, n' A
- str(block["BPM"]),
- block["Timestamp"],
- block["PrevHash"]
- ])% M( I# m: q! l8 d
- return sha256(record.encode()).hexdigest()6 K% u; X* @/ ]1 A: @
- def is_block_valid(newblock, oldblock):
- """4 `. P& G6 ? W: [! x( m8 [ c
- :param newblock:2 y1 K" j5 n) {7 X3 ~
- :param oldblock:
- :return:
- """
- if oldblock["Index"] + 1 != newblock["Index"]:0 P X( F0 z0 j, a) c0 g
- return False3 A9 n8 T$ |, e/ j
- if oldblock["Hash"] != newblock["PrevHash"]:
- return False
- if calculate_hash(newblock) != newblock["Hash"]:
- return False, V* Q f. O& F
- return True</div>
- & ^' d/ G& N0 Q
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer
- def run():: W# e- j3 L z/ h
- # start a tcp server5 h7 @: h# q% {5 y7 \/ f: B
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()</div>
- , {; A8 [6 n4 Y
- <div>import threading0 G0 ]7 G, Q: s; ~
- from queue import Queue, Empty
- # 定义变量
- block_chain = []8 ^ d; ]9 L' C% Q1 Q* z, l2 J
- temp_blocks = []" l- g4 K5 |6 W. x: Y7 Z+ M2 U O0 G% P
- candidate_blocks = Queue() # 创建队列,用于线程间通信
- announcements = Queue()
- validators = {}
- My_Lock = threading.Lock()- q* Q9 a; S8 ^8 Y
- class HandleConn(BaseRequestHandler):2 a0 s" Q& N5 D
- def handle(self):7 U% q* B8 C; `7 \
- print("Got connection from", self.client_address)
- # validator address
- self.request.send(b"Enter token balance:")
- balance = self.request.recv(8192)
- try:
- balance = int(balance)
- except Exception as e:. |2 b! C5 k! }% Q
- print(e)
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()) ~* G1 W6 \! g/ ]
- validators[address] = balance" M! F# m& F& E9 F$ B6 _1 i; ?
- print(validators): f% H: A8 y6 E8 p0 `4 f& e& P
- while True:: s; Y0 y" N# D+ H! p% W
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),$ v( ]- e* \1 R3 S; k! q' ?, C
- daemon=True): [: s# y# g4 t& I
- announce_winner_t.start()- q5 i2 P) r9 G4 W1 o7 G8 A; p
- self.request.send(b"\nEnter a new BPM:")# C. ?% v, b: l) j3 X2 b
- bpm = self.request.recv(8192)4 J5 r. V8 r0 u. B) g [
- try:
- bpm = int(bpm)5 b3 e" R5 y3 `% G b
- except Exception as e:$ z+ {( a. g( c* t3 m, P
- print(e)! ]9 K2 j8 V9 g$ E& x
- del validators[address]3 X2 S: O4 x( Y0 [: h
- break
- # with My_Lock:# N+ c+ M0 `" p; l3 W
- last_block = block_chain[-1]
- new_block = generate_block(last_block, bpm, address)) S6 n$ Q3 L. b9 f+ g" D
- if is_block_valid(new_block, last_block):" H" h8 c: t3 |& V1 ^6 j9 i% C! P
- print("new block is valid!") C8 r5 p" R3 U* _
- candidate_blocks.put(new_block)0 A1 e+ Y% g/ P* A, O+ i
- 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>
- : H5 E1 s. l0 A R
- <div># validator address
- self.request.send(b"Enter token balance:"); Z! l5 G" L3 d$ B l
- balance = self.request.recv(8192)
- try:
- balance = int(balance)
- except Exception as e:7 M5 Q- I/ p d( W
- print(e)( X. y6 l# P6 b. x
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance% s6 ^, S* e; f* S
- print(validators)</div>
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
- daemon=True)2 v+ o3 r' m6 v9 y8 k
- announce_winner_t.start()! i7 ?0 c' e0 _; k3 U7 l
- def annouce_winner(announcements, request):
- """
- :param announcements:) B+ I5 z$ g5 I7 E+ y4 P
- :param request:; ^0 l+ l8 c; p J* U6 P
- :return:7 H! X7 P6 } r- P6 U
- """* ^, f; S3 D! V+ y9 I
- while True:! j; _! b) a" B) C& H2 r( C: S
- try:+ D0 X9 q7 O' k/ j( i
- msg = announcements.get(block=False): w; v3 F2 |1 a# S
- request.send(msg.encode())
- request.send(b'\n')
- except Empty:
- time.sleep(3)
- continue</div>
- * T# ~8 Y# P# t- b" K s
- <div>self.request.send(b"\nEnter a new BPM:")& K. C0 Y( A V6 p
- bpm = self.request.recv(8192)
- try:- I: W8 ]# ]4 s+ i! D- @& s: L' t4 [
- bpm = int(bpm)
- except Exception as e:# o3 L# x2 M* T1 G% A0 Y
- print(e)) T+ g( h# o4 F* [/ @6 W3 f# ~
- del validators[address]
- break
- # with My_Lock:
- last_block = block_chain[-1]$ Y( X. }: q4 N( M; E- i& ], u
- 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>
- + ?, H0 ?: Y }; V
- <div>annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)1 y, M8 n/ \( `
- annouce_blockchain_t.start(); Z7 h+ E! G0 B0 z/ Z6 L
- def annouce_blockchain(request):
- """
- :param request:1 I d; B7 `% n( a: t6 Y- c* C4 o
- :return: H' e$ `' u4 k8 Q$ y
- """
- while True:
- time.sleep(30)- ^6 ]2 R) H% V2 a, S
- with My_Lock:3 B, ^9 q/ ?7 ~% L
- output = json.dumps(block_chain)
- try:
- request.send(output.encode())0 Q* ^# E* Y8 v
- request.send(b'\n')2 s8 L0 M7 r5 ~8 S& |3 v* {) F* n) D( }; m
- except OSError:
- pass</div>
- 2 I- l7 g y" L: M9 H5 q) I
- <div>def pick_winner(announcements):
- """7 E c/ V3 p3 `8 z8 U! n: p" \
- 选择记账人
- :param announcements:
- :return:
- """% [1 ^$ C0 \) x$ d X
- time.sleep(10)9 k0 F& j- k" Q2 M. x
- while True:5 S/ I. H) z5 Z5 a- [: B
- with My_Lock:& D9 C* s, f( O6 N
- temp = temp_blocks `2 n3 M! L2 `" U+ U5 v: X( m
- lottery_pool = [] #
- if temp:2 v) E E$ y2 I
- for block in temp:
- if block["Validator"] not in lottery_pool:# }- b/ c* j* G& v4 N
- set_validators = validators
- k = set_validators.get(block["Validator"])6 e/ n+ |, H9 B% O& C( I
- if k:
- for i in range(k):7 B! @. h! A) f( ?/ _% u
- lottery_pool.append(block["Validator"])
- lottery_winner = choice(lottery_pool)
- print(lottery_winner)# o& M; f. i0 r r/ f4 ]& a# [
- # add block of winner to blockchain and let all the other nodes known
- for block in temp:
- if block["Validator"] == lottery_winner:
- with My_Lock:2 K: u" B( @$ X5 ^
- block_chain.append(block)# @8 A6 k. L8 ]% U) E( @7 w" Q% R
- # write message in queue.
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner)
- announcements.put(msg)
- break
- with My_Lock:
- temp_blocks.clear()</div>
- <div>def run():
- # create a genesis block
- t = str(datetime.now())9 t$ h2 L, R- W2 _
- genesis_block = {
- "Index": 0,
- "Timestamp": t,
- "BPM": 0,# W& a9 v( n: l8 \6 E' }4 B9 P: o
- "PrevHash": "",3 @5 d& q- T. b% T# D
- "Validator": ""1 _, f/ S2 Q! g
- }2 a* z8 X: [. ?* ]6 x' b
- genesis_block["Hash"] = calculate_hash(genesis_block)
- print(genesis_block)# @" _' r( [1 F% L% ~
- block_chain.append(genesis_block)" t; K; l4 V* L. y( {. W0 K
- thread_canditate = threading.Thread(target=candidate, args=(candidate_blocks,), daemon=True)
- thread_pick = threading.Thread(target=pick_winner, args=(announcements,), daemon=True)* ]8 j" o# X, T
- thread_canditate.start()* {9 r/ y( M/ T7 ?5 V8 F3 k
- thread_pick.start()
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)0 m6 I: V3 k3 U3 m# {+ c0 V) u
- serv.serve_forever()/ U3 ~2 y& Q4 P+ l6 [
- def candidate(candidate_blocks):0 y1 u# }0 ?- j1 R
- """4 _0 F5 D& t4 N7 L8 {
- :param candidate_blocks:
- :return:$ p% J7 `0 e$ x1 ^
- """
- while True:
- try:
- candi = candidate_blocks.get(block=False)
- except Empty:
- time.sleep(5)
- continue
- temp_blocks.append(candi)/ o& O! a4 a! u% [: `9 }8 Y1 G2 F
- if __name__ == '__main__':# ?; V2 i2 ^6 i
- run()</div>