Пример #1
0
class Server():
    def __init__(self):
        self.app = Sanic(__name__)
        self.blockchain = Blockchain()
        self.sockets = []
        self.txnPool = []
        self.app.add_route(self.showChain, '/showChain', methods=['GET'])
        self.app.add_route(self.mineBlockPage, '/mineBlock', methods=['GET'])
        self.app.add_route(self.mineBlock, '/mineBlock', methods=['POST'])
        self.app.add_route(self.peers, '/peers', methods=['GET'])
        self.app.add_route(self.addPeer, '/addPeer', methods=['POST'])
        self.app.add_websocket_route(self.P2PHandler, '/')

    async def showChain(self, request):
        return response.text(self.blockchain.getJSON())

    async def mineBlockPage(self, request):
        return render_template('mineBlock.html')

    async def mineBlock(self, request):
        data = request.form['data'][
            0]  # IDK but data turns out to be a list instead of str
        currentBlock = self.blockchain.getLatestBlock()
        diff = self.blockchain.difficulty
        start_time = time.time()
        timestamp = calculateTimestamp(int(start_time))
        targetBlock = Block(currentBlock.index + 1, currentBlock.hash,
                            timestamp, data)
        while str(targetBlock.hash)[0:diff] != ''.join(['0'] * diff):
            targetBlock.incrementNonce()
        self.blockchain.addNewBlock(targetBlock)
        await self._broadcast(self.blockchain.getJSON(), P2P_broadcast_CHAIN)
        return response.text(str(targetBlock.nonce))

    async def peers(self, request):
        peers = map(
            lambda x: "{}:{}".format(x.remote_address[0], x.remote_address[1]),
            self.sockets)
        return response.json(peers)

    async def addPeer(self, request):
        asyncio.ensure_future(self.connect_to_peers([request.json['peer']]),
                              loop=asynico.get_event_loop())
        res = {"Status": True}
        return response.json(res)

    async def connect2Peers(self, newPeers):
        for peer in newPeers:
            try:
                ws = await websockets.connect(peer)
                await self.initConnection(ws)
            except Exception as e:
                print(str(e))

    async def P2PHandler(self, request, ws):
        try:
            await self.initConnection(ws)
        except ConnectionClosed:
            await self.connectionClosed(ws)

    async def initConnection(self, ws):
        self.sockets.append(ws)
        query = json.dumps({'type': P2P_query_ALLBLOCK})
        await ws.send(query)
        while True:
            await self.initMsgHandler(ws)

    async def connectionClosed(self, ws):
        self.sockets.remove(ws)
        print('Connection closed.')
        return

    async def initMsgHandler(self, ws):
        data = await ws.recv()
        message = json.loads(data)
        print(message)
        if message['type'] == P2P_query_LATESTBLOCK:
            await self.send_latest(ws, message)
        elif message['type'] == P2P_query_ALLBLOCK:
            await self.send_chain(ws, message)
        elif message['type'] == P2P_query_PEERLIST:
            await self.send_peerlist(ws, message)
        elif message['type'] == P2P_res_CHAIN:
            await self.process_res(ws, message)
        else:
            print('Bad query type.')

    async def send_latest(self, ws, *args):
        blockInfo = self.blockchain.getLatestBlock.getDictForm()
        res = json.dumps({'type': P2P_res_CHAIN, 'data': blockInfo})
        await ws.send(res)

    async def send_chain(self, ws, *args):
        chainInfo = self.blockchain.getJSON()
        res = json.dumps({'type': P2P_res_CHAIN, 'data': chainInfo})
        await ws.send(res)

    async def send_peerlist(self, ws, *args):
        pass

    async def process_res(self, ws, message):
        blockRecv = Blockchain.buildChainFromJSON(message['data'])
        print(message['data'])
        choose = Blockchain.chooseChain(self.blockchain, blockRecv)
        if isinstance(choose, int):
            print("Error: invalid chain. Code = ", choose)
        else:
            print("Chain replaced.")
            self.blockchain = choose

    async def _broadcast(self, message, option=P2P_broadcast_CHAIN):
        ''' General broadcast method, either works for txn and block.'''
        for socket in self.sockets:
            await socket.send(json.dumps({'type': option, 'data': message}))
Пример #2
0
import pprint as p
from blockchain import Blockchain

bch = Blockchain()
bch.addNewBlock('First transaction')
bch.addNewBlock('Second transaction')
bch.addNewBlock('Third transaction')
bch.addNewBlock('First transaction')
bch.addNewBlock('Second transaction')
bch.addNewBlock('Second transaction')
bch.addNewBlock('Second transaction')
bch.addNewBlock('Second transaction')

p.pprint(bch.blocks)