Exemplo n.º 1
0
 def on_new_block_received(self, block):
     print('block receiced')
     block = Block.unpack(block)
     if self.add_block(block):
         print('try to stop current miner')
         self.stop_miner()  # stop current miner
         self.prev_hash = block.hash
         self.peer.sendall_block(msgtype=MsgType.TYPE_NEW_BLOCK,
                                 content=block.b)
         print('try to start a new miner')
         self.start_miner()  # start a new miner
    def make_block(self, nonce) -> Block:
        trans = self.__get_trans()
        info = Attachment()
        info.add_data(b'mined by ' + self.name.encode())
        info.ready()

        block = Block(
            0,  # todo: get index
            timestamp=time.time(),
            blockdata=BlockData(trans, info),
            previous_hash=self.prev_hash,
            nonce=nonce)
        return block
Exemplo n.º 3
0
    def handle(self):
        flag = 0
        # print(BlockchainMixin.state)
        while True:
            header = self.request.recv(LENGTH_HEADER)

            if len(header) == 0:
                # self.handler_log.debug('pid {0} Round end: {1}'.format(os.getpid(), time.time()))
                # print('pid {0} Round end: {1}'.format(os.getpid(), time.time()))
                break

            if flag == 0:
                # self.handler_log.debug('pid {0} Round start: {1}'.format(os.getpid(), time.time()))
                # print('pid {0} Round start: {1}'.format(os.getpid(), time.time()))
                flag = 1

            typ = header[4:8]
            len_h = struct.unpack('=i', header[:4])[0]
            content = bytes()
            '''Just receive all the content'''
            l = 0
            while l < len_h:
                piece = self.request.recv(min(PIECE, len_h - l))
                content += piece
                l += len(piece)
            '''Check whether the block content has been received (hash or keyword IN)
            if so, continue the loop'''
            # print('received from: ', self.request.getpeername())
            '''PBFT state machine'''
            if BlockchainMixin.state is StatePBFT.IDLE:
                if typ == TYPE_TRANS:  # keep receiving trans until reach the limitation
                    BlockchainMixin.lock.acquire()
                    BlockchainMixin.trans.append(Transaction.unpack(content))
                    BlockchainMixin.lock.release()
                    if len(BlockchainMixin.trans
                           ) == BlockchainMixin.trans_limit:  # prepare a block
                        at = Attachment()
                        at.add_data(b'')
                        at.ready()

                        bd = BlockData(BlockchainMixin.trans, at)
                        block = Block(
                            BlockchainMixin.chain.chain[-1].index + 1,
                            time.time(), bd,
                            BlockchainMixin.chain.chain[-1].hash)
                        msg = BlockchainMixin.pre_prepare_msg(
                            BlockchainMixin.view, BlockchainMixin.n_request,
                            block.b)

                        BlockchainMixin.n_request += 1
                        BlockchainMixin.state = StatePBFT.PREPARE
                        BlockchainMixin.temp_block.append(block.b)
                        for ip, port in BlockchainMixin.connection:
                            if (ip, port) == self.request.getpeername():
                                continue
                            BlockchainMixin.pool.apply_async(
                                self.sends, ((ip, port), msg))

                        BlockchainMixin.trans.clear()

                elif typ == TYPE_PRE_PREPARE:  # cache the block and response with PREPARE message
                    BlockchainMixin.lock.acquire()
                    # print('content', content)
                    BlockchainMixin.temp_block.append(content)
                    BlockchainMixin.state = StatePBFT.PREPARE
                    BlockchainMixin.lock.release()
                    msg = BlockchainMixin.prepare_msg(
                        BlockchainMixin.view, BlockchainMixin.num_nodes,
                        BlockchainMixin.index, content)
                    for ip, port in BlockchainMixin.connection:
                        BlockchainMixin.pool.apply_async(
                            self.sends, ((ip, port), msg))

            elif BlockchainMixin.state is StatePBFT.PREPARE:
                if typ == TYPE_PREPARE or typ == TYPE_COMMIT:
                    BlockchainMixin.lock.acquire()
                    BlockchainMixin.state = StatePBFT.COMMIT
                    BlockchainMixin.lock.release()
                    msg = BlockchainMixin.commit_msg(BlockchainMixin.view,
                                                     BlockchainMixin.num_nodes,
                                                     BlockchainMixin.index,
                                                     content)
                    for ip, port in BlockchainMixin.connection:
                        BlockchainMixin.pool.apply_async(
                            self.sends, ((ip, port), msg))

            elif BlockchainMixin.state is StatePBFT.COMMIT:
                if typ == TYPE_COMMIT:
                    BlockchainMixin.lock.acquire()
                    BlockchainMixin.state = StatePBFT.REPLY
                    BlockchainMixin.chain.add_block(
                        Block.unpack(BlockchainMixin.temp_block[0]))
                    BlockchainMixin.temp_block.clear()
                    BlockchainMixin.lock.release()
                    msg = BlockchainMixin.commit_msg(BlockchainMixin.view,
                                                     BlockchainMixin.num_nodes,
                                                     BlockchainMixin.index,
                                                     content)
                    for ip, port in BlockchainMixin.connection:
                        BlockchainMixin.pool.apply_async(
                            self.sends, ((ip, port), msg))

                    mm = '%f' % time.time()
                    print(mm)
                    with open('logs/srv' + str(BlockchainMixin.index) + '.txt',
                              'w') as logfile:
                        logfile.writelines([mm])

            elif BlockchainMixin.state is StatePBFT.REPLY:
                pass
    def test_001_block_write(self):
        """
        use the same case as the test_000_trans_write, but transactions are seperated into different blocks
        :return:
        """
        # replace the following connection address with the address in the chainbase

        tinput = [(
            b'O\x1e,-\xe1\xa0!\x16D\x87\xcc\x923\xf7\xf6\xca\xad\xd1\t\x8eV\xdc\xe8t}N\xfa\x8af\xbe\xe7\xef',
            0)]

        private_key1 = load_pem_private_key(
            b'-----BEGIN PRIVATE KEY-----\nMIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0w'
            b'awIBAQQg64DiDBUkuGC5rrTfH6uy\nHt6vhvHrMHj3Gm64SZtdqtKhRANCAATMIea'
            b'IK4vT0ni00F6GGW40qioinPFgXjsj\n6sZGivW9Ipj+zcDfPc7RxZuFeKFmbtVaUX'
            b'Z877DM4C8ELZs2DPVQ\n-----END PRIVATE KEY-----\n', None,
            default_backend())
        public_key = b'-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzCHmiCuL09J4tNBehhluNKoqIpzx' \
                     b'YF47\nI+rGRor1vSKY/s3A3z3O0cWbhXihZm7VWlF2fO+wzOAvBC2bNgz1UA==\n-----END PUBLIC KEY-----\n'
        sha = hashlib.sha256()
        sha.update(public_key)
        public_key_hash = sha.digest()

        T1 = TransInput(tinput, public_key_hash)

        public_key_hash = []
        private_keys = []
        public_keys = []

        for i in range(6):
            private_key = ec.generate_private_key(ec.SECP256K1,
                                                  default_backend())
            private_keys.append(private_key)

            public_key = private_key.public_key()
            public_key = public_key.public_bytes(
                Encoding.PEM, PublicFormat.SubjectPublicKeyInfo)
            public_keys.append(public_key)

            sha = hashlib.sha256()
            sha.update(public_key)
            public_key_hash.append(sha.digest())

        toutput = [(7, public_key_hash[i]) for i in range(6)]
        T2 = TransOutput(toutput)

        T = Transaction(T1, T2)
        T.ready(private_key1)

        pri_key = private_keys[0]
        public_key_hash1 = public_key_hash[0]

        T8 = TransInput([(T.txid, 0)], public_key_hash1)

        toutput = [(7, public_key_hash[1])]
        T9 = TransOutput(toutput)

        T4 = Transaction(T8, T9)
        T4.ready(pri_key)

        at = Attachment()
        at.add_data(b'')
        at.ready()

        bd = BlockData([T, T4], at)
        t = time.time()
        block = Block(
            1, t, bd,
            b'G\xfdk\x88\xda5\xff\x8c\x97t\x9f\xcb\xe0\xa8\x07S\x8b9t:.9\x1d\xee\xf4\xb1\xda\xd1r\xaf\xfcu',
            33)
        """
        construct a second valid transaction, which pay 7 from random address 1 to random address 2 
        """

        with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM
                           ) as s:  # submit the second valid transaction

            s.connect(self.address)
            payload = send_handler(MsgType.TYPE_BLOCK_WRITE, block.b)
            s.sendall(payload)
            header, length, msgtype, content = recv_parser(s)

            self.assertEqual(content, b'')
            self.assertEqual(length, 0)
            self.assertEqual(
                msgtype, MsgType.TYPE_RESPONSE_OK)  # the chainbase returns OK