- <div>from hashlib import sha2565 d: g" o# w6 X* O3 G& y3 z
- from datetime import datetime3 D' B: Q0 O3 v5 p. _3 n* ?
- def generate_block(oldblock, bpm, address):7 @# S. m8 h" A0 H8 T. h2 _4 w
- """
- :param oldblock:/ Q+ H$ u1 F) z7 ]7 M- o: Z
- :param bpm:
- :param address:
- :return:
- """( f: k( `" }6 {( X4 i+ _
- newblock = {+ L1 |; P& Y, I' W
- "Index": oldblock["Index"] + 1,
- "BPM": bpm,
- "Timestamp": str(datetime.now()),
- "PrevHash": oldblock["Hash"],
- "Validator": address
- }
- newblock["Hash"] = calculate_hash(newblock)4 X* U. i [+ a8 \3 K6 Q& C7 n
- return newblock! L M# I+ t# b7 |/ {7 M
- def calculate_hash(block):8 T Z7 ~0 b" ]
- record = "".join([+ a( Y. U( @6 `* Q: V
- str(block["Index"]),
- str(block["BPM"]),
- block["Timestamp"],: R3 S; r+ p2 [" R- i
- block["PrevHash"]
- ]), C% Y: n3 n7 x1 i; l; C% ~6 G ?
- return sha256(record.encode()).hexdigest()
- def is_block_valid(newblock, oldblock):
- """9 M" R8 I/ E$ {, e, W3 B
- :param newblock:. U* D3 s) y9 p( ]7 F
- :param oldblock:/ q( Y$ B, C' ?. W9 Q3 U* K% \
- :return:* ~& u. k9 K- r$ B6 R, n
- """
- if oldblock["Index"] + 1 != newblock["Index"]:- A. a) O1 F5 @' B5 k
- return False
- if oldblock["Hash"] != newblock["PrevHash"]:
- return False) {. X+ Q3 v" C6 o! p8 U: d
- if calculate_hash(newblock) != newblock["Hash"]:2 N# ?; h- Z8 Y/ u% H6 x) r' V
- return False
- return True</div>
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer
- def run():1 z8 `+ F0 e) ^9 l9 r9 V5 d
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)8 F+ m4 Z1 w4 y8 u1 K
- serv.serve_forever()</div>
- ! C1 y5 `7 p' `! P7 z/ t4 J
- <div>import threading1 N8 P V2 |& S+ G; K T
- from queue import Queue, Empty
- # 定义变量3 D2 X1 N' W$ n: L, C
- block_chain = []
- temp_blocks = []
- candidate_blocks = Queue() # 创建队列,用于线程间通信
- announcements = Queue()1 n3 R' u6 @5 R8 @5 Z
- validators = {}" F3 c3 y. C+ q2 Z; w# B
- My_Lock = threading.Lock()
- class HandleConn(BaseRequestHandler):1 G6 \; n% _4 F0 y+ p0 |
- def handle(self):
- print("Got connection from", self.client_address)
- # validator address" S; K, F/ ]/ p$ C9 V4 d
- self.request.send(b"Enter token balance:")8 ^, O8 l/ s/ q1 w" X5 e
- balance = self.request.recv(8192)
- try:
- balance = int(balance)
- except Exception as e:6 j$ |% ]6 l7 z3 V; U! X; w
- print(e)
- t = str(datetime.now()), W5 w: u7 n" b& u! ?
- address = sha256(t.encode()).hexdigest()! s* f; r( i/ h' ]/ X( }+ m: Z
- validators[address] = balance
- print(validators)
- while True:& `1 B) I1 x$ X! E+ R& M
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
- daemon=True)0 M8 m5 t. A' G) e5 x O
- announce_winner_t.start()4 q' N/ N$ z+ Y' P- x' r! t
- self.request.send(b"\nEnter a new BPM:")5 `" q; W8 j% Z4 T" x
- bpm = self.request.recv(8192)
- try:& @! }6 f) N/ U9 \* T! Y' A: ]' \
- bpm = int(bpm)0 Q6 `+ K3 N9 V" I, N( U( g% x; g1 Y
- except Exception as e:
- print(e): P# l0 J9 ]$ S5 N
- del validators[address]
- break' f5 H$ o* k! w+ X; C) q
- # with My_Lock:
- last_block = block_chain[-1], \5 q; _2 {& A3 {5 `
- new_block = generate_block(last_block, bpm, address)
- if is_block_valid(new_block, last_block):" e) [+ ]: f# l" ]& D5 u4 f7 r
- 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>
- 2 w8 g8 T8 E( q( j. T
- <div># validator address
- self.request.send(b"Enter token balance:")
- balance = self.request.recv(8192)" o, [+ E/ l& Q7 o' d
- try:
- balance = int(balance)4 H+ j" Y! B Q( j, ?7 \* T/ g* U( J
- except Exception as e:
- print(e)( n$ Y/ G5 S {& u
- t = str(datetime.now())5 w7 a. c9 U+ y& f* r! q9 U1 v
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance1 t% L; C/ }* G$ T2 M5 `. D( S- e
- print(validators)</div>
- " @& O0 E1 l: m) [
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),) U. K( g' [, W5 R' X
- daemon=True)
- announce_winner_t.start(). S' f3 X: I- y2 V, Z( d7 J0 B
- def annouce_winner(announcements, request):
- """
- :param announcements:3 Q4 e5 u( S1 \% \% ?1 A
- :param request:
- :return:
- """
- while True:0 n. O4 B# U! q3 a) F( ^
- try:
- msg = announcements.get(block=False)" K& R s1 t6 T
- request.send(msg.encode())
- request.send(b'\n')! W: X# a$ a& b
- except Empty:/ n, K' U( }7 v# i$ N0 a
- time.sleep(3)
- continue</div>
- <div>self.request.send(b"\nEnter a new BPM:")7 ~; p/ ^( _0 ~* q
- bpm = self.request.recv(8192)
- try:
- bpm = int(bpm)
- except Exception as e:( X: h3 F1 T+ h9 N/ p
- print(e)1 {/ b/ M1 Y* Y9 g
- del validators[address]9 s8 J8 ?% P! G% P: @' l+ S3 O
- break/ a- u7 K0 q m* _/ n" ?6 f8 ?6 j, l
- # with My_Lock:
- last_block = block_chain[-1]- i1 |) ?# T% y
- new_block = generate_block(last_block, bpm, address)8 a$ h4 i V' u6 i2 v& l
- if is_block_valid(new_block, last_block):: n4 u6 ^- P; [9 E
- print("new block is valid!")2 G/ E/ ^4 M0 Y8 e. Y
- candidate_blocks.put(new_block)</div>
- & n' B( `, G) B) z$ c5 r
- <div>annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)
- annouce_blockchain_t.start()
- def annouce_blockchain(request):
- """
- :param request:
- :return:
- """
- while True:
- time.sleep(30)
- with My_Lock:
- output = json.dumps(block_chain)
- try:, o9 F) ?7 j6 j4 A
- request.send(output.encode())( W* g n1 z: d* G
- request.send(b'\n')
- except OSError:8 y; q/ |7 h: H
- pass</div>
- <div>def pick_winner(announcements):, }; y& T" @- J( z2 [( ^* G2 L
- """
- 选择记账人& [% |2 @: l# i" t
- :param announcements:" \5 X* h; z+ K. G
- :return:+ ]7 Q/ t) ^1 Q4 `3 ]
- """" }7 n7 u) s# Y, a4 ]
- time.sleep(10)
- while True:
- with My_Lock:! W! z& b* W; ^# w
- temp = temp_blocks+ Y" j% j- H2 ~" k4 ]. w" h
- lottery_pool = [] #6 @9 q2 z4 B% f7 _4 N+ e8 l F1 i
- if temp:1 f M6 y/ C* `9 l2 }4 T
- for block in temp:
- if block["Validator"] not in lottery_pool:9 ?, ], E! w8 n: C
- set_validators = validators
- k = set_validators.get(block["Validator"])
- if k:# X% [) W; g" j* l7 m6 P2 Q- x
- for i in range(k):
- lottery_pool.append(block["Validator"])
- lottery_winner = choice(lottery_pool)
- print(lottery_winner)
- # add block of winner to blockchain and let all the other nodes known: c: F% _# b5 H+ ^( e2 R x/ U' O! T
- for block in temp:* ^( L" N, A) ]. t$ H
- if block["Validator"] == lottery_winner:8 n T9 ~$ b3 S$ ^9 H
- with My_Lock:, x; i4 R. Y" e/ ]
- block_chain.append(block)
- # write message in queue.
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner); c: t/ o& | |! f, Q5 B4 b h
- announcements.put(msg)) Z! U$ l. q }1 I# v. f' w8 }8 v
- break
- with My_Lock:' A6 k4 H" V G
- temp_blocks.clear()</div>
- <div>def run():
- # create a genesis block% A, h2 u/ ~. n+ I! J% V
- t = str(datetime.now())
- genesis_block = {
- "Index": 0,
- "Timestamp": t,
- "BPM": 0,6 S+ }3 j4 W: r2 Z
- "PrevHash": "",7 ^6 _% p5 _' g% n- D
- "Validator": ""0 C5 f. g. t$ l& G
- }4 @; N# f2 {4 N! y* \
- genesis_block["Hash"] = calculate_hash(genesis_block)
- print(genesis_block)
- block_chain.append(genesis_block)7 b) {% ~ h1 K/ N b% M; C
- 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()- Q0 `8 G$ U5 ~/ d* ^% Z, g
- thread_pick.start()
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)/ s( y/ G9 x( k3 R% }
- serv.serve_forever()
- def candidate(candidate_blocks):
- """
- :param candidate_blocks:5 `, e S& B% a! j" M1 X- C
- :return:' l/ E; s. Y) j. c- Z/ K
- """
- while True:( x, U- D+ D6 S2 u$ c4 Y) d& H
- try:5 Z) H4 j1 |$ M2 f; T- c2 B
- candi = candidate_blocks.get(block=False)
- except Empty:
- time.sleep(5)* E2 Q2 |1 e0 B& H. o
- continue
- temp_blocks.append(candi)
- if __name__ == '__main__':
- run()</div>