2 次代碼提交 fa585c6025 ... 4a9362c20d

作者 SHA1 備註 提交日期
  drumstick-code 4a9362c20d Merge remote-tracking branch 'origin/master' 6 年之前
  drumstick-code a9949a440c 添加peers前半部分的代码,补充了必要的文件 6 年之前
共有 5 個文件被更改,包括 268 次插入50 次删除
  1. 1 2
      SEECBC-Test/knowledge.txt
  2. 1 1
      SEECBC-Test/logger.py
  3. 203 0
      SEECBC-Test/network.py
  4. 4 4
      SEECBC-Test/peer.py
  5. 59 43
      SEECBC-Test/vm.py

+ 1 - 2
SEECBC-Test/knowledge.txt

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

+ 1 - 1
SEECBC-Test/logger.py

@@ -3,7 +3,7 @@
 import logging
 
 logging.basicConfig(level= logging.DEBUG,
-                    format = '%(asctime)s - %(message)s')
+                    format = 'SEEC-BC: %(asctime)s - %(message)s')
 
 
 logger = logging.getLogger(__name__)

+ 203 - 0
SEECBC-Test/network.py

@@ -0,0 +1,203 @@
+# -*- coding: utf-8 -*-
+
+import time
+import random
+from datatype import Vin,Vout,Tx,Block,get_merkle_root_of_txs
+from logger import logger
+from peer import Peer,find_utxos_from_block,add_utxos_to_set
+
+from consensus import consensus_with_fasttest_minner
+from params import Params
+from math import ceil
+from itertools import accumulate
+
+
+#Class p2p Network 
+# =============================================================================
+
+class Network(object):
+
+    def __init__(self,nop = None,von = None):
+        
+        self.peers = []
+        self.off_peers = []
+        self.consensus_peers = []
+        self.current_winner = None
+        self.winner = []
+        self.init_peers_number = nop or Params.INIT_NUMBER_OF_PEERS
+        self.init_value = von or Params.INIT_COIN_PER_PEER
+        self.create_genesis_block(self.init_peers_number,self.init_value)
+        self.time_spent = [0]
+        
+        self._is_consensus_peers_chosen = False
+        self._not = 0
+
+    
+    def init_peers(self,number):
+        for _ in range(number):
+            coords = generate_random_coords()
+            peer = Peer(coords)
+            create_peer(self,peer)
+    
+    def add_peer(self):
+        coords = generate_random_coords()#产生随机坐标
+        peer = Peer(coords)
+        create_peer(self,peer)
+        #Change
+        peer.update_utxo_set(self.peers[0])
+        peer.update_mem_pool(self.peers[0])
+        peer.update_blockchain(self.peers[0])
+        logger.info('A new peer joined in --> {0}(pid={1})'.format(peer,peer.pid))
+
+    #添加创世块
+    def create_genesis_block(self,number,value):
+        self.init_peers(number = number)
+        tx_out = [Vout(value=value, to_addr=peer.wallet.addresses[-1])
+                  for peer in self.peers]
+
+        tx_in =[Vin(to_spend = None,
+                    signature = b'SEECBC',#change
+                    pubkey = None)]
+
+        txs = [Tx(tx_in = tx_in,tx_out = tx_out,nlocktime = 0)]
+        genesis_block = Block(version=0,prev_block_hash=None,timestamp = 841124,bits = 0,nonce = 0,txs = txs)
+        logger.info('A blockchain p2p network created,{0} peers joined'.format(self.nop))
+        logger.info('genesis block has been generated')
+        
+        utxos = find_utxos_from_block(txs)
+        for peer in self.peers:
+            peer.blockchain.append(genesis_block)
+            add_utxos_to_set(peer.utxo_set,utxos)
+        
+    #产生随机的交易
+    def make_random_transactions(self):
+        random_index = random.randint(1,self.nop)
+        self._not = random_index
+        for _ in range(random_index):
+            reciever = random.choice(self.peers[1:])
+            sender = random.choice(self.peers[1:])
+            sender.create_transaction(reciever.wallet.addresses[-1],
+                                      tx_random_value())
+            sender.broadcast_transaction()
+
+    def set_consensus_peers(self,*idx):
+        for index in idx:
+            self.consensus_peers.append(self.peers[index])
+            
+        self._is_consensus_peers_chosen = True
+    
+    def choose_random_consensus_peers(self):
+        n = self.nop
+        #we suppose we have 20%~60% nodes are consensus node
+        lower_bound = Params.LOWWER_BOUND_OF_CONSENSUS_PEERS
+        upper_bound = Params.UPPER_BOUND_OF_CONSENSUS_PEERS
+        k = random.randint(ceil(lower_bound*n),ceil(upper_bound*n))
+        self.consensus_peers = random.sample(self.peers,k)     
+        self._is_consensus_peers_chosen = True
+        
+        
+    def consensus(self,meth = 'pow'):
+        if not self._is_consensus_peers_chosen:
+            self.choose_random_consensus_peers()
+        
+        if meth == 'pow':
+            logger.info('{0} peers are mining'.format(len(self.consensus_peers)))
+            n,nonce,time = consensus_with_fasttest_minner(self.consensus_peers)
+            self.time_spent.append(time)
+            self.current_winner = self.consensus_peers[n]
+            self.winner.append(self.current_winner)
+            
+            logger.info('{0}(pid={1}) is winner,{2} secs used'.format(
+                    self.current_winner,
+                    self.current_winner.pid,
+                    time
+                    ))
+            
+            block = self.current_winner.package_block(nonce = nonce)
+            self.current_winner.recieve_block(block)
+            self.current_winner.broadcast_block(block)
+            
+    def draw(self):
+        pass
+    
+    @property
+    def time(self):
+        return _accumulate(self.time_spent)
+
+    def get_time(self):
+        return self.time[-1]
+ 
+    @property
+    def nop(self):
+        return len(self.peers)
+    
+    def __repr__(self):
+        return 'A p2p blockchain network with {0} peers'.format(self.nop)
+
+def create_peer(net,peer):
+    peer.network = net
+    peer.pid = net.nop
+    peer.wallet.new_keys()
+    net.peers.append(peer)
+
+
+#functions
+# =============================================================================
+
+
+
+#Iterables 
+# =============================================================================
+    
+
+# 返回交易中所有输出地址
+def addr_finder(tx):
+    return (out.vout.to_addr for out in tx.tx_out)
+
+def _accumulate(_list):
+    return list(accumulate(_list))
+    
+#random data
+# =============================================================================
+
+def tx_random_value():
+    return random.randint(0,100)
+
+#产生一个随机的tuple坐标
+def generate_random_coords():
+    return (random.randint(0,100),random.randint(0,100))
+
+    
+if __name__ == "__main__":
+   pass
+   net = Network(nop = 2,von = 10000)
+   zhangsan = net.peers[0]
+   zhangsan,lisi = net.peers[0],net.peers[1]
+   zhangsan.create_transaction(lisi.wallet.addresses[0],100)
+   zhangsan.broadcast_transaction()
+   lisi.create_transaction(zhangsan.wallet.addresses[0],100)
+   lisi.broadcast_transaction()
+
+   net = Network()
+   net.make_random_transactions()
+   net.consensus()
+   b = zhangsan.get_utxos()[0]
+   print(b.pubkey_script)
+   # tx = zhangsan.current_tx
+   # vin = tx.tx_in[0]
+   # vin1 = Vin(vin.to_spend,b'1'*64,vin.pubkey)
+   # tx.tx_in[0] = vin1
+   # lisi.mem_pool = {}
+   # lisi.verify_transaction(tx,lisi.mem_pool)
+   #
+   #
+   #
+   #
+   # for _ in range(4):
+   #     net.make_random_transactions()
+   #     net.consensus()
+
+
+
+        
+

+ 4 - 4
SEECBC-Test/peer.py

@@ -94,7 +94,7 @@ class Peer(object):
     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]
+                if (utxo.vout.to_addr in self.wallet.addresses) and utxo.unspent]
 
     # """
     # 获取未确定的未消费的交易
@@ -148,7 +148,7 @@ class Peer(object):
     """
 
     def create_coinbase(self, value):
-        return Tx.create_coinbase(self.wallet.addrs[-1], value=value)
+        return Tx.create_coinbase(self.wallet.addresses[-1], value=value)
 
     ############################################################
     # peer as route
@@ -475,7 +475,7 @@ def create_normal_tx(peer, to_addr, value):
             break
     # 如果总计大于value
     if sum > value:
-        my_addr = wallet.addrs[-1]
+        my_addr = wallet.addresses[-1]
         tx_out += [Vout(to_addr, value - fee), Vout(my_addr, sum - value)]
     # 否则一定是相等
     else:
@@ -484,7 +484,7 @@ def create_normal_tx(peer, to_addr, value):
     # 将刚刚交易的utxo都封装为[vin]
     for utxo in utxos[:n]:
         addr = utxo.vout.to_addr
-        idx = wallet.addrs.index(addr)
+        idx = wallet.addresses.index(addr)
         sk, pk = wallet.keys[idx].sk, wallet.keys[idx].pk
 
         string = str(utxo.pointer) + str(pk.to_bytes()) + str(tx_out)

+ 59 - 43
SEECBC-Test/vm.py

@@ -6,28 +6,29 @@ from ecc import convert_pubkey_to_addr,VerifyingKey,sha256d
 class Stack(list):
     
     push = list.append
-    
+
+    #获取最后一个元素
     def peek(self):
         return self[-1]
 
-    
+# 见4.5.3
 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,
-            }
+            "OP_ADDR": self.calc_addr,
+            "OP_DUP": self.dup,
+            "OP_NDUP": self.ndup,  # 复制N个元素到栈顶
+            "OP_MULHASH": self.calc_mulhash,  # 计算多重公钥哈希
+            "OP_CHECKSIG": self.check_sig,  # 验证签名
+            "OP_CHECKMULSIG": self.check_mulsig,  # 验证多重签名
+            "OP_ADD": self.add,
+            "OP_MINUS": self.minus,
+            "OP_MUL": self.mul,
+            "OP_EQ": self.equal_check,
+            "OP_EQUAL": self.equal,
+        }
 
 
     def set_script(self,script,message = b''):
@@ -47,55 +48,69 @@ class LittleMachine(object):
     def pop(self):
         return self.stack.pop()
 
-    def push(self,value):
-        self.stack.push(value)
+    def push(self, element):
+        self.stack.push(element)
 
-    def evaluate(self,op):
-        if op in self._map:
-            self._map[op]()
+    def evaluate(self, opcode):
+        if opcode in self._map:
+            self._map[opcode]()
+
+        #如果是值,则压栈
+        elif self.__is_value__(opcode):
+            self.push(opcode)
+        else:
+            logger.info('Uknow opcode: '.format(opcode))
 
-        elif isinstance(op,str) or\
-             isinstance(op,bytes)or\
-             isinstance(op,int) or\
-             isinstance(op,bool):
-            self.push(op)
+    #自己的方法,用于判断是否是value
+    def __is_value__(self, opcode):
+        if isinstance(opcode, bool) or isinstance(opcode, str) or \
+                isinstance(opcode, bytes) or isinstance(opcode, int):
+            return True
         else:
-            logger.info('Uknow opcode: '.format(op))
+            return False
 
     def add(self):
         self.push(self.pop() + self.pop())
 
     def minus(self):
-        last = self.pop()
-        self.push(self.pop() - last)
+        element1 = self.pop()
+        element2 = self.pop()
+        self.push(element2 - element1)
 
     def mul(self):
-        self.push(self.pop() * self.pop())
+        element1 = self.pop()
+        element2 = self.pop()
+        self.push(element1 * element2)
 
     def dup(self):
-        self.push(self.peek())
+        element1 = self.peek();
+        self.push(element1)
 
     def ndup(self):
         n = self.pop()
-        for val in self.stack[-n:]:
-            self.push(val)
+        for element in self.stack[-n:]:
+            self.push(element)
         self.push(n)
 
     def equal_check(self):
-        flag = self.pop() == self.pop()
+        element1 = self.pop()
+        element2 = self.pop()
+        flag = (element1 == element2)
         if not flag:
             self.result = False
 
     def equal(self):
-        self.push(self.pop()==self.pop())
+        element1 = self.pop()
+        element2 = self.pop()
+        self.push(element1 == element2)
 
     def calc_mulhash(self):
         n = self.pop()
         pk_strs = [self.pop() for _ in range(n)]
-        s = b''
+        all_pk_str = b''
         for val in pk_strs[::-1]:
-            s += val
-        self.push(sha256d(s))
+            all_pk_str =all_pk_str + val
+        self.push(sha256d(all_pk_str))
         
 
     def check_sig(self):
@@ -122,7 +137,7 @@ class LittleMachine(object):
             except Exception:
                 flag = False
             if not flag:
-                falg = False
+                #falg = False
                 break
         self.push(flag)
         
@@ -132,15 +147,16 @@ class LittleMachine(object):
         self.push(convert_pubkey_to_addr(pk_str))
         
     def run(self):
-        while (self.pointer < len(self.script)):
-            op = self.script[self.pointer]
+        script_len = len(self.script)
+        while (self.pointer < script_len):
+            opcode = self.script[self.pointer]
             self.pointer += 1
-            self.evaluate(op)
+            self.evaluate(opcode)
             
-        if not self.result:
-            return False
-        else:
+        if self.result:
             return self.peek()
+        else:
+            return False
 
 
 if __name__ == "__main__":