g-coin 분석(0) : g-coin 분석(0)
이전 게시글의 분석글을 위의 링크로 보실 수 있습니다.
이제 이전 분석을 이어가보도록 하겠습니다.
분석
남은 blockchain.py, miner.py, node.py, proof.py 는 현재 게시글에서 정리를 이어가도록 하겠습니다.
proof.py
import hashlib import gcoin.config as cfg def valid_proof(block, proof=None): """ Validates proof last digits of hash(previous_block.header, proof) == config.PROOF_DIGITS Args: block (obj): proof (int): proof to validate Returns: bool: """ proof = proof if proof else block.proof proof_seed = '{0}{1}'.format(block.header.hash(), proof).encode() proof_hash = hashlib.sha256(proof_seed).hexdigest() return proof_hash[:block.difficulty] == cfg.PROOF_DIGITS * block.difficulty def find_proof(block): """proof of work Args: block (obj): Returns: int: proof """ proof = 0 while valid_proof(block, proof) is False: proof += 1 return proof
proof.py는 config.py 파일을 불러옵니다.
그리고 두개의 함수가 있네요.
def valid_proof(block, proof=None): """ Validates proof last digits of hash(previous_block.header, proof) == config.PROOF_DIGITS Args: block (obj): proof (int): proof to validate Returns: bool: """ proof = proof if proof else block.proof proof_seed = '{0}{1}'.format(block.header.hash(), proof).encode() proof_hash = hashlib.sha256(proof_seed).hexdigest() return proof_hash[:block.difficulty] == cfg.PROOF_DIGITS * block.difficulty
def find_proof(block): """proof of work Args: block (obj): Returns: int: proof """ proof = 0 while valid_proof(block, proof) is False: proof += 1 return proof
인자로 넘겨받는 블록을 유요할때까지 계속 while문으로 돌리는 것을 볼 수 있었습니다.
유효한 해쉬값을 찾을때까지 +=1 을 하여 리턴하네요 !
miner.py
import gcoin.config as cfg import gcoin.proof as proof from gcoin.transaction import Transaction class Miner: def __init__(self, account_id): self.account_id = account_id def __call__(self, blockchain): # Adding mining rewards transaction = Transaction(cfg.GENESIS_ACCOUNT_ID, self.account_id, cfg.AMOUNT_OF_REWARD) blockchain.add_transaction(transaction) # Make new block with transactions and hash of last block new_block = blockchain.new_block() # Proof of Work new_proof = proof.find_proof(new_block) new_block.proof = new_proof blockchain.add_block(new_block) return new_block
채굴하는 코드입니다!!!
채굴!!! 가즈아!!!!!!
먼저 3개의 코드를 불러오는 것을 볼 수 있습니다.
config.py, proof.py, transaction.py
그리고 초기화에서 account_id 를 클래스 자신에게 대입을 하네요.
아마도 이 계정은 채굴자의 계정이 아닐까 싶습니다 :D
그리고 채굴의 기여한 내용을 거래 기록에 남기네요.
그리고 추가를 하구요.
그리고 채굴되었다면 새로운 블럭을 생성하여 채굴이 완료되는 것을 볼 수 있습니다.
그 뒤 새로운 블럭에 유효한 증명을 하여 새로운 블럭에 대입하고 블록체인에 추가를 하고 새로운 블럭을 리턴을 해주는 코드네요.
blockchain.py
import gcoin.proof import gcoin.config as cfg from gcoin.book import Book from gcoin.block import Block class BlockChain: def __init__(self, chain=None): """init chain with existing chain or make this new blockchain Args: chain: list of dictionary of Block, see load_chain """ self.chain = [] self.book = Book() self.transactions = [] if chain: self.load_chain(chain) else: self.init_chain() def init_chain(self): """Make genesis block""" genesis_block = Block([], previous_hash=cfg.GENESIS_HASH) genesis_proof = gcoin.proof.find_proof(genesis_block) genesis_block.proof = genesis_proof self.add_block(genesis_block) def add_transaction(self, transaction): """Add new transaction It will only add amount Args: transaction (obj): Transaction object Returns: int: index of next block of chain return -1 if it's not correct transaction """ if self.book.check_balance(transaction): self.transactions.append(transaction) return len(self.chain) + 1 # Add this transaction to next block else: raise Exception('Transaction is wrong.') def new_block(self): last_block = self.chain[-1] block = Block(self.transactions, previous_hash=last_block.hash()) self.transactions = [] return block def add_block(self, block): self.chain.append(block) self.book.apply(block.transactions) def valid(self): """Valid chain""" index = 1 while index < len(self): prev_block = self.chain[index-1] curr_block = self.chain[index] # Check hash with previous hash if curr_block.previous_hash != prev_block.hash(): return False # Check proof of current block if not gcoin.proof.valid_proof(curr_block): return False index += 1 return True def load_chain(self, chain): """load chain from list of dictionary from existing blockchain Args: chain (list): [{ transactions: [{ sender: 'dsf9s9f0ad' recipient: 'dfsad90fasf' amount: 12 }] proof: 318832940000 previous_hash: 'fj9afje9ajf9sef0s0f' timestamp: 1506057125.900785 }] """ for block in chain: block = Block.init_from_json(block) self.add_block(block) def last_block(self): return self.chain[-1] def dump(self): return [block.dump() for block in self.chain] def __len__(self): return len(self.chain)
이게 바로 제일 중요한 블록체인에 대한 코드가 아닐까 싶습니다.
찬찬히 코드를 살펴보도록 합시다!!!
def __init__(self, chain=None): """init chain with existing chain or make this new blockchain Args: chain: list of dictionary of Block, see load_chain """ self.chain = [] self.book = Book() self.transactions = [] if chain: self.load_chain(chain) else: self.init_chain()
def init_chain(self): """Make genesis block""" genesis_block = Block([], previous_hash=cfg.GENESIS_HASH) genesis_proof = gcoin.proof.find_proof(genesis_block) genesis_block.proof = genesis_proof self.add_block(genesis_block)
먼저 블록체인을 위해 리스트와 통장(?)과 거래 기록을 초기화하는 것을 볼 수 있습니다.
그 후 체인이 있을 경우 load_chain함수로 생성한 체인에 로드하네요.
아닐 경우엔 init_chain으로 체인을 초기화하는 것을 볼 수 있습니다.
블록체인에 첫 블록을 추가하는 부분이네요 ㅎㅎ
def add_transaction(self, transaction): """Add new transaction It will only add amount Args: transaction (obj): Transaction object Returns: int: index of next block of chain return -1 if it's not correct transaction """ if self.book.check_balance(transaction): self.transactions.append(transaction) return len(self.chain) + 1 # Add this transaction to next block else: raise Exception('Transaction is wrong.')
거래 기록 object를 받네요!
check_balance로 거래기록을 받은 것을 인자로 넘겨주어 제대로된 거래인지 확인을 합니다.
제대로 된 거래일 경우 거래 기록에 추가하고 체인에 대해 길이 +1을 하네요.
def new_block(self): last_block = self.chain[-1] block = Block(self.transactions, previous_hash=last_block.hash()) self.transactions = [] return block def add_block(self, block): self.chain.append(block) self.book.apply(block.transactions)
마지막 블록이라는 변수에 체인의 마지막 블록을 대입하며 블록을 생성하네요!
생성한 블럭은 반환해주네요!
그리고 말그대로 블럭체인에 블럭을 추가하는 코드입니다.
def load_chain(self, chain): """load chain from list of dictionary from existing blockchain Args: chain (list): [{ transactions: [{ sender: 'dsf9s9f0ad' recipient: 'dfsad90fasf' amount: 12 }] proof: 318832940000 previous_hash: 'fj9afje9ajf9sef0s0f' timestamp: 1506057125.900785 }] """ for block in chain: block = Block.init_from_json(block) self.add_block(block)
네 이건 json 데이터를 받아 block 을 초기화하고 블록체인에 추가하네요.
그 외엔 딱히 중요한 내용은 없는 것 같습니다.
node.py
import requests from uuid import uuid4 from gcoin.blockchain import BlockChain class Node: def __init__(self, id=None): self.id = id if id else self._generate_id() self.neighbor = set() @staticmethod def _generate_id(): return str(uuid4()).replace('-', '') def add(self, address): self.neighbor.add(address) def __len__(self): return len(self.neighbor) @staticmethod def fetch_neighbor_chain(address): res = requests.get('{0}/chain'.format(address)) return res.json() def consensus_with_neighbor(self, blockchain): """Consensus conflicts with neighbor Args: blockchain (obj): BlockChain object of mine for consensus Returns: obj or None: None if my blockchain is King new BlockChain object if my blockchain is looser """ new_blockchain = None max_length = len(blockchain) for node in self.neighbor: data = self.fetch_neighbor_chain(node) if data['length'] > max_length: new_blockchain = BlockChain(chain=data['chain']) if not new_blockchain.valid(): new_blockchain = None else: max_length = len(new_blockchain) return new_blockchain
네 드디어 마지막 파일입니다!!!!
def fetch_neighbor_chain(address): res = requests.get('{0}/chain'.format(address)) return res.json()
chain에 get 리퀘스트를 쏴서 현재 블록체인들의 json 파일을 리턴해주네요.
def consensus_with_neighbor(self, blockchain): """Consensus conflicts with neighbor Args: blockchain (obj): BlockChain object of mine for consensus Returns: obj or None: None if my blockchain is King new BlockChain object if my blockchain is looser """ new_blockchain = None max_length = len(blockchain) for node in self.neighbor: data = self.fetch_neighbor_chain(node) if data['length'] > max_length: new_blockchain = BlockChain(chain=data['chain']) if not new_blockchain.valid(): new_blockchain = None else: max_length = len(new_blockchain) return new_blockchain
블록체인을 인자로 받아 현재 체인에 대해 추가하는 코드 부분입니다.
이로써 모든 파일에 대한 코드를 분석해보았습니다.
다음 게시글에서는 서버에서 실행환경을 구축하여 실제로 동작을 하는지를 확인하도록 하겠습니다.
읽어주셔서 감사합니다.
'0x30 Study > 0x32 Blockchain' 카테고리의 다른 글
g-coin 분석(2) (33) | 2018.03.05 |
---|---|
g-coin 분석(0) (0) | 2018.03.01 |
BlockChain을 공부하자! (0) (62) | 2018.02.28 |