|
|
@@ -1,26 +1,28 @@
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
+
|
|
|
import random
|
|
|
-from .ecc import VerifyingKey,build_message,convert_pubkey_to_addr
|
|
|
-from .datatype import Pointer,Vin,Vout,UTXO,Tx,Block,get_merkle_root_of_txs
|
|
|
-from .params import Params
|
|
|
-from .consensus import mine,caculate_target
|
|
|
-from .logger import logger
|
|
|
-from .wallet import Wallet
|
|
|
-from .vm import LittleMachine
|
|
|
-from .merkletree import MerkleTree
|
|
|
+from ecc import VerifyingKey, build_message, convert_pubkey_to_addr
|
|
|
+from datatype import Pointer, Vin, Vout, UTXO, Tx, Block, get_merkle_root_of_txs
|
|
|
+from params import Params
|
|
|
+from consensus import mine, caculate_target
|
|
|
+from logger import logger
|
|
|
+from wallet import Wallet
|
|
|
+from vm import LittleMachine
|
|
|
+#from merkletree import MerkleTree
|
|
|
+
|
|
|
|
|
|
class Peer(object):
|
|
|
-
|
|
|
- def __init__(self,coords = None):
|
|
|
+
|
|
|
+ def __init__(self, coords=None):
|
|
|
self.coords = coords
|
|
|
self.network = None
|
|
|
- self.txs = []
|
|
|
+ self.txs = [] # 该节点创建的交易
|
|
|
self.candidate_block_txs = []
|
|
|
self.candidate_block = None
|
|
|
self.blockchain = []
|
|
|
self.orphan_block = []
|
|
|
- self.utxo_set = {}
|
|
|
+ self.utxo_set = {} # 未消费的交易的集合
|
|
|
self.mem_pool = {}
|
|
|
self.orphan_pool = {}
|
|
|
self.pid = None
|
|
|
@@ -31,7 +33,7 @@ class Peer(object):
|
|
|
self.machine = LittleMachine()
|
|
|
self._is_wallet_generated = False
|
|
|
self.generate_wallet()
|
|
|
-
|
|
|
+
|
|
|
self._is_block_candidate_created = False
|
|
|
self._is_current_tx_created = False
|
|
|
self._is_current_tx_sent = False
|
|
|
@@ -41,23 +43,20 @@ class Peer(object):
|
|
|
self._pointers_from_vouts = None
|
|
|
self._utxos_from_vouts = None
|
|
|
self._txs_removed = None
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
############################################################
|
|
|
# peer as wallet
|
|
|
############################################################
|
|
|
"""
|
|
|
Generate wallet
|
|
|
"""
|
|
|
-
|
|
|
+
|
|
|
def generate_wallet(self):
|
|
|
- if not self._is_wallet_generated:
|
|
|
+ # 因为认为这个布尔值没有意义,所以我取消了
|
|
|
+ # 其他方法可以统一这样写
|
|
|
+ if not hasattr(self, 'wallet'): # not self._is_wallet_generated:
|
|
|
self.wallet = Wallet()
|
|
|
- self._is_wallet_generated = True
|
|
|
-
|
|
|
+ # self._is_wallet_generated = True
|
|
|
|
|
|
@property
|
|
|
def sk(self):
|
|
|
@@ -67,442 +66,500 @@ class Peer(object):
|
|
|
def pk(self):
|
|
|
return self.wallet.keys[-1].pk.to_bytes() if self.wallet.keys else None
|
|
|
|
|
|
-
|
|
|
@property
|
|
|
def addr(self):
|
|
|
return self.wallet.addrs[-1] if self.wallet.addrs else None
|
|
|
|
|
|
+ """
|
|
|
+ 获得私钥的长度
|
|
|
+ """
|
|
|
+
|
|
|
@property
|
|
|
def key_base_len(self):
|
|
|
return len(self.sk)
|
|
|
-
|
|
|
+
|
|
|
"""
|
|
|
your bank balance
|
|
|
"""
|
|
|
+
|
|
|
def get_balance(self):
|
|
|
- utxos = self.get_utxo()
|
|
|
+ utxos = self.get_utxos()
|
|
|
return sum(utxo.vout.value for utxo in utxos)
|
|
|
-
|
|
|
+
|
|
|
"""
|
|
|
your output
|
|
|
"""
|
|
|
-
|
|
|
- def get_utxo(self):
|
|
|
+
|
|
|
+ # 修改名字为UTXO
|
|
|
+ def get_utxos(self):
|
|
|
+ # 遍历set, 获得所有有效的节点(输出节点为当前节点的钱包中地址的一个)&& 未消费
|
|
|
return [utxo for utxo in self.utxo_set.values()
|
|
|
if (utxo.vout.to_addr in self.wallet.addrs) and utxo.unspent]
|
|
|
-
|
|
|
- def get_unconfirmed_utxo(self):
|
|
|
- utxos = self.get_utxo()
|
|
|
- return [utxo for utxo in utxos if not utxo.confirmed]
|
|
|
-
|
|
|
- def get_confirmed_utxo(self):
|
|
|
- utxos = self.get_utxo()
|
|
|
- return [utxo for utxo in utxos if utxo.confirmed]
|
|
|
-
|
|
|
- def set_fee(self,value):
|
|
|
- self.fee = value
|
|
|
-
|
|
|
- def get_fee(self):
|
|
|
- return self.fee
|
|
|
|
|
|
- def calculate_fees(self,txs=[]):
|
|
|
+ # """
|
|
|
+ # 获取未确定的未消费的交易
|
|
|
+ # """
|
|
|
+ # def get_unconfirmed_utxo(self):
|
|
|
+ # utxos = self.get_utxos()
|
|
|
+ # return [utxo for utxo in utxos if not utxo.confirmed]
|
|
|
+ #
|
|
|
+ # """
|
|
|
+ # 获取确定的未消费的交易
|
|
|
+ # """
|
|
|
+ # def get_confirmed_utxo(self):
|
|
|
+ # utxos = self.get_utxos()
|
|
|
+ # return [utxo for utxo in utxos if utxo.confirmed]
|
|
|
+ #
|
|
|
+
|
|
|
+ # def set_fee(self,value):
|
|
|
+ # self.fee = value
|
|
|
+ #
|
|
|
+ # def get_fee(self):
|
|
|
+ # return self.fee
|
|
|
+
|
|
|
+ def calculate_fees(self, txs=[]):
|
|
|
return sum(tx.fee for tx in txs)
|
|
|
|
|
|
-
|
|
|
def get_block_reward(self):
|
|
|
return Params.FIX_BLOCK_REWARD
|
|
|
|
|
|
-
|
|
|
"""
|
|
|
create a transaction
|
|
|
"""
|
|
|
- def create_transaction(self,to_addr,
|
|
|
+
|
|
|
+ def create_transaction(self, to_addr,
|
|
|
value,
|
|
|
- tx_type = "normal"):
|
|
|
-
|
|
|
+ tx_type="normal"):
|
|
|
+
|
|
|
if tx_type == 'normal':
|
|
|
- outputs = create_normal_tx(self,to_addr,value)
|
|
|
+ outputs = create_normal_tx(self, to_addr, value)
|
|
|
if outputs:
|
|
|
- tx_in,tx_out,fee = outputs
|
|
|
- self.current_tx = Tx(tx_in,tx_out,fee = fee,nlocktime = 0)
|
|
|
- self.txs.append(self.current_tx)
|
|
|
+ tx_in, tx_out, fee = outputs
|
|
|
+ self.current_tx = Tx(tx_in, tx_out, fee=fee, nlocktime=0)
|
|
|
+ self.txs.append(self.current_tx)
|
|
|
self._is_current_tx_created = True
|
|
|
-
|
|
|
- logger.info('{0}(pid={1}) created a transaction'.format(self,self.pid))
|
|
|
+ logger.info('{0}(pid={1}) created a transaction'.format(self, self.pid))
|
|
|
return True
|
|
|
return False
|
|
|
-
|
|
|
|
|
|
"""
|
|
|
if this is a recorder peer, build rewards for self after won
|
|
|
+ 创世块发送的比特币的交易
|
|
|
"""
|
|
|
- def create_coinbase(self,value):
|
|
|
- return Tx.create_coinbase(self.wallet.addrs[-1],value = value)
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+ def create_coinbase(self, value):
|
|
|
+ return Tx.create_coinbase(self.wallet.addrs[-1], value=value)
|
|
|
+
|
|
|
############################################################
|
|
|
# peer as route
|
|
|
############################################################
|
|
|
"""
|
|
|
broadcast a transaction
|
|
|
"""
|
|
|
- def send_transaction(self):
|
|
|
+
|
|
|
+ def __send_transaction__(self):
|
|
|
+ # 如果txs 为None
|
|
|
if not self.txs:
|
|
|
return False
|
|
|
-
|
|
|
+
|
|
|
if self._is_current_tx_created:
|
|
|
- sign_utxo_from_tx(self.utxo_set,self.current_tx)
|
|
|
-
|
|
|
- add_tx_to_mem_pool(self,self.current_tx)
|
|
|
- self._is_current_tx_created = False
|
|
|
+ # 将tx 对应的utxo标记为spent
|
|
|
+ sign_utxo_from_tx(self.utxo_set, self.current_tx)
|
|
|
+ add_tx_to_mem_pool(self, self.current_tx)
|
|
|
self._is_current_tx_sent = True
|
|
|
-
|
|
|
- logger.info("{0}(pid={1}) sent a transaction to network".format(self,self.pid))
|
|
|
+ self._is_current_tx_created = False
|
|
|
+ logger.info("{0}(pid={1}) sent a transaction to network".format(self, self.pid))
|
|
|
return True
|
|
|
return False
|
|
|
-
|
|
|
-
|
|
|
- def recieve_transaction(self,tx):
|
|
|
- if tx and (tx not in self.mem_pool):
|
|
|
- if self.verify_transaction(tx,self.mem_pool):
|
|
|
- add_tx_to_mem_pool(self,tx)
|
|
|
- return True
|
|
|
-
|
|
|
- return False
|
|
|
|
|
|
-
|
|
|
- def broadcast_transaction(self,tx = None):
|
|
|
+ # #XGY: No Usage
|
|
|
+ # def recieve_transaction(self,tx):
|
|
|
+ # if tx and (tx not in self.mem_pool):
|
|
|
+ # if self.verify_transaction(tx,self.mem_pool):
|
|
|
+ # add_tx_to_mem_pool(self,tx)
|
|
|
+ # return True
|
|
|
+ #
|
|
|
+ # return False
|
|
|
+
|
|
|
+ def broadcast_transaction(self, tx=None):
|
|
|
if not self._is_current_tx_sent:
|
|
|
- self.send_transaction()
|
|
|
-
|
|
|
+ self.__send_transaction__()
|
|
|
+
|
|
|
self._is_current_tx_created = False
|
|
|
self._is_current_tx_sent = False
|
|
|
-
|
|
|
+
|
|
|
tx = tx or self.current_tx
|
|
|
if tx:
|
|
|
peers = self.network.peers[:]
|
|
|
peers.remove(self)
|
|
|
- number = broadcast_tx(peers,tx)
|
|
|
+ number = broadcast_tx(peers, tx)
|
|
|
self.current_tx = None
|
|
|
-
|
|
|
- logger.info("{0}(pid={1})'s transaction verified by {2} peers".format(self,self.pid,number))
|
|
|
+
|
|
|
+ logger.info("{0}(pid={1})'s transaction verified by {2} peers".format(self, self.pid, number))
|
|
|
return number
|
|
|
return 0
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
"""
|
|
|
broadcast a transaction
|
|
|
- """
|
|
|
- def broadcast_block(self,block):
|
|
|
+ """
|
|
|
+
|
|
|
+ def broadcast_block(self, block):
|
|
|
peers = self.network.peers[:]
|
|
|
peers.remove(self)
|
|
|
- number = broadcast_winner_block(peers,block)
|
|
|
- logger.info('{0} received by {1} peers'.format(block,number))
|
|
|
-
|
|
|
-
|
|
|
- def locate_block(self,block_hash):
|
|
|
- return locate_block_by_hash(self,block_hash)
|
|
|
-
|
|
|
-
|
|
|
- def recieve_block(self,block):
|
|
|
- if not self.verify_block(block):
|
|
|
- return False
|
|
|
- return try_to_add_block(self,block)
|
|
|
-
|
|
|
-
|
|
|
+ # 广播胜利的节点
|
|
|
+ number = broadcast_winner_block(peers, block)
|
|
|
+ logger.info('{0} received by {1} peers'.format(block, number))
|
|
|
+
|
|
|
+ # #XGY: No Usage
|
|
|
+ # def locate_block(self,block_hash):
|
|
|
+ # return locate_block_by_hash(self,block_hash)
|
|
|
+ #
|
|
|
+
|
|
|
+ def recieve_block(self, block):
|
|
|
+ # 验证该节点是否有效,如果有效,则尝试添加节点
|
|
|
+ if self.verify_block(block):
|
|
|
+ return try_to_add_block(self, block)
|
|
|
+ return False
|
|
|
+
|
|
|
"""
|
|
|
verify a transaction
|
|
|
"""
|
|
|
-
|
|
|
- def verify_transaction(self,tx,pool = {}):
|
|
|
- if tx in self.txs:
|
|
|
+
|
|
|
+ def verify_transaction(self, tx, pool={}):
|
|
|
+ if tx not in self.txs:
|
|
|
+ return verify_tx(self, tx, pool)
|
|
|
+ # 如果tx已经在自己的节点里,则不需要验证,直接返回true
|
|
|
+ else:
|
|
|
return True
|
|
|
- return verify_tx(self,tx,pool)
|
|
|
|
|
|
"""
|
|
|
verify a block
|
|
|
- """
|
|
|
-
|
|
|
- def verify_block(self,block):
|
|
|
+ """
|
|
|
+
|
|
|
+ def verify_block(self, block):
|
|
|
+ # 没有值,是None
|
|
|
if self._delayed_tx:
|
|
|
fill_mem_pool(self)
|
|
|
-
|
|
|
+
|
|
|
+ # 没有值,是None
|
|
|
if self.orphan_pool:
|
|
|
check_orphan_tx_from_pool(self)
|
|
|
-
|
|
|
+ # 也是None
|
|
|
if block == self.candidate_block:
|
|
|
return True
|
|
|
-
|
|
|
- if not verify_winner_block(self,block):
|
|
|
+
|
|
|
+ if not verify_winner_block(self, block):
|
|
|
return False
|
|
|
|
|
|
return True
|
|
|
-
|
|
|
- def response_path(self,tx):
|
|
|
- if tx.id in self.mem_pool:
|
|
|
- return "unconfirmed"
|
|
|
-
|
|
|
- tot_height = self.get_height()
|
|
|
- for i in range(tot_height):
|
|
|
- txs = self.blockchain[-i-1].txs
|
|
|
- if tx in txs:
|
|
|
- break
|
|
|
- else:
|
|
|
- return False
|
|
|
-
|
|
|
- height = tot_height - i
|
|
|
- idx = txs.index(tx)
|
|
|
- idxs = [tx.id for tx in txs]
|
|
|
- merkle = MerkleTree(idxs)
|
|
|
- path = merkle.get_path(idx)
|
|
|
- return height,path
|
|
|
-
|
|
|
|
|
|
-
|
|
|
+ # XGY: No Usage
|
|
|
+ # def response_path(self,tx):
|
|
|
+ # if tx.id in self.mem_pool:
|
|
|
+ # return "unconfirmed"
|
|
|
+ #
|
|
|
+ # tot_height = self.get_height()
|
|
|
+ # for i in range(tot_height):
|
|
|
+ # txs = self.blockchain[-i-1].txs
|
|
|
+ # if tx in txs:
|
|
|
+ # break
|
|
|
+ # else:
|
|
|
+ # return False
|
|
|
+ #
|
|
|
+ # height = tot_height - i
|
|
|
+ # idx = txs.index(tx)
|
|
|
+ # idxs = [tx.id for tx in txs]
|
|
|
+ # merkle = MerkleTree(idxs)
|
|
|
+ # path = merkle.get_path(idx)
|
|
|
+ # return height,path
|
|
|
+ #
|
|
|
+
|
|
|
"""
|
|
|
peer links to p2p network
|
|
|
"""
|
|
|
-
|
|
|
- def login(self):
|
|
|
- assert self in self.network.off_peers,(
|
|
|
- "This peer does not connect to network or online"
|
|
|
- )
|
|
|
- repeat_log_in(self,self.network)
|
|
|
- self.update_blockchain()
|
|
|
-
|
|
|
-
|
|
|
+ # XGY: No Usage
|
|
|
+ # def login(self):
|
|
|
+ # assert self in self.network.off_peers,(
|
|
|
+ # "This peer does not connect to network or online"
|
|
|
+ # )
|
|
|
+ # repeat_log_in(self,self.network)
|
|
|
+ # self.update_blockchain()
|
|
|
+ #
|
|
|
+
|
|
|
"""
|
|
|
peer logs out
|
|
|
"""
|
|
|
- def logout(self):
|
|
|
- assert self in self.network.peers,(
|
|
|
- "This peer does not connect to network"
|
|
|
- )
|
|
|
- log_out(self,self.network)
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- def update_blockchain(self,other):
|
|
|
- return update_chain(self,other)
|
|
|
-
|
|
|
-
|
|
|
- def update_mem_pool(self,other):
|
|
|
+ # XGY: No Usage
|
|
|
+ # def logout(self):
|
|
|
+ # assert self in self.network.peers,(
|
|
|
+ # "This peer does not connect to network"
|
|
|
+ # )
|
|
|
+ # log_out(self,self.network)
|
|
|
+ #
|
|
|
+
|
|
|
+ """
|
|
|
+ 下面是更新的方法
|
|
|
+ """
|
|
|
+
|
|
|
+ def update_blockchain(self, other):
|
|
|
+ return update_chain(self, other)
|
|
|
+
|
|
|
+ def update_mem_pool(self, other):
|
|
|
if other._delayed_tx:
|
|
|
fill_mem_pool(other)
|
|
|
- return update_pool(self,other.mem_pool)
|
|
|
-
|
|
|
+ return update_pool(self, other.mem_pool)
|
|
|
|
|
|
- def update_utxo_set(self,other):
|
|
|
+ def update_utxo_set(self, other):
|
|
|
self.utxo_set.update(other.utxo_set)
|
|
|
-
|
|
|
+
|
|
|
############################################################
|
|
|
# peer as recorder
|
|
|
############################################################
|
|
|
-
|
|
|
+
|
|
|
"""
|
|
|
if u r a consensus peer, u have create a candidate block
|
|
|
"""
|
|
|
-
|
|
|
+
|
|
|
def create_candidate_block(self):
|
|
|
- self.choose_tx_candidates()
|
|
|
+ # 设置candidate_block_txs
|
|
|
+ self.candidate_block_txs = self.choose_tx_candidates()
|
|
|
txs = self.candidate_block_txs
|
|
|
value = self.get_block_reward() + self.calculate_fees(txs)
|
|
|
+ # 挖矿成功之后,从创世块获得value
|
|
|
coinbase = self.create_coinbase(value)
|
|
|
- txs = [coinbase]+txs
|
|
|
-
|
|
|
+ txs = [coinbase] + txs
|
|
|
+
|
|
|
prev_block_hash = self.blockchain[-1].hash
|
|
|
- bits = Params.INITIAL_DIFFICULTY_BITS
|
|
|
- self.candidate_block = Block(version=0,
|
|
|
+ # 挖矿难度
|
|
|
+ bits = Params.INITIAL_DIFFICULTY_BITS
|
|
|
+ self.candidate_block = Block(version=0,
|
|
|
prev_block_hash=prev_block_hash,
|
|
|
- timestamp = self.network.time[-1],
|
|
|
- bits = bits,
|
|
|
- nonce = 0,
|
|
|
- txs = txs or [])
|
|
|
-
|
|
|
+ timestamp=self.network.time[-1],
|
|
|
+ bits=bits,
|
|
|
+ nonce=0,
|
|
|
+ txs=txs or [])
|
|
|
+
|
|
|
self._is_block_candidate_created = True
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
'''
|
|
|
pow used right now
|
|
|
- '''
|
|
|
- def consensus(self,meth = 'pow'):
|
|
|
+ '''
|
|
|
+
|
|
|
+ def consensus(self, meth='pow'):
|
|
|
+ # 如果候选块没有被创建
|
|
|
if not self._is_block_candidate_created:
|
|
|
+ # 调用创建方法
|
|
|
self.create_candidate_block()
|
|
|
- self._is_block_candidate_created = False
|
|
|
-
|
|
|
+ self._is_block_candidate_created = False # 这个很奇怪
|
|
|
+
|
|
|
if meth == 'pow':
|
|
|
return mine(self.candidate_block)
|
|
|
|
|
|
"""
|
|
|
if this is a recorder peer, we have package the candidate block
|
|
|
"""
|
|
|
- def package_block(self,nonce):
|
|
|
- block = self.candidate_block._replace(nonce = nonce)
|
|
|
+ """
|
|
|
+ 包装区块
|
|
|
+ """
|
|
|
+
|
|
|
+ def package_block(self, nonce):
|
|
|
+ block = self.candidate_block._replace(nonce=nonce)
|
|
|
return block
|
|
|
|
|
|
"""
|
|
|
choose transactions for candidate block
|
|
|
"""
|
|
|
+
|
|
|
def choose_tx_candidates(self):
|
|
|
if self.tx_choice_method == 'whole':
|
|
|
+ # 如果当前内存池为None, 则新建一个
|
|
|
if not self.mem_pool:
|
|
|
self.update_mem_pool(self.network.peers[0])
|
|
|
- self.candidate_block_txs = choose_whole_txs_from_pool(self.mem_pool)
|
|
|
-
|
|
|
+ return choose_whole_txs_from_pool(self.mem_pool)
|
|
|
+ # self.candidate_block_txs = choose_whole_txs_from_pool(self.mem_pool)
|
|
|
+
|
|
|
elif self.tx_choice_method == 'random':
|
|
|
if not self.mem_pool:
|
|
|
self.update_mem_pool(self.network.peers[0])
|
|
|
- self.candidate_block_txs = choose_raondom_txs_from_pool(self.mem_pool)
|
|
|
+ return choose_raondom_txs_from_pool(self.mem_pool)
|
|
|
+ # self.candidate_block_txs = choose_raondom_txs_from_pool(self.mem_pool)
|
|
|
|
|
|
"""
|
|
|
get transactions for candidate block
|
|
|
"""
|
|
|
- def get_tx_candidates(self):
|
|
|
- return self.candidate_block_txs
|
|
|
-
|
|
|
+
|
|
|
+ # XGY: No Usage
|
|
|
+ # def get_tx_candidates(self):
|
|
|
+ # return self.candidate_block_txs
|
|
|
+ #
|
|
|
+
|
|
|
def get_height(self):
|
|
|
return len(self.blockchain)
|
|
|
-
|
|
|
- def roll_back_now(self):
|
|
|
- roll_back(self)
|
|
|
+
|
|
|
+ # XGY: No Usage
|
|
|
+ # def roll_back_now(self):
|
|
|
+ # roll_back(self)
|
|
|
|
|
|
def __repr__(self):
|
|
|
- return 'peer{0}'.format(self.coords)
|
|
|
-
|
|
|
-
|
|
|
-# =============================================================================
|
|
|
-#login and logout
|
|
|
+ return 'peer<{0}>'.format(self.coords)
|
|
|
|
|
|
-def repeat_log_in(peer,net):
|
|
|
- net.off_peers.remove(peer)
|
|
|
- net.peers.append(peer)
|
|
|
-
|
|
|
-def log_out(peer,net):
|
|
|
- net.peers.remove(peer)
|
|
|
- net.off_peers.append(peer)
|
|
|
- peer.mem_pool = []
|
|
|
|
|
|
-def update_chain(peer,other):
|
|
|
+# =============================================================================
|
|
|
+# login and logout
|
|
|
+#
|
|
|
+# def repeat_log_in(peer,net):
|
|
|
+# net.off_peers.remove(peer)
|
|
|
+# net.peers.append(peer)
|
|
|
+#
|
|
|
+# def log_out(peer,net):
|
|
|
+# net.peers.remove(peer)
|
|
|
+# net.off_peers.append(peer)
|
|
|
+# peer.mem_pool = []
|
|
|
+
|
|
|
+def update_chain(peer, other):
|
|
|
other_height = other.get_height()
|
|
|
height = peer.get_height()
|
|
|
+ # 如果其他区块的长度大于当前的区块,则将peer的blockchain替换为other
|
|
|
if other_height > height:
|
|
|
peer.blockchain = []
|
|
|
for block in other.blockchain:
|
|
|
peer.blockchain.append(block)
|
|
|
return True
|
|
|
return False
|
|
|
-
|
|
|
|
|
|
-def update_pool(peer,pool):
|
|
|
- a,b = set(peer.mem_pool),set(pool)
|
|
|
- for tx_id in (b-a):
|
|
|
+
|
|
|
+"""
|
|
|
+更新pool
|
|
|
+"""
|
|
|
+
|
|
|
+
|
|
|
+def update_pool(peer, pool):
|
|
|
+ a, b = set(peer.mem_pool), set(pool)
|
|
|
+ for tx_id in (b - a):
|
|
|
tx = pool.get(tx_id)
|
|
|
peer.mem_pool[tx_id] = tx
|
|
|
-
|
|
|
+
|
|
|
if peer._delayed_tx:
|
|
|
fill_mem_pool(peer)
|
|
|
-
|
|
|
+
|
|
|
if peer.orphan_pool:
|
|
|
check_orphan_tx_from_pool(peer)
|
|
|
-
|
|
|
+
|
|
|
return True
|
|
|
|
|
|
-
|
|
|
|
|
|
-# =============================================================================
|
|
|
-#create transactions
|
|
|
-def create_normal_tx(peer,to_addr,value) :
|
|
|
- utxos,balance = peer.get_utxo(),peer.get_balance()
|
|
|
- fee,wallet = peer.fee,peer.wallet
|
|
|
-
|
|
|
- tx_in,tx_out = [],[]
|
|
|
+# =============================================================================
|
|
|
+# create transactions
|
|
|
+"""
|
|
|
+创建一个vin为当前节点中地址,指向一个其他地址的的交易
|
|
|
+"""
|
|
|
+
|
|
|
+
|
|
|
+def create_normal_tx(peer, to_addr, value):
|
|
|
+ utxos, balance = peer.get_utxos(), peer.get_balance()
|
|
|
+ fee, wallet = peer.fee, peer.wallet
|
|
|
+ tx_in, tx_out = [], []
|
|
|
value = value + fee
|
|
|
- if balance < value:
|
|
|
- logger.info('no enough money for transaction for {0}(pid = {1})'.format(peer,peer.pid))
|
|
|
+ # 当前余额小于发送的value,则不能发送
|
|
|
+ if balance < value:
|
|
|
+ logger.info('no enough money for transaction for {0}(pid = {1})'.format(peer, peer.pid))
|
|
|
return
|
|
|
-
|
|
|
- need_to_spend,n = 0,0
|
|
|
- for i,utxo in enumerate(utxos):
|
|
|
- need_to_spend += utxo.vout.value
|
|
|
- if need_to_spend >= value:
|
|
|
- n = i+1
|
|
|
+
|
|
|
+ sum, n = 0, 0
|
|
|
+ # 找到满足条件的value
|
|
|
+ # enumrate()将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列
|
|
|
+ for index, utxo in enumerate(utxos):
|
|
|
+ sum += utxo.vout.value
|
|
|
+ if sum >= value:
|
|
|
+ n = index + 1
|
|
|
break
|
|
|
-
|
|
|
- if need_to_spend > value:
|
|
|
+ # 如果总计大于value
|
|
|
+ if sum > value:
|
|
|
my_addr = wallet.addrs[-1]
|
|
|
- tx_out +=[Vout(to_addr,value-fee),Vout(my_addr,need_to_spend-value)]
|
|
|
+ tx_out += [Vout(to_addr, value - fee), Vout(my_addr, sum - value)]
|
|
|
+ # 否则一定是相等
|
|
|
else:
|
|
|
- tx_out += [Vout(to_addr,value-fee)]
|
|
|
-
|
|
|
-
|
|
|
+ tx_out += [Vout(to_addr, value - fee)]
|
|
|
+
|
|
|
+ # 将刚刚交易的utxo都封装为[vin]
|
|
|
for utxo in utxos[:n]:
|
|
|
addr = utxo.vout.to_addr
|
|
|
idx = wallet.addrs.index(addr)
|
|
|
- sk,pk = wallet.keys[idx].sk,wallet.keys[idx].pk
|
|
|
-
|
|
|
+ sk, pk = wallet.keys[idx].sk, wallet.keys[idx].pk
|
|
|
+
|
|
|
string = str(utxo.pointer) + str(pk.to_bytes()) + str(tx_out)
|
|
|
message = build_message(string)
|
|
|
signature = sk.sign(message)
|
|
|
- tx_in.append(Vin(utxo.pointer,signature,pk.to_bytes()))
|
|
|
-
|
|
|
- return tx_in,tx_out,fee
|
|
|
+ tx_in.append(Vin(utxo.pointer, signature, pk.to_bytes()))
|
|
|
|
|
|
+ return tx_in, tx_out, fee
|
|
|
+
|
|
|
+
|
|
|
+# XGY: No Usage
|
|
|
+# def create_subtle_tx(nd,to_addr,value):
|
|
|
+# pass
|
|
|
|
|
|
-def create_subtle_tx(nd,to_addr,value):
|
|
|
- pass
|
|
|
|
|
|
def choose_raondom_txs_from_pool(pool):
|
|
|
n = len(pool)
|
|
|
+ # 挖矿节点n 最多为参数中的最大值
|
|
|
n = n if n < Params.MAX_TX_NUMBER_FOR_MINER else Params.MAX_TX_NUMBER_FOR_MINER
|
|
|
- candidates = random.sample(list(pool.keys()),n)
|
|
|
+ candidates = random.sample(list(pool.keys()), n)
|
|
|
return [pool.get(t) for t in candidates]
|
|
|
|
|
|
+
|
|
|
+"""
|
|
|
+从pool中提取list
|
|
|
+"""
|
|
|
+
|
|
|
+
|
|
|
def choose_whole_txs_from_pool(pool):
|
|
|
return list(pool.values())
|
|
|
|
|
|
+
|
|
|
# =============================================================================
|
|
|
-#broadcast transactions
|
|
|
+# broadcast transactions
|
|
|
# =============================================================================
|
|
|
-
|
|
|
-def broadcast_tx(peers,current_tx):
|
|
|
- rand,idxs,choice = random.uniform(0,1),range(len(peers)),[-1]
|
|
|
+
|
|
|
+def broadcast_tx(peers, current_tx):
|
|
|
+ rand, idxs, choice = random.uniform(0, 1), range(len(peers)), [-1]
|
|
|
number_of_verification = 0
|
|
|
-
|
|
|
+
|
|
|
if rand < Params.SLOW_PEERS_IN_NETWORK:
|
|
|
choice = [random.choice(idxs)]
|
|
|
if rand < Params.SLOWER_PEERS_IN_NETWORK:
|
|
|
- choice = random.sample(idxs,k = 2)
|
|
|
+ choice = random.sample(idxs, k=2)
|
|
|
|
|
|
- for i,peer in enumerate(peers):
|
|
|
+ for i, peer in enumerate(peers):
|
|
|
if peer._delayed_tx:
|
|
|
- dice = random.uniform(0,1)
|
|
|
+ dice = random.uniform(0, 1)
|
|
|
if dice > Params.SLOW_PEERS_IN_NETWORK:
|
|
|
fill_mem_pool(peer)
|
|
|
-
|
|
|
- if peer.verify_transaction(current_tx,peer.mem_pool):
|
|
|
+
|
|
|
+ if peer.verify_transaction(current_tx, peer.mem_pool):
|
|
|
if (i in choice) and (not peer._delayed_tx):
|
|
|
peer._delayed_tx = current_tx
|
|
|
continue
|
|
|
-
|
|
|
- add_tx_to_mem_pool(peer,current_tx)
|
|
|
- number_of_verification += 1
|
|
|
-
|
|
|
+
|
|
|
+ add_tx_to_mem_pool(peer, current_tx)
|
|
|
+ number_of_verification += 1
|
|
|
+
|
|
|
if peer.orphan_pool:
|
|
|
check_orphan_tx_from_pool(peer)
|
|
|
-
|
|
|
+
|
|
|
return number_of_verification
|
|
|
|
|
|
|
|
|
def check_orphan_tx_from_pool(peer):
|
|
|
copy_pool = peer.orphan_pool.copy()
|
|
|
for tx in copy_pool.values():
|
|
|
- if not verify_tx(tx,peer.mem_pool):
|
|
|
+ if not verify_tx(tx, peer.mem_pool):
|
|
|
return False
|
|
|
- add_tx_to_mem_pool(peer,tx)
|
|
|
+ add_tx_to_mem_pool(peer, tx)
|
|
|
del peer.orphan_pool[tx.id]
|
|
|
return True
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
# =============================================================================
|
|
|
#broadcast_block
|
|
|
# =============================================================================
|
|
|
@@ -874,4 +931,5 @@ def calculate_next_block_bits(local_time,prev_height,prev_bits):
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
- a,b = Peer(),Peer()
|
|
|
+ a = Peer()
|
|
|
+ print(a.wallet)
|