- <div>from hashlib import sha2565 o# g2 D, g: P9 z, k
- from datetime import datetime7 v' o: o# l9 k( K+ F
- def generate_block(oldblock, bpm, address):5 M$ c. \' V! C5 S
- """
- :param oldblock:! j6 w% [7 ^5 @) S3 ]4 M* N4 h
- :param bpm:* E) n2 u- O i. J
- :param address:
- :return:1 S/ ?& z" W! V: s& S
- """8 b: N9 |. J! J' o
- newblock = {% X( Q, t9 i" u h" L6 Z
- "Index": oldblock["Index"] + 1,
- "BPM": bpm,2 Z% L" j3 z7 T) O3 M/ z9 n
- "Timestamp": str(datetime.now()),
- "PrevHash": oldblock["Hash"],. X' G8 X- R4 S. n) X. G( m
- "Validator": address
- }. z3 Z9 E3 [- q3 M4 D
- newblock["Hash"] = calculate_hash(newblock)
- return newblock$ W5 w2 X9 K0 A( m% V2 Z$ i3 L
- def calculate_hash(block):
- record = "".join([; q+ v& Y. x. ]- s- _ b. {
- str(block["Index"]),! f1 u5 I. ?# a3 n
- str(block["BPM"])," T1 s4 k' e2 O7 | }* o
- block["Timestamp"],9 {" U: h; K' l9 Z# c) |2 L, N5 Z
- block["PrevHash"]* w. u8 M0 w; e! g( X* R$ X
- ])
- return sha256(record.encode()).hexdigest()
- def is_block_valid(newblock, oldblock):
- """
- :param newblock:8 n* I0 g! D, @4 x' o' v C/ x d/ D
- :param oldblock:
- :return:# s* ?) O! o$ p' z
- """
- if oldblock["Index"] + 1 != newblock["Index"]:- B: V8 z8 i2 A* e" _
- return False- @: Y' `. u3 @/ ~5 W3 \
- if oldblock["Hash"] != newblock["PrevHash"]:
- return False
- if calculate_hash(newblock) != newblock["Hash"]:# w* q. [ A) r: k+ I
- return False4 o8 m; s$ U. q2 j. L
- return True</div>
- + ]1 Y5 m2 ^, ^ c0 N R! [! ]' v
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer
- def run():
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()</div>
- * `! Z( E0 Q& c+ m9 [5 y# [+ P2 i
- <div>import threading' S6 y1 r7 k; y: f5 W
- from queue import Queue, Empty
- # 定义变量
- block_chain = []. R- n. k- V( G) w6 L
- temp_blocks = []
- candidate_blocks = Queue() # 创建队列,用于线程间通信
- announcements = Queue()
- validators = {}, F9 U! S7 L* J* f" B9 A' [
- My_Lock = threading.Lock()
- class HandleConn(BaseRequestHandler):$ [3 @7 i j' T% a7 Y, u
- def handle(self):% K1 G% v; M: {- S9 ?+ w
- print("Got connection from", self.client_address)* V' L: `& f& ~- x- \6 S8 J
- # validator address
- self.request.send(b"Enter token balance:")/ B2 P: b% [; v& h0 F9 W
- balance = self.request.recv(8192)
- try:+ p! y7 E) i% a. l
- balance = int(balance); n) L5 p, V% u% l
- except Exception as e:
- print(e)
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()4 `9 C" ^+ i) `8 A2 l
- validators[address] = balance
- print(validators)9 S$ X$ C- I! { D9 ], ^
- while True:
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
- daemon=True)) G/ Z1 j/ F B7 A5 @ C( d; d: ?
- announce_winner_t.start()& j3 C# d/ d& @; x: S7 v
- self.request.send(b"\nEnter a new BPM:")
- bpm = self.request.recv(8192)" F! U% V& E/ B4 c, V( S
- try:8 f( q2 e. ^: Y4 v
- bpm = int(bpm)# A0 Q2 J+ r& {
- except Exception as e:/ c. x9 ?; c- S Q
- print(e)9 X0 B7 l# V2 J( z; q; t3 B/ \; x
- del validators[address]
- break& j& L' r: \; D. A N: D- p, H
- # with My_Lock:$ n0 L% o8 K" s, _* @. V
- last_block = block_chain[-1]
- new_block = generate_block(last_block, bpm, address)5 A) s' O' A3 O% C; z
- 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")
- annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)3 }2 g* t) a# v$ H( u, g3 n: u" O- V
- annouce_blockchain_t.start()</div>
- M, z/ m' l+ L9 g
- <div># validator address6 M! t! p9 X ?0 t' w4 r
- self.request.send(b"Enter token balance:")/ @3 x N: P* _& Y
- balance = self.request.recv(8192)
- try:- Y4 F( h9 q0 C @/ [0 f T
- balance = int(balance)/ Y) g o5 k$ V+ i, u# f4 N
- except Exception as e:& [9 }: O9 ?; `( ~$ N$ t( S* }8 Y1 l* \, [
- print(e)
- t = str(datetime.now()); E- J! [* z6 @6 X( f$ k- S- v) U
- address = sha256(t.encode()).hexdigest()$ S+ _2 T& q4 f/ b$ g% q
- validators[address] = balance9 c0 P0 g; J- ^" x ?+ k/ ~
- print(validators)</div>
- : Z6 `1 G* n, s2 A
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),8 V. {4 I4 p# O' P9 H6 R
- daemon=True)4 k: j2 b/ Q) a; v4 p
- announce_winner_t.start()1 |1 w8 U U7 `. X+ u
- def annouce_winner(announcements, request):
- """3 _0 i8 E2 o# _0 D) q+ S
- :param announcements:! w1 M% w8 I8 U6 j7 s# W O/ |0 ~. H$ Q( |
- :param request:% D' P2 d5 o# t7 \
- :return:
- """- z0 L5 T' ~, f, w, V8 d
- while True:+ j+ `1 s) {4 a4 P0 D/ G
- try:0 T" X1 W: e# A; M; a$ Y2 }. n+ n
- msg = announcements.get(block=False)" X: B- Q+ x) ^% B7 @3 \
- request.send(msg.encode())
- request.send(b'\n')2 p* s+ q N h; o+ h
- except Empty:. ~+ T2 ]1 y% V r5 x
- time.sleep(3)
- continue</div>
- : Z5 Q: E" g# M* |
- <div>self.request.send(b"\nEnter a new BPM:")4 x6 ]' V# _) j$ u
- bpm = self.request.recv(8192)! G4 n' r; A# O1 q- Y
- try:2 W' C% \: _$ ?" E/ a& H
- bpm = int(bpm)
- except Exception as e:0 a+ G( Y/ `/ S" P% r. n* h* w
- print(e)
- del validators[address]5 }" R# |+ ^9 t& c8 S+ {
- break; A. K m+ D. z- d3 @/ d
- # with My_Lock:
- last_block = block_chain[-1]8 V: N$ |+ H ^; Q: b
- new_block = generate_block(last_block, bpm, address)* n- l( R7 W, b D! u% [
- if is_block_valid(new_block, last_block):
- print("new block is valid!")0 T- L1 y+ E/ a( Y( F$ I$ `
- candidate_blocks.put(new_block)</div>
- ' H' T' F6 g. ?2 v. F' q* ^
- <div>annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)
- annouce_blockchain_t.start(); ?# |; |" D" Y8 {/ Q
- def annouce_blockchain(request):" X) i D7 l& q; n
- """9 j/ {7 H6 j- B+ h2 @6 u3 ?
- :param request:
- :return:
- """
- while True:" C9 m) M) Q% f+ F
- time.sleep(30)
- with My_Lock:
- output = json.dumps(block_chain)0 A2 W; R6 d; L0 |- X# ~, d
- try:
- request.send(output.encode())! M$ S |) B0 _6 O1 Q+ j
- request.send(b'\n')
- except OSError:7 K9 E& c* O* ]& i" I
- pass</div>
- 6 T" S: u* E7 D1 _3 X5 s( K e5 ]
- <div>def pick_winner(announcements):- Q% H/ t% M: d% P2 V1 a
- """+ R* z. o& b$ C+ {; {
- 选择记账人
- :param announcements:+ U1 T, }7 H8 ]( y: Q
- :return:+ t! t2 o( E A5 U$ t* \
- """
- time.sleep(10)
- while True:+ X& `* ^# L3 i i" f' p
- with My_Lock:
- temp = temp_blocks
- lottery_pool = [] #
- if temp:$ x3 ?- R' W) |( O7 m
- for block in temp:
- if block["Validator"] not in lottery_pool:
- set_validators = validators8 K% ]& L8 C8 h
- k = set_validators.get(block["Validator"]) _. e b3 W2 e6 V+ S7 H
- if k:% `1 M2 X8 E+ h7 g0 y5 O
- for i in range(k):4 g6 }1 I4 u# _1 m/ c7 A
- lottery_pool.append(block["Validator"])1 U' `( V/ g$ c9 R
- lottery_winner = choice(lottery_pool)
- print(lottery_winner) R# y a1 ]3 P3 p% ]: K$ ]
- # add block of winner to blockchain and let all the other nodes known0 R t. y8 u8 r8 j3 @3 Y
- for block in temp:0 w A; ?7 \, u
- if block["Validator"] == lottery_winner:! u! i o9 o$ o1 u: v) r( R' I
- with My_Lock:
- block_chain.append(block)
- # write message in queue.
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner)
- announcements.put(msg)+ z! c ]+ [6 [$ x
- break- ]- D* x/ z6 d$ T ]. U
- with My_Lock:
- temp_blocks.clear()</div>
- & m9 X' W) Q% l3 ?
- <div>def run():
- # create a genesis block8 P; L( }1 V! V. j# B
- t = str(datetime.now())% p( ^, M, g$ O
- genesis_block = {; C2 n' D1 p4 l% e' _' r
- "Index": 0,
- "Timestamp": t,% q; t; Y+ o. z- A
- "BPM": 0,
- "PrevHash": "",
- "Validator": ""
- }3 f" L. k0 e% B8 }+ l/ G
- genesis_block["Hash"] = calculate_hash(genesis_block) w5 w& v" v c$ Z
- print(genesis_block)
- block_chain.append(genesis_block)
- thread_canditate = threading.Thread(target=candidate, args=(candidate_blocks,), daemon=True)+ ^' c' ~/ o; r- I6 U
- thread_pick = threading.Thread(target=pick_winner, args=(announcements,), daemon=True). ?7 s/ q/ Q: _ s
- thread_canditate.start()
- thread_pick.start()
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)
- serv.serve_forever()
- def candidate(candidate_blocks):
- """
- :param candidate_blocks:0 @' Z- _" g$ z Q. W8 d$ w
- :return:
- """
- while True:3 [) F$ A! m$ \* d
- try:
- candi = candidate_blocks.get(block=False) w/ j" K$ E# I8 x/ c
- except Empty:' K0 }: ~6 A. q, A9 g" }$ ?
- time.sleep(5)
- continue
- temp_blocks.append(candi)9 V0 z- x$ {2 H8 u: s/ @
- if __name__ == '__main__':
- run()</div>