Python POS 알고리즘 기반 블록 체인 구현
비트 코 인 퍼 블 릭 체인 구조 분석 에서 탈 중개 화 디자인 을 실현 하기 위해 비트 코 인 은 공 통 된 협 의 를 설계 하고 이 협 의 를 통 해 시스템 의 안정성 과 공격 성 을 확보한다 고 언급 한 적 이 있다.그리고 우 리 는 지금까지 가장 광범 위 하 게 사용 되 고 사람들 에 게 가장 받 아들 여진 공 통 된 알고리즘 이 우리 가 이전에 소개 한 POW(proof of work)작업량 증명 알고리즘 이라는 것 을 알 고 있다.현재 시가 상위 2 위인 비트 코 인과 이 더 리 움 도 이 알고리즘 을 사용 하고 있다.
POW 컨 센서 스 알고리즘 이 큰 성공 을 거 두 었 지만 그 에 대한 의문 도 멈 춘 적 이 없다.그 중 가장 중요 한 원인 은 전력 소모 이다.불완전한 통계 에 따 르 면 POW 의 채굴 체 제 를 바탕 으로 소모 하 는 전력 은 매우 크 고 심지어 절대 다수의 국가 보다 전력 소비량 이 더 많다.이것 은 우리 의 자원 에 큰 낭 비 를 초래 했다.그 밖 에 비트 대륙 등 회사 의 강세 에 따라 산 력 의 높 은 집중 을 초래 했다.
상기 여러 가지 원인 을 바탕 으로 더 많은 공감 대 알고리즘 은 POS,DPOS,BPFT 등 이 제시 되 었 다.오늘 은 POS(proof stake)알고리즘 을 알 아 보 겠 습 니 다.
Proof of stake,권익 증명 으로 번역.권익 증명 은 간단하게 이해 하면 더 많은 token 을 가 진 사람 이 더 큰 확률 로 기장 권 리 를 얻 고 보상 을 받 을 수 있다 는 것 을 알 수 있 습 니 다.이 확률 은 구체 적 으로 얼마나 됩 니까?다음은 코드 구현 에서 보 여 드 리 고 분석 도 뒤에 놓 겠 습 니 다.물론 POS 가 POW 보다 더 좋 을 까?더 중심 화 되 나 요?지금 보기에 반드시 그렇지 는 않 기 때문에 우 리 는 여기 서도 누가 좋 고 누가 나 쁜 지 비교 하지 않 는 다.우 리 는 중립 적 인 입장 에서 단순히 POS 라 는 알고리즘 을 토론 했다.
코드 실전
Block 생 성
POS 알고리즘 을 실현 하려 면 하나의 체인 을 생 성 하 는 것 을 피하 기 어렵 고 체인 은 하나의 Block 에 의 해 생 성 되 기 때문에 먼저 Block 을 어떻게 생 성 하 는 지 살 펴 보 겠 습 니 다.물론 앞의 내용 에서 Block 을 어떻게 생 성 하 는 지,그리고 거래,UTXO 등 이 소개 되 었 습 니 다.오늘 우리 의 핵심 은 POS 를 실현 하 는 것 이기 때문에 Block 의 생 성에 대해 우 리 는 가장 간단 한 실현 방식 으로 여러분 들 이 핵심 적 인 내용 에 초점 을 맞 출 수 있 도록 하 겠 습 니 다.
우 리 는 세 가지 방법 으로 합 법 적 인 블록 을 만 드 는 것 을 실현 한다.
from hashlib import sha256
from datetime import datetime
def generate_block(oldblock, bpm, address):
"""
:param oldblock:
:param bpm:
:param address:
:return:
"""
newblock = {
"Index": oldblock["Index"] + 1,
"BPM": bpm,
"Timestamp": str(datetime.now()),
"PrevHash": oldblock["Hash"],
"Validator": address
}
newblock["Hash"] = calculate_hash(newblock)
return newblock
def calculate_hash(block):
record = "".join([
str(block["Index"]),
str(block["BPM"]),
block["Timestamp"],
block["PrevHash"]
])
return sha256(record.encode()).hexdigest()
def is_block_valid(newblock, oldblock):
"""
:param newblock:
:param oldblock:
:return:
"""
if oldblock["Index"] + 1 != newblock["Index"]:
return False
if oldblock["Hash"] != newblock["PrevHash"]:
return False
if calculate_hash(newblock) != newblock["Hash"]:
return False
return True
여기 서 더욱 유연 하기 위해 우 리 는 클래스 의 실현 방식 을 사용 하지 않 고 함수 로 Block 생 성 을 실현 하여 쉽게 이해 할 수 있 을 것 이 라 고 믿 습 니 다.TCP 서버 만 들 기
우 리 는 권익 증명 알고리즘 으로 기장 자 를 선택해 야 하기 때문에 많은 Node(노드)에서 기장 자 를 선택해 야 한다.즉,서버 가 노드 를 연결 시 키 는 동시에 정 보 를 노드 에 동기 화해 야 한다.따라서 TCP 긴 링크 가 필요 합 니 다.
from socketserver import BaseRequestHandler, ThreadingTCPServer
def run():
# start a tcp server
serv = ThreadingTCPServer(('', 9090), HandleConn)
serv.serve_forever()
여기 서 우 리 는 python 내 라 이브 러 리 socketserver 로 TCPServer 를 만 들 었 습 니 다.주의해 야 할 것 은 여기 서 우리 가 사용 하 는 다 중 스 레 드 생 성 방식 입 니 다.이렇게 하면 여러 개의 클 라 이언 트 가 동시에 연결 되 고 막 히 지 않도록 보장 할 수 있 습 니 다.물론 이 server 도 문제 가 있 습 니 다.바로 몇 개의 클 라 이언 트 가 연결 되 어 있 으 면 몇 개의 스 레 드 를 만 들 고 더 좋 은 방법 은 스 레 드 풀 을 만 드 는 것 입 니 다.이곳 은 테스트 이기 때문에 더욱 간단 한 방식 을 채택 했다.보시 다시 피 저희 가 TCPServer 를 만 들 때 HandleConn 을 사 용 했 습 니 다.하지만 아직 정의 가 되 지 않 았 기 때문에 HandleConn 을 정의 하 겠 습 니 다.
메시지 처리 장치
다음은 Handler 함 수 를 실현 하 겠 습 니 다.Handler 함 수 는 Client Node 와 통신 할 때 우리 의 Node 가 아래 의 기능 을 실현 해 야 합 니 다.
BPM 생 성 블록 을 입력 하 십시오4.567917.한 블록 의 합 법성 검증
임무 가 꽤 많은 것 같 습 니 다.다음은 코드 가 실현 되 는 것 을 보 겠 습 니 다.
import threading
from queue import Queue, Empty
#
block_chain = []
temp_blocks = []
candidate_blocks = Queue() # ,
announcements = Queue()
validators = {}
My_Lock = threading.Lock()
class HandleConn(BaseRequestHandler):
def handle(self):
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:
print(e)
t = str(datetime.now())
address = sha256(t.encode()).hexdigest()
validators[address] = balance
print(validators)
while True:
announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
daemon=True)
announce_winner_t.start()
self.request.send(b"
Enter a new BPM:")
bpm = self.request.recv(8192)
try:
bpm = int(bpm)
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!")
candidate_blocks.put(new_block)
self.request.send(b"
Enter a new BPM:
")
annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True)
annouce_blockchain_t.start()
이 코드 는 대부분의 학생 들 에 게 어 려 울 수 있 습 니 다.여기 서 우 리 는 다 중 스 레 드 방식 을 사용 하 는 동시에 메시지 온라인 스 레 드 간 통신 을 할 수 있 도록 대기 열 을 사 용 했 습 니 다.여기 서 대기 열 을 사용 하 는 것 도 우리 의 시스템 을 더욱 잘 확대 하기 위해 서 이다.나중에 가능 하 다 면 이 절 의 프로그램 은 분포 식 시스템 으로 쉽게 확대 할 수 있다.다 중 스 레 드 에서 처리 하 는 임 무 를 독립 된 서비스 로 나 눈 다음 에 메시지 큐 로 통신 하 는 것 은 간단 한 분포 식 시스템 입 니 다.(설 레 죠?)여기 가 어렵 기 때문에 코드 는 그래도 말 해 보 세 요.
# validator address
self.request.send(b"Enter token balance:")
balance = self.request.recv(8192)
try:
balance = int(balance)
except Exception as e:
print(e)
t = str(datetime.now())
address = sha256(t.encode()).hexdigest()
validators[address] = balance
print(validators)
이 부분 은 우리 가 언급 한 Node 클 라 이언 트 가 자신 이 후보 에 게 추가 한 코드 입 니 다.클 라 이언 트 를 연결 할 때마다 후 보 를 추가 합 니 다.여기에 우 리 는 추 가 된 타임 스탬프 의 hash 로 후 보 를 기록한다.물론 다른 방식 으로 도 사용 할 수 있 습 니 다.예 를 들 어 우리 코드 에 있 는 clientaddress
announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,),
daemon=True)
announce_winner_t.start()
def annouce_winner(announcements, request):
"""
:param announcements:
:param request:
:return:
"""
while True:
try:
msg = announcements.get(block=False)
request.send(msg.encode())
request.send(b'
')
except Empty:
time.sleep(3)
continue
그 다음 에 우 리 는 기장 권 을 얻 은 노드 정 보 를 모든 노드 로 방송 하 는 스 레 드 를 만 들 었 다.
self.request.send(b"
Enter a new BPM:")
bpm = self.request.recv(8192)
try:
bpm = int(bpm)
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!")
candidate_blocks.put(new_block)
노드 가 입력 한 BPM 값 에 따라 블록 을 만 들 고 블록 의 유효성 을 검증 합 니 다.유효한 블록 을 후보 블록 에 넣 고 기장 자가 블록 을 체인 에 추가 하 기 를 기다 리 고 있 습 니 다.
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:
request.send(output.encode())
request.send(b'
')
except OSError:
pass
마지막 스 레 드 를 시작 하여 모든 노드 에 블록 체인 을 동기 화 합 니 다.다 봤 습 니 다.노드 와 Server 가 상호작용 하 는 부분 은 그 다음 에 가장 중요 한 부분 입 니 다.
POS 알고리즘 구현
def pick_winner(announcements):
"""
:param announcements:
:return:
"""
time.sleep(10)
while True:
with My_Lock:
temp = temp_blocks
lottery_pool = [] #
if temp:
for block in temp:
if block["Validator"] not in lottery_pool:
set_validators = validators
k = set_validators.get(block["Validator"])
if k:
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
for block in temp:
if block["Validator"] == lottery_winner:
with My_Lock:
block_chain.append(block)
# write message in queue.
msg = "
{0}
".format(lottery_winner)
announcements.put(msg)
break
with My_Lock:
temp_blocks.clear()
여기 우리 pickwinner 는 기장 권 리 를 선택 합 니 다.우 리 는 token 수량 에 따라 목록 을 만 들 었 습 니 다.한 사람 이 기장 권 리 를 얻 을 확률 은:p = mount['NodeA']/mount['All']
문자 설명 은 token 수가 전체 에서 차지 하 는 비례 입 니 다.예 를 들 어 총 수 는 100 개 이 고 그 는 10 개 이다.그러면 기장 권 을 얻 을 확률 은 0.1 이다.여기 서 핵심 부분 은 많이 다 르 지 않다.그 다음 에 노드 를 추가 하고 테스트 를 시작 하 자.POS 의 기장 방식 을 시험 하 다
테스트 하기 전에 시작 부분 에서 해 야 할 일이 있 습 니 다.앞에서 우리 의 run 방법 은 보완 해 야 합 니 다.코드 는 다음 과 같 습 니 다.
def run():
# create a genesis block
t = str(datetime.now())
genesis_block = {
"Index": 0,
"Timestamp": t,
"BPM": 0,
"PrevHash": "",
"Validator": ""
}
genesis_block["Hash"] = calculate_hash(genesis_block)
print(genesis_block)
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()
thread_pick.start()
# start a tcp server
serv = ThreadingTCPServer(('', 9090), HandleConn)
serv.serve_forever()
def candidate(candidate_blocks):
"""
:param candidate_blocks:
:return:
"""
while True:
try:
candi = candidate_blocks.get(block=False)
except Empty:
time.sleep(5)
continue
temp_blocks.append(candi)
if __name__ == '__main__':
run()
TCPServer 에 노드 추가프로그램의 복잡성 을 충분히 줄 이기 위해 tcp client 는 이 루어 지지 않 습 니 다.뒤쪽 으로 확장 할 수 있 습 니 다.어쨌든 우리 시스템 은 쉽게 확장 할 수 있 습 니 다.그 다음 에 우 리 는 다 중 스 레 드 부분 을 나 누 었 습 니 다.tcp client 를 실현 하 는 것 은 완전한 분포 식 시스템 입 니 다.
그래서 우 리 는 Liux 자체 명령 nc 를 사용 합 니 다.nc 를 어떻게 사용 하 는 지 모 르 는 학생 들 이 google 이나 man nc 를 사용 할 수 있 습 니 다.
서비스 시작 python pos.py 실행
터미널 3 개 열기
각각 아래 명령 을 입력 하 다
nc localhost 9090
터미널 출력Enter token balance:
클 라 이언 트 가 서버 ok 에 연결 되 어 있다 는 뜻 입 니 다.
POS 의 기장 방식 을 시험 하 다
다음은 순서대로 제시 에 따라 조작한다.balance 는 기분 에 따라 조작 할 수 있 습 니 다.여 기 는 테스트 이기 때문에 100 을 입력 합 니 다.
이 어 BPM 입력 을 알려 드 리 겠 습 니 다.앞서 말씀 드 렸 듯 이 BPM 을 입력 하 는 것 은 Block 을 만 들 기 위해 서 입 니 다.그럼 입력 하 세 요.9.ok 을 마음대로 입력 하 세 요.그 다음 에 잠시 기 다 려 서 기장 을 기다 리 겠 습 니 다.
출력
순서대로 서로 다른 터미널 에서 알림 에 따라 숫자 를 입력 하고 메시지 가 동기 화 되 기 를 기다린다.
블록 체인 생 성
다음은 제 가 얻 은 블록 정보 세 개 입 니 다.
총결산
위의 코드 에서 우 리 는 POS 알고리즘 을 바탕 으로 장 부 를 기록 하 는 완전한 체인 을 실현 했다.물론 여기 에는 확장 되 고 개선 할 만 한 부분 이 많다.
4.567917.시스템 은 성분 포 식 을 확대 하여 더욱 건장 하 게 할 수 있다.
대략 상기 몇 가 지 를 열 거 했 고 다른 것 은 넓 힐 수 있 는 곳 이 많 습 니 다.관심 이 있 는 친 구 는 먼저 놀 수 있 고 후 자 는 우리 뒤의 튜 토리 얼 을 기다 릴 수 있 습 니 다.(광고 에 미 처 손 을 쓸 수가 없다.하하)
물론 언어 가 중요 하지 않 기 때문에 여기 서 저도 go 언어의 버 전 소스 주 소 를 실 현 했 습 니 다.
go 언어의 실현 감각 은 좀 더 잘 이해 하고 우아 하 게 보 여야 한다.이것 도 고 언어 가 분포 식 분야 에서 더욱 잘 팔 리 는 이유 중 하나 입 니 다!
항목 주소
https://github.com/csunny/py-bitcoin/
레 퍼 런 스
https://medium.com/@mycoralhealth/code-your-own-proof-of-stake-blockchain-in-go-610cd99aa658
총결산
위 에서 말씀 드 린 것 은 소 편 이 소개 한 Python 이 POS 알고리즘 을 기반 으로 한 블록 체인 을 실현 하 는 것 입 니 다.여러분 께 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.소 편 이 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.