def add_transaction(self, sender_blockchain_address, recipient_blockchain_address, value, sender_public_key=None, signature=None): transaction = utils.sorted_dict_by_key({ 'sender_blockchain_address': sender_blockchain_address, 'recipient_blockchain_address': recipient_blockchain_address, 'value': float(value) }) if sender_blockchain_address == MINING_SENDER: self.transaction_pool.append(transaction) return True if self.verify_transaction_signature(sender_public_key, signature, transaction): if (self.calculate_total_amount(sender_blockchain_address) < float(value)): logger.error({ 'action': 'add_transaction', 'error': 'no_value' }) return False self.transaction_pool.append(transaction) return True return False
def valid_proof(self, transactions, previous_hash, nonce): guess_block = utils.sorted_dict_by_key({ 'transactions': transactions, 'nonce': nonce, 'previous_hash': previous_hash }) guess_hash = self.hash(guess_block) return guess_hash[:self.difficulty] == '0'*self.difficulty
def add_transaction(self, sender_blockchain_address, recipient_blockchain_address, value, sender_public_key=None, signature=None): """ transactionを追加する. ex. wallet A -> wallet B に 1.0送金. Parameters ---------- sender_blockchain_address: str wallet Aのblockchain address recipient_blockchain_address: str wallet Bのblockchain address value: float 1.0 sender_public_key: str signature : str Returns ------- bool See Also -------- """ transaction = utils.sorted_dict_by_key({ "sender_blockchain_address": sender_blockchain_address, "recipient_blockchain_address": recipient_blockchain_address, "value": float(value) }) # miningの場合 if sender_blockchain_address == MINING_SENDER: self.transaction_pool.append(transaction) return True # mining以外の場合 if self.verify_transaction_signature(sender_public_key, signature, transaction): # 送り金がない場合 if self.calculate_total_amount(sender_blockchain_address) < float( value): logger.error({ 'action': 'add_transaction', 'error': 'no_value' }) return False self.transaction_pool.append(transaction) return True return False
def add_transaction(self, sender_blockchain_address, recipient_blockchain_address, value): transaction = utils.sorted_dict_by_key({ 'sender_blockchain_address': sender_blockchain_address, 'recipient_blockchain_address': recipient_blockchain_address, 'value': float(value) }) self.transaction_pool.append(transaction) return True
def valid_proof(self, transactions, previous_hash, nonce, dificulty=MINING_DIFFICULTY): guess_block = utils.sorted_dict_by_key({ 'transactions': transactions, 'nonce': nonce, 'previous_hash': previous_hash }) guess_hash = self.hash(guess_block) return guess_hash[:dificulty] == '0'*dificulty
def create_block(self, nonce, previous_hash): block = utils.sorted_dict_by_key({ 'timestamp': time.time(), 'transactions': self.transaction_pool, 'nonce': nonce, 'previous_hash': previous_hash }) self.chain.append(block) self.transaction_pool = [] return block
def create_genesis_block(self): print('create_genesis_block is called') block = utils.sorted_dict_by_key({ 'timestamp': time.time(), 'transactions' : self.transaction_pool, 'nonce': 0, 'previous_hash': self.hash({}) }) self.chain.append(block) self.transaction_pool = []
def create_block(self, nonce, previous_hash): block = utils.sorted_dict_by_key({ 'timestamp': time.time(), 'transactions': self.transaction_pool, 'nonce': nonce, 'previous_hash': previous_hash }) self.chain.append(block) self.transaction_pool = [] for node in self.neighbours: requests.delete(f'http://{node}/transactions') return block
def valid_proof(self, transactions, previous_hash, nonce, difficulty=MINING_DIFFICULTY): # ブロックをつくって guess_block = utils.sorted_dict_by_key({ 'transactions': transactions, 'previous_hash': previous_hash, 'nonce': nonce }) # ハッシュを作って guess_hash = self.hash(guess_block) # 判定をする return guess_hash[:difficulty] == '0'*difficulty
def generate_signature(self): sha256 = hashlib.sha256() transactions = utils.sorted_dict_by_key({ 'sender_blockchain_address': self.sender_blockchain_address, 'recipient_blockchain_address': self.recipient_blockchain_address, 'value': float(self.value) }) sha256.update(str(transactions).encode('utf-8')) message = sha256.digest() private_key = SigningKey.from_string( bytes().fromhex(self.sender_private_key), curve=NIST256p) private_key_sign = private_key.sign(message) signature = private_key_sign.hex() return signature
def verify_transaction_signature(self, transaction, sender_public_key, signature): sha256 = hashlib.sha256() sha256.update( str(utils.sorted_dict_by_key(transaction)).encode('utf-8')) message = sha256.digest() verifying_key = VerifyingKey.from_string( bytes().fromhex(sender_public_key), curve=NIST256p) signature_bytes = bytes().fromhex(signature) try: verified_key = verifying_key.verify(signature_bytes, message) # return verified_key return True except BadSignatureError: return False
def valid_proof(self, transactions, prev_hash, nonce, difficulty=MINING_DIFICALITY): """ nonceの計算を行う """ # ハッシュ値の計算を行うブロックを定義しておく guess_block = utils.sorted_dict_by_key({ 'transactions': transactions, 'nonce': nonce, 'previous_hash': prev_hash, }) # ハッシュ値の計算を行う guess_hash = self.hash(guess_block) # マイニングディフィカリティに応じたルールで判断する return guess_hash[:difficulty] == '0' * difficulty
def add_transaction(self, sender_blockchain_address, recipient_blockchain_address, value): """ 新しいトランザクションを作成し、トランザクションプールに追加する valueは金額を扱うので、floatでキャストする """ # トランザクションを作成 transaction = utils.sorted_dict_by_key({ 'sender_blockchain_address': sender_blockchain_address, 'recipient_blockchain_address': recipient_blockchain_address, 'value': float(value), }) # トランザクションプールに追加する self.transaction_pool.append(transaction) # 追加に成功したらTrue return True
def create_block(self, nonce, previous_hash): print('create_block is called') block = utils.sorted_dict_by_key({ 'timestamp': time.time(), 'difficulty': self.difficulty, 'transactions': self.transaction_pool, 'nonce': nonce, 'previous_hash': previous_hash }) if not self.valid_proof(block['transactions'],block['previous_hash'], block['nonce'],block['difficulty']): return False, None self.chain.append(block) self.transaction_pool = [] return True, block
def create_block(self, nonce, previous_hash): """ Blockを作成する Parameters ---------- nonce: int previous_hash: str Returns ------- block : dict See Also -------- >>> block_chain = BlockChain() >>> block_1 = block_chain.create_block(5, "hash 1") >>> block_1['nonce'] 5 >>> block_1['previous_hash'] 'hash 1' >>> block_2 = block_chain.create_block(2, "hash 2") >>> block_2['nonce'] 2 >>> block_2['previous_hash'] 'hash 2' """ block = utils.sorted_dict_by_key({ "timestamp": time.time(), "transactions": self.transaction_pool, "nonce": nonce, "previous_hash": previous_hash }) self.chain.append(block) self.transaction_pool = [] # 同期させる for node in self.neighbours: requests.delete(f"http://{node}/transactions") return block
def generate_signature(self): """ 署名を生成する ex. wallet A -> wallet B に 1.0送金. sender_blockchain_address: wallet Aのblockchain_address recipient_blockchain_address: wallet Bのblockchain_address value: 1.0 秘密鍵とtransactionsからsignatureを生成する 1. transactionsをSHA-256でハッシュ化(bytes) 2. message: ハッシュ化したtransactionsを16進数文字列化 3. NIST256pでprivate_keyを作成(bytes) See Also -------- >>> wallet_A = Wallet() >>> wallet_B = Wallet() >>> t = Transaction(wallet_A.private_key, wallet_A.public_key, wallet_A.blockchain_address, wallet_B.blockchain_address, 1.0) >>> _ = t.generate_signature() """ sha256 = hashlib.sha256() transaction = utils.sorted_dict_by_key({ "sender_blockchain_address": self.sender_blockchain_address, "recipient_blockchain_address": self.recipient_blockchain_address, "value": float(self.value) }) # sha256のupdate sha256.update(str(transaction).encode("utf-8")) # hashのメッセージ message = sha256.digest() # private_keyの作成 private_key = SigningKey.from_string(bytes().fromhex( self.sender_private_key), curve=NIST256p) # signアルゴリズム private_key_sign = private_key.sign(message) signature = private_key_sign.hex() return signature
def generate_signature(self): """ 送金者の秘密鍵でトランザクションに署名 トランザクションをsha256でハッシュ化 PrivateKey.sign(message_hash)でSignatureオブジェクトを作成 署名結果のrとsをタプルで返す """ sha256 = hashlib.sha256() transaction = utils.sorted_dict_by_key({ 'sender_blockchain_address': self.sender_blockchain_address, 'recipient_blockchain_address': self.recipient_blockchain_address, 'value': float(self.value) }) sha256.update(str(transaction).encode('utf-8')) message = sha256.digest() msg_hex = message.hex() msg_hex_str = str(msg_hex) msg_hex_str_0x = '0x' + msg_hex_str priv_int = int('0x'+self.sender_private_key, 0) priv = PrivateKey(priv_int) sig = priv.sign(int(msg_hex_str_0x, 0)) return (sig.r, sig.s)
def add_transaction(self, sender_blockchain_address, recipient_blockchain_address, value, sender_public_key=None, signature=None): # valueは小数点がくるためfloat transaction = utils.sorted_dict_by_key({ 'sender_blockchain_address': sender_blockchain_address, 'recipient_blockchain_address': recipient_blockchain_address, 'value': float(value) }) # マイニング処理の場合 if sender_blockchain_address == MINING_SENDER: self.transaction_pool.append(transaction) return True # signatureをチェック if self.verify_transaction_signature( sender_public_key, signature, transaction): self.transaction_pool.append(transaction) return True return False
def valid_proof(self, transactions, previous_hash, nonce, difficulty=MINING_DIFFICULTY): """ nonceを計算する. Parameters ---------- transactions: list of dicts [{"recipient_blockchain_address": str, "sender_blockchain_address": str, "value": float}] previous_hash: str hash化([{"nonce": int, "previous_hash": str, "timestamp": float, "transactions": list}]) nonce: int サーチ対象 difficulty: int miningの難易度.hash化した文字列の先頭"0"の連続数 Returns ------- bool See Also -------- """ guess_block = utils.sorted_dict_by_key({ "transactions": transactions, "nonce": nonce, "previous_hash": previous_hash }) guess_hash = self.hash(guess_block) return guess_hash[:difficulty] == "0" * difficulty
def create_block(self, nonce, previous_hash): """ブロックチェーンを作成する関数 作成したブロックをブロックチェーンのリストに追加し、 トランザクションプールを空にする """ # ブロックを作成 block = { 'timestamp': time.time(), 'transactions': self.transaction_pool, 'nonce': nonce, 'previous_hash': previous_hash, } # ブロックをソートする ハッシュ化したときに毎回同じハッシュ値になるように sorted_block = utils.sorted_dict_by_key(block) # ブロックを追加 self.chain.append(sorted_block) # トランザクションプールを空にする self.transaction_pool = [] return sorted_block
def __handle_message(self, msg, is_core, peer=None): """ ConnectionManagerに引き渡すコールバックの中身。 """ print('message_type : ', msg[2]) if peer is not None: if msg[2] == MSG_REQUEST_FULL_CHAIN: # walletのチェーンを同期 print('Send our latest blockchain for reply to : ', peer) my_chain = self.blockchain.chain chain_data = json.dumps(my_chain) new_message = self.cm.get_message_text(RSP_FULL_CHAIN, chain_data) self.cm.send_msg(peer, new_message) elif msg[2] == MSG_REQUEST_KEY_INFO: # walletにminerの鍵情報を渡す key_info = pickle.dumps(self.miners_wallet, 0).decode() m_type = MSG_KEY_INFO message = self.cm.get_message_text(m_type, key_info) self.cm.send_msg(peer, message) elif msg[2] == MSG_DELETE_TRANSACTION: # transaction poolを空に print('DELETE_TRANSACTION is called') self.blockchain.transaction_pool = [] else: if msg[2] == MSG_NEW_TRANSACTION: print('NEW_TRANSACTION command is called') payload = json.loads(msg[4]) new_transaction = utils.sorted_dict_by_key({ 'sender_blockchain_address': payload['sender_blockchain_address'], 'recipient_blockchain_address': payload['recipient_blockchain_address'], 'value': float(payload['value']) }) current_transactions = self.blockchain.transaction_pool.copy() print('new transaction : ', new_transaction) if new_transaction in current_transactions: print('transaction is already in pool') return else: signature = pickle.loads( payload['signature'].encode('utf8')) print('signature', signature) is_transacted = self.blockchain.add_transaction( payload['sender_blockchain_address'], payload['recipient_blockchain_address'], payload['value'], payload['sender_public_key'], signature) if is_transacted: print('new transaction is generated') print('\n\ntransaction_pool', self.blockchain.transaction_pool) if not is_core: # ウォレットからのトランザクションはブロードキャスト print('transaction bloadcasted') m_type = MSG_NEW_TRANSACTION new_message = self.cm.get_message_text(m_type, msg[4]) self.cm.send_msg_to_all_peer(new_message) elif msg[2] == RSP_FULL_CHAIN: print('RSP_FULL_CHAIN command is called') if not is_core: return new_block_chain = json.loads(msg[4]) self.blockchain.resolve_conflicts(new_block_chain)