- 0 M0 y, z8 k3 f0 Q9 g. `* M3 @2 P w
- <div>from hashlib import sha256
- from datetime import datetime
- def generate_block(oldblock, bpm, address):6 b% E9 f2 ~. K" P2 B- U
- """7 L H# Y, Y0 ?$ F$ F8 c: l) D% G4 G
- :param oldblock:
- :param bpm:
- :param address:9 m8 _9 @5 \. [( l& q
- :return:- X ~0 ~3 s* n% d+ f) M
- """0 [9 e! `; O5 P7 ^& V8 l4 w
- newblock = {
- "Index": oldblock["Index"] + 1,
- "BPM": bpm,
- "Timestamp": str(datetime.now()),
- "PrevHash": oldblock["Hash"],
- "Validator": address
- }; ]9 u7 X2 k8 s& N
- newblock["Hash"] = calculate_hash(newblock)
- return newblock7 J2 Z! s) w& r
- def calculate_hash(block):
- record = "".join([& ?" q+ u v B; B+ j
- str(block["Index"]),
- str(block["BPM"]),; E7 W$ e5 a* m0 @' d. o, e# c
- block["Timestamp"],% T' J7 P+ y8 s7 L3 M
- block["PrevHash"]
- ])7 S& ` w0 U3 w) G
- return sha256(record.encode()).hexdigest()
- def is_block_valid(newblock, oldblock):0 D5 Y' e- X+ f* b! N3 t
- """
- :param newblock:
- :param oldblock:
- :return:# A! h3 P1 q2 W( b& p' k! R) a
- """
- if oldblock["Index"] + 1 != newblock["Index"]:/ g# r T* t1 R! Q( H
- return False' r0 p Z: B! s- m* o
- if oldblock["Hash"] != newblock["PrevHash"]:
- return False
- if calculate_hash(newblock) != newblock["Hash"]:; I: o1 p5 k* i: F$ y" M: W. C; t1 W
- return False
- return True</div>
- <div>from socketserver import BaseRequestHandler, ThreadingTCPServer" ^! W7 g1 q+ E' G+ E: r
- def run():
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)1 W$ f3 ^# {2 S$ ^
- serv.serve_forever()</div>
- <div>import threading
- from queue import Queue, Empty( O* @! B& B/ j5 e
- # 定义变量
- block_chain = []
- temp_blocks = []
- candidate_blocks = Queue() # 创建队列,用于线程间通信
- announcements = Queue()
- validators = {}
- My_Lock = threading.Lock()
- class HandleConn(BaseRequestHandler):/ r0 W: X2 M" B
- def handle(self):
- print("Got connection from", self.client_address)
- # validator address
- self.request.send(b"Enter token balance:")" V' k1 U" H5 y6 v+ e% N: D( ^* n
- balance = self.request.recv(8192)
- try:5 h! P# V8 A4 g) v& t" o
- balance = int(balance)
- except Exception as e:
- print(e)
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance p9 E2 }5 N/ x0 B2 Q5 ^( U4 O
- print(validators)& P: k4 w/ |3 L# f$ E8 [! U
- while True:
- announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),, S6 M }. G2 g2 A2 p& b+ w
- daemon=True)' _9 ?: i& }2 b9 D5 M% e+ A9 _
- announce_winner_t.start()
- self.request.send(b"\nEnter a new BPM:")1 B# I j0 C% |- B
- bpm = self.request.recv(8192)/ w1 Q! ?) s3 U. [# k
- try:, Z, w- {, y1 N! Z2 L
- bpm = int(bpm)$ _) \0 r, t0 i
- except Exception as e:! N" Y8 _* f4 v# O
- print(e)
- del validators[address]
- break1 g( W }. A7 P. [9 @' q4 s
- # with My_Lock:: E$ O3 _4 o: S* ^# N
- last_block = block_chain[-1]& U. _2 {( v: ~1 Y3 O9 E& }' S
- 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)
- 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>
- 8 k+ l5 ?9 M5 ?2 I3 ~
- <div># validator address$ T6 y7 z+ S, j0 U
- self.request.send(b"Enter token balance:"). |5 Z v1 Y' |3 C
- balance = self.request.recv(8192)' u3 B, W& t+ @2 E% _
- try:* [9 u% b. I+ o, {
- balance = int(balance)! l! C3 l p2 q1 H3 V
- except Exception as e:
- print(e)
- t = str(datetime.now())
- address = sha256(t.encode()).hexdigest()
- validators[address] = balance& ~- t( ^- T% P. b
- print(validators)</div>
- <div>announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
- daemon=True)& T* A) C9 x0 r8 l/ X
- announce_winner_t.start()
- def annouce_winner(announcements, request):; p- @- c4 X! q9 r) O/ u
- """
- :param announcements:
- :param request:
- :return:
- """
- while True:) z- N( p* j" d
- try:, C$ A& {( \7 |1 u& Y
- msg = announcements.get(block=False)/ W1 Z& d/ x6 }! a+ `. @" R/ b$ f
- request.send(msg.encode())
- request.send(b'\n')7 z4 S: M! x5 E7 U# D
- except Empty: W7 k; R0 m) J# C$ Y8 }
- time.sleep(3)
- continue</div>
- <div>self.request.send(b"\nEnter a new BPM:")4 v' O$ e: s( l7 ?
- bpm = self.request.recv(8192)) ]3 Y- w- A$ Q1 Z T- l! X0 W3 X
- try:2 e" F2 ?( F' v$ d y* \
- bpm = int(bpm)- [: m8 ? W9 z! q, V
- except Exception as e:
- print(e)
- del validators[address]
- break
- # with My_Lock:
- 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!")( D3 G. L0 ~+ Z' I/ d
- candidate_blocks.put(new_block)</div>
- <div>annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)
- annouce_blockchain_t.start() ?6 W$ H$ e/ G/ [8 d/ z3 f
- def annouce_blockchain(request):
- """
- :param request:
- :return:
- """
- while True:
- time.sleep(30)! Z3 `# L- B6 g" w c8 I' h
- with My_Lock:
- output = json.dumps(block_chain)
- try:4 j: e# y7 q* l' m8 F3 h
- request.send(output.encode())
- request.send(b'\n')
- except OSError:1 i* U# f2 t( O% R- t
- pass</div>
- , w1 e& |3 e9 ^
- <div>def pick_winner(announcements):0 H/ j! O) d: b! H! r8 P9 a; S
- """
- 选择记账人
- :param announcements:7 z/ q& a+ `- k2 d! g1 ^
- :return:" }$ G, q9 w5 a% r: f0 l8 ]
- """
- time.sleep(10)% ?1 Y8 `, ` _; U! p0 N" ^7 U( X
- while True:6 h7 P" G. g/ E
- with My_Lock:' Z$ m8 }5 t' T0 l7 ~
- temp = temp_blocks. H) A4 k- U* X, \# u
- lottery_pool = [] #' G' V. \4 Q2 g% i
- if temp:$ a' Y1 r# A4 }. C
- for block in temp:
- if block["Validator"] not in lottery_pool:
- set_validators = validators/ S, e1 s7 `. W8 W+ g- E2 `
- k = set_validators.get(block["Validator"])
- if k:
- for i in range(k):
- lottery_pool.append(block["Validator"])
- lottery_winner = choice(lottery_pool): y3 V* T' @9 b. A$ j2 @$ c3 m
- print(lottery_winner). ]7 x9 r- e' `; M
- # 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:
- block_chain.append(block)
- # write message in queue.+ O" D9 m$ g% X
- msg = "\n{0} 赢得了记账权利\n".format(lottery_winner)
- announcements.put(msg)% M: X" u6 e( ], Q/ n8 u$ R# Q
- break, E: r2 \9 ^$ Z
- with My_Lock:
- temp_blocks.clear()</div>
- % T! C% N v# G) D- ^8 l9 q+ L2 S5 Q
- <div>def run():
- # create a genesis block
- t = str(datetime.now())
- genesis_block = {% {0 G" `" v5 J( r. v9 l
- "Index": 0,
- "Timestamp": t,
- "BPM": 0,
- "PrevHash": "", i L6 m/ m1 K2 c6 ?& B9 j2 M& h
- "Validator": "". H% a1 {+ |: X5 A3 D4 F& k2 m& w
- }
- genesis_block["Hash"] = calculate_hash(genesis_block)4 @* `. z5 e( ~" S8 e, a/ J
- print(genesis_block)
- block_chain.append(genesis_block)7 O$ R5 r: L( ?4 o0 o9 g* h# {
- thread_canditate = threading.Thread(target=candidate, args=(candidate_blocks,), daemon=True)8 m; L. C. P% {) k4 _ H
- thread_pick = threading.Thread(target=pick_winner, args=(announcements,), daemon=True)
- thread_canditate.start()4 c6 X. }' q& v T
- thread_pick.start()' c$ U1 C% D: v' Q( ~
- # start a tcp server
- serv = ThreadingTCPServer(('', 9090), HandleConn)) k2 r8 H8 e7 G& R; C
- serv.serve_forever()
- def candidate(candidate_blocks):% e- j' E, q& T, S3 b5 M
- """
- :param candidate_blocks:! ^. ]* Q6 l" ?' O, I- {
- :return:% u0 S- h; e7 L- m; W" J" ]: ]- J
- """% s1 ~0 O& G# J+ F; X: m9 \
- while True:
- try:9 C, ?( d) h+ G- ?
- candi = candidate_blocks.get(block=False)$ P1 R9 g$ @5 _- i) ]2 _
- except Empty:
- time.sleep(5)
- continue
- temp_blocks.append(candi)1 I* B! M+ L( M; L6 s
- if __name__ == '__main__':2 U- _: P4 A" l5 v* A
- run()</div>