Parcourir la source

添加peers前半部分的代码,补充了必要的文件

drumstick-code il y a 6 ans
Parent
commit
4c321ac3ac
7 fichiers modifiés avec 913 ajouts et 261 suppressions
  1. 75 0
      SEECBC-Test/consensus.py
  2. 283 0
      SEECBC-Test/datatype.py
  3. 2 0
      SEECBC-Test/knowledge.txt
  4. 32 0
      SEECBC-Test/params.py
  5. 318 260
      SEECBC-Test/peer.py
  6. 202 0
      SEECBC-Test/vm.py
  7. 1 1
      SEECBC-Test/wallet.py

+ 75 - 0
SEECBC-Test/consensus.py

@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+"""
+"""
+
+
+from ecc import sha256d
+import time 
+
+
+def caculate_target(bits):
+    return (1 << (256 - bits))
+
+def mine(block):
+    nonce = 0
+    target = caculate_target(block.bits)
+    merkle_root_hash = block.get_merkle_root()
+    while int(sha256d(block.header(nonce,merkle_root_hash)), 16) >= target:
+        nonce += 1
+    
+    return nonce
+
+
+def consensus_with_fasttest_minner(peers):
+    l,start = [],time.time()
+    for peer in peers:
+        l.append(peer.consensus())
+    return l.index(min(l)),min(l),time.time()-start
+
+
+
+
+
+
+def get_block_reward(height,fees = 0):
+##    COIN = int(1e8)
+    reward_interval = 210000
+    reward = 50
+    halvings = height // reward_interval
+
+    if halvings >= 64:
+        return fees
+
+    reward >>= halvings
+    return reward + fees
+
+
+if __name__ == "__main__":
+    import matplotlib.pyplot as plt
+    from itertools import accumulate
+    plt.rcParams['font.sans-serif']=['SimHei']
+    plt.rcParams['axes.unicode_minus']=False
+    x = [2009,2013,2017,2021,2025,2029,2033]
+    d = 4*365*24*6*50
+    y = [0,d,d/2,d/4,d/8,d/16,d/32]
+    y = list(accumulate(y))
+    plt.plot(x,y,'r-')
+    plt.xlim([2009,2033])
+    plt.ylim([0,21e6])
+    plt.xlabel(u'年份')
+    plt.ylabel(u'流通中的比特币总量')
+    plt.show()
+    
+##    from datatype import Block,Vin,Vout,Tx
+##    block = Block(version=0, 
+##              prev_block_hash=None,
+##              timestamp=12234, 
+##              bits= 21, 
+##              nonce=100000,
+##              txs=[Tx(tx_in=[Vin(to_spend=None, 
+##                                 signature=b'0', 
+##                                 pubkey=None)],
+##                      tx_out=[Vout(to_addr='143UVyz7ooiAv1pMqbwPPpnH4BV9ifJGFF',
+##                                          value=5000000000)],nlocktime= 111)])
+##    
+##    b = mine(block)

+ 283 - 0
SEECBC-Test/datatype.py

@@ -0,0 +1,283 @@
+#!/usr/bin/env python3
+
+import os 
+from ecc import sha256d
+
+#A pointer to a transaction unspent output
+class Pointer(tuple):
+
+    def __new__(cls,tx_id,n):
+        return super(Pointer,cls).__new__(cls,(tx_id,n))
+
+    @property
+    def tx_id(self):
+        return self[0]
+
+    @property
+    def n(self):
+        return self[1]
+    # XGY:重新打印时的方法,相当于String
+    def __repr__(self):
+        return "Pointer(tx_id:{0},n:{1})".format(self[0],self[1])
+    
+    
+    
+#value input for a transaction
+class Vin(tuple):
+
+    def __new__(cls,to_spend,signature,pubkey):
+        return super(cls,Vin).__new__(cls,(to_spend,signature,pubkey))
+        
+    
+    @property
+    def to_spend(self):
+        return self[0]
+    
+    @property
+    def signature(self):
+        return self[1]
+
+    #XGY: 公共密钥
+    @property
+    def pubkey(self):
+        return self[2]
+
+    @property
+    def sig_script(self):
+        return self[1]+self[2]
+
+    def __repr__(self):
+        return "Vin(to_spend:{0},signature:{1},pubkey:{2})".format(self[0],self[1],self[2])
+    
+
+#value output for a transaction
+class Vout(tuple):
+    
+    def __new__(cls,to_addr,value):
+        return super(Vout,cls).__new__(cls,(to_addr,value))
+        
+        
+    @property
+    def to_addr(self):
+        return self[0]
+    
+    @property
+    def value(self):
+        return self[1]
+
+    @property
+    def pubkey_script(self):
+        script = "OP_DUP OP_ADDR {0} OP_EQ OP_CHECKSIG".format(self[0])
+        return script
+
+    def __repr__(self):
+        return "Vout(to_addr:{0},value:{1})".format(self[0],self[1])
+
+#unspent transation output
+class UTXO(tuple):
+    
+    def __new__(cls,
+                vout,
+                pointer,
+                is_coinbase,
+                unspent=True,
+                confirmed=False,
+                ):
+        return super(UTXO,cls).__new__(cls,(vout,
+                                            pointer,
+                                            is_coinbase,
+                                            unspent,
+                                            confirmed))
+        
+    
+    @property
+    def vout(self):
+        return self[0]
+    
+    @property
+    def pointer(self):
+        return self[1]
+    
+    @property
+    def is_coinbase(self):
+        return self[2]
+
+    @property
+    def pubkey_script(self):
+        return self[0].pubkey_script
+
+    @property
+    def unspent(self):
+        return self[3]
+
+
+    @property
+    def confirmed(self):
+        return self[4]
+
+    def _replace(self,unspent = True, confirmed = False):
+        return UTXO(self[0],self[1],self[2],unspent,confirmed)
+    
+    def __repr__(self):
+        return "UTXO(vout:{0},pointer:{1})".format(self[0],self[1])
+
+
+#transaction
+class Tx(tuple):
+    
+    def __new__(cls,tx_in,tx_out,fee=0,timestamp=0,nlocktime=0):
+        return super(Tx,cls).__new__(cls,(tx_in,
+                                          tx_out,
+                                          fee,
+                                          timestamp,
+                                          nlocktime))
+        
+    @property
+    def tx_in(self):
+        return self[0]
+    
+    @property
+    def tx_out(self):
+        return self[1]
+    
+    @property
+    def fee(self):
+        return self[2]
+    
+    @property
+    def nlocktime(self):
+        return self[3]
+    
+    @property
+    def is_coinbase(self) -> bool:
+        return len(self[0]) == 1 and self[0][0].to_spend is None
+
+    @classmethod
+    def create_coinbase(cls, pay_to_addr, value):
+        return cls(
+            tx_in = [Vin(to_spend=None,
+                         signature= str(os.urandom(32)),
+                         pubkey=None)],
+            tx_out = [Vout(to_addr=pay_to_addr,
+                           value=value)]
+            )
+
+    @property
+    def id(self):
+        return sha256d(self.to_string())
+    
+    def to_string(self):
+        return "{0}{1}{2}".format(self[0],
+                                  self[1],
+                                  self[3])
+
+    def __repr__(self):
+        return "Tx(id:{0})".format(self.id)
+
+
+#block
+class Block(tuple): 
+    def __new__(cls,version,
+                prev_block_hash,
+                timestamp,
+                bits,
+                nonce,
+                txs):
+        return super(Block,cls).__new__(cls,(version,
+                                             prev_block_hash,
+                                             timestamp,
+                                             bits,
+                                             nonce,
+                                             txs))
+        
+    
+    @property
+    def version(self):
+        return self[0]
+    
+    @property
+    def prev_block_hash(self):
+        return self[1]
+    
+    @property
+    def timestamp(self):
+        return self[2]
+    
+    @property
+    def bits(self):
+        return self[3]
+    
+    @property
+    def nonce(self):
+        return self[4]
+    
+    @property
+    def txs(self):
+        return self[5]
+
+    @property
+    def merkle_root_hash(self):
+        return self.get_merkle_root()
+
+    def _replace(self,nonce = 0):
+        return Block(self[0],
+                     self[1],
+                     self[2],
+                     self[3],
+                     nonce,
+                     self[5])
+
+    #XGY: 可信签名树,用于签名认证
+    def get_merkle_root(self):
+        return get_merkle_root_of_txs(self.txs) if self.txs else None
+    
+    def header(self,nonce = None,merkle_root_hash = None):
+        if merkle_root_hash is None:
+            merkle_root_hash = self.get_merkle_root()
+            
+        return "{0}{1}{2}{3}{4}{5}".format(self[0],
+                                           self[1],
+                                           self[2],
+                                           self[3],
+                                           merkle_root_hash,
+                                           nonce or self[4])
+
+    @property
+    def hash(self):
+        return sha256d(self.header())
+
+    def __repr__(self):
+        return "Block(hash:{0})".format(self.hash)
+
+
+
+def get_merkle_root_of_txs(txs):
+    return get_merkle_root([tx.id for tx in txs])
+
+
+def get_merkle_root(level):
+    
+    while len(level) != 1:
+        odd = None
+        if len(level) % 2 == 1:
+            odd = level.pop()
+            
+        level = [sha256d(i1+i2) for i1,i2 in pair_node(level)]
+
+        if odd:
+            level.append(odd)
+    return level[0]
+    
+def pair_node(l):
+    return (l[i:i + 2] for i in range(0, len(l), 2))
+
+
+if __name__ == "__main__":
+    p = Pointer(1,2)
+    vout = Vout(1,2)
+    utxo = UTXO((1,2),[2,3],True,1)
+    vin = Vin(p,b'1',b'12')
+    tx = Tx([vin],[vout])
+    block = Block(1,2,3,4,5,[tx])
+    
+    

+ 2 - 0
SEECBC-Test/knowledge.txt

@@ -8,3 +8,5 @@
 7 hdwallet 可以通过父私钥+父链码+索引号 生成 子私钥.....
 8 hdwallet 钱包路径可以表示为 m/22/3/1 m 的 23个索引子的3的子的1的子
 
+4.
+

+ 32 - 0
SEECBC-Test/params.py

@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+class Params:
+    
+    MAX_FUTURE_BLOCK_TIME = 10*6
+    
+    PERIOD_FOR_ONE_CONSENSUS = 1 * 5 #we hope 10 secs for one consensus
+    
+    PERIOD_FOR_TOTAL_BLOCKS = 5 * 20 #adjust difficults 20 blocks are found 
+    
+    TOTAL_BLOCKS = PERIOD_FOR_TOTAL_BLOCKS/PERIOD_FOR_ONE_CONSENSUS
+    
+    INITIAL_DIFFICULTY_BITS = 18 
+    
+    FIX_BLOCK_REWARD = 500
+    
+    MAX_TX_NUMBER_FOR_MINER = 5 
+    
+    INIT_NUMBER_OF_PEERS = 12
+    
+    INIT_COIN_PER_PEER = 100000
+    
+    FIX_FEE_PER_TX = 10
+    
+    UPPER_BOUND_OF_CONSENSUS_PEERS = 60./100
+    
+    LOWWER_BOUND_OF_CONSENSUS_PEERS = 20./100
+    
+    SLOW_PEERS_IN_NETWORK = 20./100
+    
+    SLOWER_PEERS_IN_NETWORK = 10./100
+    
+    

+ 318 - 260
SEECBC-Test/peer.py

@@ -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)

+ 202 - 0
SEECBC-Test/vm.py

@@ -0,0 +1,202 @@
+
+
+from logger import logger
+from ecc import convert_pubkey_to_addr,VerifyingKey,sha256d
+
+class Stack(list):
+    
+    push = list.append
+    
+    def peek(self):
+        return self[-1]
+
+    
+class LittleMachine(object):
+
+    def __init__(self):
+        self.stack = Stack()
+        self._map = {
+            "OP_ADD":          self.add,
+            "OP_MINUS":        self.minus,
+            "OP_MUL":          self.mul,
+            "OP_EQ":           self.equal_check,
+            "OP_EQUAL"    :    self.equal,
+            "OP_CHECKSIG":     self.check_sig,
+            "OP_ADDR":         self.calc_addr,
+            "OP_DUP"      :    self.dup,
+            "OP_NDUP"     :    self.ndup,
+            "OP_CHECKMULSIG" : self.check_mulsig,
+            "OP_MULHASH":      self.calc_mulhash,
+            }
+
+
+    def set_script(self,script,message = b''):
+        self.clear()
+        self.result = True
+        self.pointer = 0
+        self.message = message
+        self.script = script
+        
+
+    def clear(self):
+        self.stack.clear()
+        
+    def peek(self):
+        return self.stack.peek()
+    
+    def pop(self):
+        return self.stack.pop()
+
+    def push(self,value):
+        self.stack.push(value)
+
+    def evaluate(self,op):
+        if op in self._map:
+            self._map[op]()
+
+        elif isinstance(op,str) or\
+             isinstance(op,bytes)or\
+             isinstance(op,int) or\
+             isinstance(op,bool):
+            self.push(op)
+        else:
+            logger.info('Uknow opcode: '.format(op))
+
+    def add(self):
+        self.push(self.pop() + self.pop())
+
+    def minus(self):
+        last = self.pop()
+        self.push(self.pop() - last)
+
+    def mul(self):
+        self.push(self.pop() * self.pop())
+
+    def dup(self):
+        self.push(self.peek())
+
+    def ndup(self):
+        n = self.pop()
+        for val in self.stack[-n:]:
+            self.push(val)
+        self.push(n)
+
+    def equal_check(self):
+        flag = self.pop() == self.pop()
+        if not flag:
+            self.result = False
+
+    def equal(self):
+        self.push(self.pop()==self.pop())
+
+    def calc_mulhash(self):
+        n = self.pop()
+        pk_strs = [self.pop() for _ in range(n)]
+        s = b''
+        for val in pk_strs[::-1]:
+            s += val
+        self.push(sha256d(s))
+        
+
+    def check_sig(self):
+        pk_str = self.pop()
+        sig = self.pop()
+        verifying_key = VerifyingKey.from_bytes(pk_str)
+        
+        try:
+            flag = verifying_key.verify(sig,self.message)
+        except Exception:
+            flag = False
+        self.push(flag)
+
+    def check_mulsig(self):
+        n = self.pop()
+        pk_strs = [self.pop() for _ in range(n)]
+        m = self.pop()
+        sigs = [self.pop() for _ in range(m)]
+        pk_strs = pk_strs[-m:]
+        for i in range(m):
+            verifying_key = VerifyingKey.from_bytes(pk_strs[i])
+            try:
+                flag = verifying_key.verify(sigs[i],self.message)
+            except Exception:
+                flag = False
+            if not flag:
+                falg = False
+                break
+        self.push(flag)
+        
+
+    def calc_addr(self):
+        pk_str = self.pop()
+        self.push(convert_pubkey_to_addr(pk_str))
+        
+    def run(self):
+        while (self.pointer < len(self.script)):
+            op = self.script[self.pointer]
+            self.pointer += 1
+            self.evaluate(op)
+            
+        if not self.result:
+            return False
+        else:
+            return self.peek()
+
+
+if __name__ == "__main__":
+    from datatype import Vin,Vout
+    from ecc import SigningKey,convert_pubkey_to_addr
+##    k = 12356
+##    k1 = 23464
+##    sk = SigningKey.from_number(k)
+##    pk = sk.get_verifying_key()
+##
+##    sk1 = SigningKey.from_number(k1)
+##    pk1 = sk1.get_verifying_key()
+##    addr = convert_pubkey_to_addr(pk.to_bytes())
+##    addr1 = convert_pubkey_to_addr(pk1.to_bytes())
+##    
+##    m1 = b'hello'
+##    m2 = b'go away'
+##    sig = sk.sign(m1)
+##    sig1 = sk1.sign(m2)
+##    vin = Vin(None,sig1,pk1.to_bytes())
+##    vout = Vout(addr,10)
+##    
+##    sig_script = [vin.sig_script[:64],vin.sig_script[64:]]
+##    pubkey_script = vout.pubkey_script.split(' ')
+
+
+    kA = 3453543
+    kB = 2349334
+    skA = SigningKey.from_number(kA)
+    skB = SigningKey.from_number(kB)
+    pkA = skA.get_verifying_key()
+    pkB = skB.get_verifying_key()
+    message = b'I love blockchain'
+
+    sigA = skA.sign(message)
+    sigB = skB.sign(message)
+    Hash = sha256d(pkA.to_bytes()+pkB.to_bytes())
+    sig_script = [sigA,sigB,2,pkA.to_bytes(),pkB.to_bytes(),2]
+    pubkey_script = ['OP_NDUP','OP_MULHASH',Hash,'OP_EQ',2,'OP_CHECKMULSIG']
+    script = sig_script + pubkey_script
+    machine = LittleMachine()
+    machine.set_script(script,message)
+    print (machine.run())
+    
+##    script = [a,1,2,'OP_DUP','OP_ADD','OP_EQ']
+##    machine = LittleMachine()
+##    machine.set_script(script)
+##    print(machine.run())
+
+    
+
+            
+
+    
+
+
+    
+        
+        

+ 1 - 1
SEECBC-Test/wallet.py

@@ -19,7 +19,7 @@ class Keys(tuple):
 
 
 class Wallet(object):
-    def __init__(self,generation_method):
+    def __init__(self,generation_method = 'ecc'):
         self.generation_method = generation_method
         self.keys = []
         self.addresses = []