示例#1
0
    def run(self):
        parser = argparse.ArgumentParser()
        parser.add_argument("command",
                            help="type of operation: add <data> or show")
        parser.add_argument("--data", help="block data")

        args = parser.parse_args()

        blockchain = Blockchain()

        if args.data:
            if args.command == "add":
                blockchain.add_block(args.data)
                print("Done")

        if args.command == "show":
            iterator = blockchain.iterator()

            while True:
                block = iterator.next()

                print("previous_hash : " + block['previous_hash'])
                print("current_hash : " + block['hash'])
                print("data : " + block['data'])
                print("timestamp : " + block['timestamp'])
                print("nounce : " + str(block['nounce']))
                print('\n')

                if block['previous_hash'] == "0":
                    break
示例#2
0
    def test_is_valid_chain__valid_chain(self):
        other_chain = Blockchain()
        other_chain.add_block(other_chain.generate_new_block('new-block'))
        other_chain.add_block(
            other_chain.generate_new_block('other-new-block'))

        self.assertTrue(self.blockchain.is_valid_chain(other_chain.blocks))
示例#3
0
    def replace_chain(self):
        other_chain = Blockchain()
        other_chain.add_block(other_chain.generate_new_block('new-block'))
        new_latest_block = other_chain.add_block(
            other_chain.generate_new_block('other-new-block'))

        self.blockchain.replace_chain(other_chain.blocks)

        self.assertEqual(new_latest_block, self.blockchain.latest_block)
        self.assertEqual(3, self.blockchain.length)
示例#4
0
def main():
    chain = Blockchain()

    n = int(input('Enter the number of blocks to be created: '))

    for x in range(n):
        data = str(input('Enter data for block {}: '.format(x + 1)))
        chain.add_block(data)

    chain.print_blockchain()
示例#5
0
def main():
    bc = Blockchain()

    bc.add_block('foo')
    bc.add_block('bar')
    bc.add_block('baz')
    bc.add_block('qux')

    for block in bc.chain:
        print(block)
示例#6
0
def compute_wallet():
    files = os.listdir(path + '/blockchain_wallets')
    files.sort()
    for name in files:
        with open(path + '/blockchain_wallets/' + name, "r") as content:
            print('Wallets of {}:'.format(name))
            chains = read_chain(content.read())
            chain = Blockchain()
            for block in chains:
                chain.add_block(block)
            print('{}\n'.format(chain.wallets))
示例#7
0
 def test_add_new_block(self, mock_date):
     mock_date.now.return_value = datetime.fromtimestamp(1515193204)
     bc = Blockchain()
     bc.add_block("TEST DATA 1", 0, 0)
     added_block = bc.blockchain[1]
     self.assertEqual(
         "ac34557f94c70cc7faff7d25f59907dac174e2d7d776bd60f069f682f26f7626",
         added_block.previous_hash)
     self.assertEqual(1, added_block.index)
     self.assertEqual("TEST DATA 1", added_block.data)
     self.assertEqual(
         "836f04540c1972054224a4c476386664d2b5c65d57fbf04033ff5385c3886faa",
         added_block.hash)
示例#8
0
    async def test_blockchain_received__append(self):
        other_blockchain = Blockchain()
        other_blockchain.add_block(
            other_blockchain.generate_new_block('new-block'))

        ws = await self.client.ws_connect('/ws')
        ws.send_str(
            convert_dumps({
                'type': MessageTypes.RESPONSE_BLOCKCHAIN,
                'data': other_blockchain.dict()
            }))

        async for msg in ws:
            self.assertEqual(other_blockchain.latest_block,
                             self.server.blockchain.latest_block)
            return ws.close()
示例#9
0
def detect_incorrect(chain_directory):

    chains_list, filenames = block_reader.read_chains_directory(
        chain_directory)
    print("chain : status, block, transaction, amount, sender balance")
    for i in range(len(chains_list)):
        chain = chains_list[i]
        filename = filenames[i]
        block_chain = Blockchain()
        good = True

        for block in chain:
            added = block_chain.add_block(block)
            if not added:
                good = False
                if block.is_proof_ready():

                    print("{} : incorrect, {}, {}, {}, {}".format(
                        filename[:-5], block.header.index,
                        block.invalid_transactions[0][0].index,
                        block.invalid_transactions[0][0].amount,
                        block.invalid_transactions[0][1]))

                else:
                    print("{}, Not Proved, {}".format(filename[:-5],
                                                      block.header.index))

                break  # when there is an invalid block, no need to continue checking other blocks
        if good:
            print(filename[:-5] + ": correct")
示例#10
0
def compute_wallets(chain_directory):
    chains_list, filenames = block_reader.read_chains_directory(
        chain_directory)

    block_chains = []
    for chain in chains_list:
        block_chain = Blockchain()
        for block in chain:
            block_chain.add_block(block)
        block_chains.append(block_chain)

    for i in range(len(block_chains)):
        block_chain = block_chains[i]
        filename = filenames[i]
        print("------------User Balances-------------")
        print(filename)
        print(block_chain.wallets)
示例#11
0
class Node():
    def __init__(self):
        self.blockchain = Blockchain()
        self.current_block = self.blockchain.create_block()
        self.start_time = time.time()
        self.stop_flag = False

    def scan_tx(self):
        while True:
            if self.stop_flag:
                break

            elapse = time.time() - self.start_time
            if elapse > BOLCK_TIME:  # generate a new block
                self.start_time = time.time()
                self.blockchain.add_block(self.current_block)

                new_block_log(self.current_block, self.blockchain.state)

                self.current_block = self.blockchain.create_block()

            if self.blockchain.tx_pool:
                tx = self.blockchain.tx_pool.popleft()

                from_account = self.blockchain.state.get_account(
                    tx.from_address)
                tx.nonce = from_account.get_nonce()
                tx.hash = tx.hash_tx()

                # verify tx
                if from_account.get_balance() < tx.amount:
                    print("invalid tx: balance not enough")
                else:
                    self.current_block.add_transaction(tx)
                    self.blockchain.state.change_state(tx)
            else:
                time.sleep(0.3)

    def run(self):
        self.thread = threading.Thread(target=self.scan_tx)
        self.thread.start()

    def stop(self):
        self.stop_flag = True
        self.thread.join()
示例#12
0
class Node:

    def __init__(self):
        self.blockchain = Blockchain()
        self.memPool = []

    def create_block(self):
        """ Creation d'un bloc avec tx de memPool """
        if len(self.blockchain.blocks) != 0:
            self.new_block = Block(
                getHashBlock(self.blockchain.get_topBlock()))
        else:
            self.new_block = Block('00')

        for tx in self.memPool:
            self.new_block.transactionFiles.append(tx)

        self.clear_memPool()

    def add_fileTx(self, tx_pf):
        """ Ajout d'une tx dans memPool """
        self.memPool.append(tx_pf)

    def clear_memPool(self):
        """ vide memPool """
        self.memPool = []

    def mine(self):
        """ Minage, renvoie bloc finalise et pret a envoyer dans bc """
        if self.new_block:
            self.new_block.validateSelf()

    def add_blockToBlockchain(self):
        """ Ajoute un bloc a la bc """
        self.blockchain.add_block(self.new_block)

    def process(self):
        """ shortcut pour exec process crea + minage + ajout dans bc """
        self.create_block()
        self.mine()
        self.add_blockToBlockchain()
def test_broadcasting_block():
    timestamp = datetime.utcfromtimestamp(0)
    node_id = uuid4()
    w1 = Wallet(test=True)
    w2 = Wallet(test=True)

    chain1 = Blockchain(w1.address, node_id, difficulty=1, is_test=True)
    chain2 = Blockchain(w2.address, node_id, difficulty=1, is_test=True)

    chain2.chain = chain1.chain
    assert chain1.chain == chain2.chain

    details = Details(
        sender=w1.address,
        recipient=w2.address,
        nonce=0,
        amount=0.5,
        timestamp=timestamp,
        public_key=w1.public_key.hex(),
    )
    transaction_1 = w1.sign_transaction(details)

    assert Verification.verify_chain(chain1.chain)
    b = chain1.mine_block()

    result, _ = chain2.add_block(b)
    assert result

    assert Verification.verify_chain(chain1.chain)
    assert Verification.verify_chain(chain2.chain)

    chain1.add_transaction(transaction_1, is_receiving=True)
    chain1.mine_block()
    chain2.add_block(chain1.last_block)

    assert Verification.verify_chain(chain1.chain)
    assert Verification.verify_chain(chain2.chain)

    assert chain1.chain == chain2.chain
def create_chain_from_dump(chain_dump):
    blockchain = Blockchain()
    for idx, block_data in enumerate(chain_dump):
        block = Block(block_data["index"], block_data["transactions"],
                      block_data["timestamp"], block_data["previous_hash"])
        proof = block_data['hash']
        if idx > 0:
            added = blockchain.add_block(block, proof)
            if not added:
                raise Exception("The chain dump is tampered!!")
        else:  # the block is a genesis block, no verification needed
            blockchain.chain.append(block)
    return blockchain
示例#15
0
def verificar_agregar_block():
    block_data = request.get_json()
    block = Block(block_data["index"], block_data["transactions"],
                  block_data["timestamp"], block_data["previous_hash"],
                  block_data["nonce"])

    prueba = block_data['hash']
    adicional = Blockchain.add_block(block, prueba)

    if not adicional:
        return "El bloque fue descartado por el nodo", 400

    return "Bloque agregado a la cadena", 201
示例#16
0
class MinerNode:
    blockchain: Blockchain

    public_key: str
    private_key: str

    def __init__(self):
        self.blockchain = Blockchain()

        (pub, priv) = rsa.newkeys(512)
        self.public_key = pub
        self.private_key = priv

    def sign(self, block: Block):
        block.miner_signature = rsa.sign(block.miner_signature_bytes(),
                                         self.private_key, 'SHA-256')

    def add_block(self, transaction: Transaction):
        new_block = self.blockchain.create_new_block(transaction)
        self.sign(new_block)
        self.blockchain.add_block(new_block)

    def display(self):
        self.blockchain.display()

    def increment_fifteen(self):
        print("Incrementing transaction 15 amount by 10.")
        self.blockchain.increment_fifteen()

    def is_chain_valid(self) -> bool:
        return self.blockchain.is_chain_valid()

    def print_customer_three(self, customer_three: Customer):
        print("Print Customer 3 Transactions:")
        self.blockchain.print_customer_three(customer_three)

    def print_merchant_two(self, merchant_two: Merchant):
        print("Print Merchant 2 Transactions:")
        self.blockchain.print_merchant_two(merchant_two)
示例#17
0
def create_chain_from_dump(chain_dump):
    generated_blockchain = Blockchain()
    generated_blockchain.create_genesis_block()
    for idx, block_data in enumerate(chain_dump):
        if idx == 0:
            continue  # skip genesis block
        block = Block(block_data["key"], block_data["transactions"],
                      block_data["timestamp"], block_data["previous_hash"],
                      block_data["nonce"])
        proof = block_data['hash']
        added = generated_blockchain.add_block(block, proof)
        if not added:
            raise Exception("The chain dump is tampered!!")
    return generated_blockchain
示例#18
0
def crear_chain_desde_papelera(chain_papelera):
    generar_blockchain = Blockchain()
    generar_blockchain.create_genesis_block()
    for idx, block_data in enumerate(chain_papelera):
        if idx == 0:
            continue  # omitir el bloque genesis
        block = Block(block_data["index"], block_data["transactions"],
                      block_data["timestamp"], block_data["previous_hash"],
                      block_data["nonce"])
        prueba = block_data['hash']
        adicional = generar_blockchain.add_block(block, prueba)
        if not adicional:
            raise Exception("la papelera de la cade esta manipulada !")
    return generar_blockchain
def create_chain_from_dump(chain_dump):
    gen_blockchain = Blockchain()
    gen_blockchain.create_gen()
    for idx, block_data in enumerate(chain_dump):
        if idx == 0:
            continue
        block = Block(block_data['index'], block_data['trans'],
                      block_data['time'], block_data['prev_hash'],
                      block_data['nonce'])
        proof = block_data['hash']
        added = gen_blockchain.add_block(block, proof)
        if not added:
            raise Exception("The chain dump is tampered.")
    return gen_blockchain
示例#20
0
def incorrect_block():
    files = os.listdir(path + '/blockchain_incorrect/')
    files.sort()
    for name in files:
        with open(path + '/blockchain_incorrect/' + name, 'r') as content:
            chains = read_chain(content.read())
            chain = Blockchain()
            valid = True
            for block in chains:
                if block.is_proof_ready():
                    if check_transactions(chain, block, name):
                        chain.add_block(block)
                    else:
                        valid = False
                        break
                else:
                    print(
                        '{} is incorrect: block index is {}, this block has not been proved!'
                        .format(name, block.header.index))
                    valid = False
                    break
            if valid:
                print('{} is correct!'.format(name))
示例#21
0
def create_chain_from_dump(dump):
    """
    Construct chain from json dump.
    """
    new_blockchain = Blockchain()
    for idx, data in enumerate(dump):
        if idx == 0:
            continue
        block = Block(data['index'], data['transactions'], data['timestamp'],
                      data['pred_hash'], data['nonce'])
        proof = data['hash']
        added = new_blockchain.add_block(block, proof)
        if not added:
            raise Exception('The chain dump was tampered!')
    return new_blockchain
示例#22
0
class Server(object):

    def __init__(self):

        self.app = Sanic()
        self.blockchain = Blockchain()
        self.sockets = []
        self.app.add_route(self.blocks, '/blocks', methods=['GET'])
        self.app.add_route(self.mine_block, '/mineBlock', methods=['POST'])
        self.app.add_route(self.peers, '/peers', methods=['GET'])
        self.app.add_route(self.add_peer, '/addPeer', methods=['POST'])
        self.app.add_websocket_route(self.p2p_handler, '/')

    async def blocks(self, request):
        return json(self.blockchain.blocks)

    async def mine_block(self, request):

        try:
            newBlock = self.blockchain.generate_next_block(request.json["data"])
        except KeyError as e:
            return json({"status": False, "message": "pass value in data key"})
        self.blockchain.add_block(newBlock)
        await self.broadcast(self.response_latest_msg())
        return json(newBlock)

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

    async def add_peer(self, request):
        import asyncio
        asyncio.ensure_future(self.connect_to_peers([request.json["peer"]]),
                                             loop=asyncio.get_event_loop())
        return json({"status": True})

    async def connect_to_peers(self, newPeers):
        for peer in newPeers:
            logger.info(peer)
            try:
                ws = await websockets.connect(peer)

                await self.init_connection(ws)
            except Exception as e:
                logger.info(str(e))

    # initP2PServer WebSocket server
    async def p2p_handler(self, request, ws):
        logger.info('listening websocket p2p port on: %d' % port)


        try:
            await self.init_connection(ws)
        except (ConnectionClosed):
            await self.connection_closed(ws)

    async def connection_closed(self, ws):

        logger.critical("connection failed to peer")
        self.sockets.remove(ws)

    async def init_connection(self, ws):

        self.sockets.append(ws)
        await ws.send(JSON.dumps(self.query_chain_length_msg()))

        while True:
            await self.init_message_handler(ws)

    async def init_message_handler(self, ws):
        data = await ws.recv()
        message = JSON.loads(data)
        logger.info('Received message: {}'.format(data))

        await {
            QUERY_LATEST: self.send_latest_msg,
            QUERY_ALL: self.send_chain_msg,
            RESPONSE_BLOCKCHAIN: self.handle_blockchain_response
        }[message["type"]](ws, message)

    async def send_latest_msg(self, ws, *args):
        await ws.send(JSON.dumps(self.response_latest_msg()))

    async def send_chain_msg(self, ws, *args):

        await ws.send(JSON.dumps(self.response_chain_msg()))

    def response_chain_msg(self):
        return {
            'type': RESPONSE_BLOCKCHAIN,
            'data': JSON.dumps([block.dict() for block in self.blockchain.blocks])
        }

    def response_latest_msg(self):

        return {
            'type': RESPONSE_BLOCKCHAIN,
            'data': JSON.dumps([self.blockchain.get_latest_block().dict()])
        }

    async def handle_blockchain_response(self, ws, message):

        received_blocks = sorted(JSON.loads(message["data"]), key=lambda k: k['index'])
        logger.info(received_blocks)
        latest_block_received = received_blocks[-1]
        latest_block_held = self.blockchain.get_latest_block()
        if latest_block_received["index"] > latest_block_held.index:
            logger.info('blockchain possibly behind. We got: ' + str(latest_block_held.index)
                  + ' Peer got: ' + str(latest_block_received["index"]))
            if latest_block_held.hash == latest_block_received["previous_hash"]:
                logger.info("We can append the received block to our chain")

                self.blockchain.blocks.append(Block(**latest_block_received))
                await self.broadcast(self.response_latest_msg())
            elif len(received_blocks) == 1:
                logger.info("We have to query the chain from our peer")
                await self.broadcast(self.query_all_msg())
            else:
                logger.info("Received blockchain is longer than current blockchain")
                await self.replace_chain(received_blocks)
        else:
            logger.info('received blockchain is not longer than current blockchain. Do nothing')

    async def replace_chain(self, newBlocks):

        try:

            if self.blockchain.is_valid_chain(newBlocks) and len(newBlocks) > len(self.blockchain.blocks):
                logger.info('Received blockchain is valid. Replacing current blockchain with '
                            'received blockchain')
                self.blockchain.blocks = [Block(**block) for block in newBlocks]
                await self.broadcast(self.response_latest_msg())
            else:
                logger.info('Received blockchain invalid')
        except Exception as e:
            logger.info("Error in replace chain" + str(e))



    def query_chain_length_msg(self):

        return {'type': QUERY_LATEST}

    def query_all_msg(self):

        return {'type': QUERY_ALL}

    async def broadcast(self, message):

        for socket in self.sockets:
            logger.info(socket)
            await socket.send(JSON.dumps(message))
示例#23
0
from blockchain import Blockchain

transaction1 = {"Sender": "Arman", "Receiver": "Hale", "Amount": 100}
transaction2 = {"Sender": "Hale", "Receiver": "Ozgur", "Amount": 200}
transaction3 = {"Sender": "Ozgur", "Receiver": "Arman", "Amount": 300}

new_blockchain = Blockchain()
new_blockchain.add_block(transaction1)
new_blockchain.add_block(transaction2)
new_blockchain.add_block(transaction3)
new_blockchain.print_blocks()
示例#24
0
 def test_add_block(self):
     chain = Blockchain()
     chain.add_block(self.get_block("some message"))
     self.assertEqual(1, len(chain.blocks))
     self.assertEqual("some message", chain.blocks[-1].messages[0].data)
示例#25
0
文件: review.py 项目: dpuleo3/python
from blockchain import Blockchain

block_one_transactions = {"sender":"Alice", "receiver": "Bob", "amount":"50"}
block_two_transactions = {"sender": "Bob", "receiver":"Cole", "amount":"25"}
block_three_transactions = {"sender":"Alice", "receiver":"Cole", "amount":"35"}
fake_transactions = {"sender": "Bob", "receiver":"Cole, Alice", "amount":"25"}

local_blockchain = Blockchain()
local_blockchain.print_blocks()

local_blockchain.add_block(block_one_transactions)
local_blockchain.add_block(block_two_transactions)
local_blockchain.add_block(block_three_transactions)
local_blockchain.print_blocks()
local_blockchain.chain[2].transactions = fake_transactions
local_blockchain.validate_chain()
示例#26
0
class BlockchainNode(object):

    #socket timeout in seconds
    CONNECTION_LISTEN_TIMEOUT = 5
    # the number of timesouts that need to occur before we ask our peers about
    # the blockchain
    SYNC_BLOCKCHAIN_TIMEOUTS = 10

    def __init__(self, port, peers):
        self.serverhostname = None
        self.serverport = None
        self.id = None
        self.serversock = self.__init_server_socket(port)
        self.blockchain = Blockchain(self.id)
        self.peers = {}
        # map of message types to handlder functions
        self.handlers = {
            BlockchainMessage.PEER_INIT: self.__handle_peer_init_msg,
            BlockchainMessage.PEER_REMV: self.__handle_peer_remv_msg,
            BlockchainMessage.GET_BLOCKCHAIN: self.__handle_get_blockchain_msg,
            BlockchainMessage.FULL_BLOCKCHAIN:
            self.__handle_full_blockchain_msg,
            BlockchainMessage.NEW_BLOCK: self.__handle_new_block_msg,
            BlockchainMessage.GET_LATEST_BLOCK:
            self.__handle_get_latest_block_msg,
            BlockchainMessage.LATEST_BLOCK: self.__handle_latest_block_msg,
            BlockchainMessage.GET_MAGIC_NUM: self.__handle_get_magic_num_msg,
            BlockchainMessage.NEW_MAGIC_NUM: self.__handle_new_magic_num_msg
        }
        self.shutdown = False
        self.sync_count = 0

        self.lock = threading.RLock()

        # fire up the node
        self.start(peers)

    # starts the blockchainnode's main server listening loop, and spawing the
    # mining thread as well
    # params:
    #   -possiblepeers: a list of peers to establish on startup (these are passed
    #   in from the command line)
    def start(self, possiblepeers):

        if len(possiblepeers) > 0:
            logging.info("establishing peers from passed in list")
            self.peers = self.__establish_peers(possiblepeers)
        else:
            self.blockchain.set_magic_number()

        logging.info("BLOCKCHAIN NODE STARTED - %s:%d" %\
            (self.serverhostname, self.serverport))
        while not self.shutdown:
            try:
                logging.debug("listening for peer connections")
                clientsock, clientaddr = self.serversock.accept()
                clientsock.settimeout(None)
                peerconn_thread = threading.Thread(target = \
                    self.__handlepeerconnectandrecv, args = [ clientsock ])
                peerconn_thread.start()
            except socket.timeout:
                self.__maintain_bc_and_mine()
                self.lock.acquire()
                self.sync_count = (self.sync_count + 1) % 10
                self.lock.release()
                continue
            except KeyboardInterrupt:
                logging.debug("ctrl+c pressed")
                self.shutdown = True
                continue

        logging.debug("peer connection listening loop ending")
        logging.debug("closing server socket")
        self.serversock.close()
        logging.info("notifying peers to remove me from their peer list")
        self.__broadcast_to_peers(BlockchainMessage.PEER_REMV)

    # initializes the server socket for the blockchainnode
    # params:
    #   -port: the port on which the server socket should listen
    #   -queue_size: the number of connections that will be queued
    #   (not socket.accept()'ed) before refusing connections
    def __init_server_socket(self, port, queue_size=5):
        logging.debug("initializing server socket")
        # IPv4 (AF_INET) TCP (SOCK_STREAM) socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # allow for the socket to be reclaimed before it's TIMEWAIT
        # period is finished
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind(("", port))
        sock.settimeout(self.CONNECTION_LISTEN_TIMEOUT)
        addrinfo = socket.getaddrinfo("", port, socket.AF_INET,
                                      socket.SOCK_STREAM)
        sockinfo = addrinfo[0]
        self.serverhostname = sockinfo[4][0]
        self.serverport = sockinfo[4][1]
        self.id = self.serverhostname + ":" + str(self.serverport)
        sock.listen(queue_size)
        return sock

    # called when the socket times out in the main loop - this checks the blockchain
    # sends out any messages when information is needed and attempts to mine a block
    def __maintain_bc_and_mine(self):
        self.lock.acquire()
        logging.debug("number of peers: %d" % len(self.peers))
        logging.debug("sync count = %d" % self.sync_count)
        if self.blockchain.magic_num == None:
            self.__broadcast_to_peers(BlockchainMessage.GET_MAGIC_NUM)
        else:
            if len(self.blockchain.blocks) == 0 and len(self.peers) > 0:
                logging.debug(
                    "blockchain is empty but I have peers - request the blockchain"
                )
                self.__broadcast_to_peers(BlockchainMessage.GET_BLOCKCHAIN)
            elif self.sync_count == 9:
                logging.debug("10 timeeouts - request the latest block")
                self.__broadcast_to_peers(BlockchainMessage.GET_LATEST_BLOCK)

            logging.debug("current blockchain length %d" %
                          len(self.blockchain.blocks))
            logging.debug("current blockchain: %s" % self.blockchain.blocks)
            newblock = self.blockchain.mine_block()
            if newblock != None:
                logging.info("new block mined:%s" % newblock)
                self.__broadcast_to_peers(BlockchainMessage.NEW_BLOCK,
                                          newblock)
        self.lock.release()

    # handles an incoming connection from another blockchainnode
    # params:
    #   -clientsock: the client socket extracted from the accepted connection
    def __handlepeerconnectandrecv(self, clientsock):
        host, port = clientsock.getpeername()
        logging.info("handling peer connection from: %s:%d" % (host, port))
        try:
            raw_msg = clientsock.recv(1024)
            length = struct.unpack_from("!I", raw_msg[:4])[0]
            bytes_recvd = len(raw_msg[4:])
            logging.debug("length: %s, bytes_recvd: %d" %
                          (length, bytes_recvd))
            while bytes_recvd < length:
                chunk = clientsock.recv(1024)
                raw_msg += chunk
                bytes_recvd += len(chunk)
                logging.debug("length: %s, bytes_recvd: %d" %
                              (length, bytes_recvd))

            msg = pickle.loads(raw_msg[4:])

            logging.info("received message: %s", repr(msg))

            if msg.msg_type == BlockchainMessage.PEER_INIT or \
            msg.msg_type == BlockchainMessage.PEER_REMV:
                self.handlers[msg.msg_type](msg)
            else:
                peerid = msg.senderid
                self.lock.acquire()
                peer = None
                if self.peers.has_key(peerid):
                    peer = self.peers[peerid]
                    self.lock.release()
                    if self.handlers.has_key(msg.msg_type):
                        self.handlers[msg.msg_type](peer, msg)
                    else:
                        logging.info("received unknown message type: " \
                            "%s - doing nothing" % (str(msg.msg_type)))
                else:
                    logging.info(
                        "peerid not an established peer - doing nothing")
                    self.lock.release()
        except Exception:
            logging.error(
                "An exception occured handling connection/receving message")
            raise
        finally:
            logging.debug("cleaning up client socket")
            clientsock.close()

    # handles the PEER_INIT message type
    # params:
    #   -message: the messsage to process
    def __handle_peer_init_msg(self, message):
        logging.debug("processing PEER_INIT message")
        peer = self.__peer_from_peerid(message.senderid)

        if not self.peers.has_key(peer.id):
            logging.info("storing: %s as established peer" % repr(peer))
            self.lock.acquire()
            self.peers[peer.id] = peer
            self.lock.release()
        else:
            logging.debug("already established this peer: %s, ignoring" %
                          repr(peer))

    # handles PEER_REMV message type
    # params:
    #   -message: the message to process
    def __handle_peer_remv_msg(self, message):
        peeridtoremove = message.senderid
        self.lock.acquire()
        if self.peers.has_key(peeridtoremove):
            logging.info("removing peer: %s" % (self.peers[peeridtoremove]))
            del self.peers[peeridtoremove]
        else:
            logging.debug(
                "received PEER_REMV from peer not in my list - ignoring")
        self.lock.release()

    # handles GET_BLOCKCHAIN message type
    # params:
    #   -peer: the peer who sent the message
    #   -message: the message to process
    def __handle_get_blockchain_msg(self, peer, message):
        logging.info("handling GET_BLOCKCHAIN message")
        self.lock.acquire()
        if len(self.blockchain.blocks) > 0:
            peer.send_msg(self.id, BlockchainMessage.FULL_BLOCKCHAIN,
                          self.blockchain.blocks)
        else:
            logging.debug("my blockchain is empty - ignoring message")
        self.lock.release()

    # handles FULL_BLOCKCHAIN message type
    # params:
    #   -peer: the peer who sent the message
    #   -message: the message to process
    def __handle_full_blockchain_msg(self, peer, message):
        logging.info("handling FULL_BLOCKCHAIN message")
        listofblocks = message.data
        self.lock.acquire()
        self.blockchain.examine_peer_blockchain(listofblocks)
        self.lock.release()

    # handles NEW_BLOCK message type
    # params:
    #   -peer: the peer who sent the message
    #   -message: the message to process
    def __handle_new_block_msg(self, peer, message):
        logging.info("handling NEW_BLOCK message")
        newblock = message.data
        self.lock.acquire()
        if self.blockchain.validate_newblock(newblock):
            logging.info("new block is valid - adding")
            self.blockchain.add_block(newblock)
        else:
            logging.info(
                "new block received is not valid - request block chain from peers"
            )
            self.__broadcast_to_peers(BlockchainMessage.GET_BLOCKCHAIN)
        self.lock.release()

    #handles GET_LATEST_BLOCK message type
    #params:
    #   -peer: the peer who sent the message
    #   -message: the message to process
    def __handle_get_latest_block_msg(self, peer, message):
        logging.info("handling GET_LATEST_BLOCK message")
        self.lock.acquire()
        latest_block = self.blockchain.get_latest_block()
        if latest_block == None:
            logging.debug("no latest block to send - ignoring")
        else:
            peer.send_msg(self.id, BlockchainMessage.LATEST_BLOCK,
                          latest_block)
        self.lock.release()

    #handles LATEST_BLOCK message type
    #params:
    #   -peer: the peer who sent the message
    #   -message: the message to process
    def __handle_latest_block_msg(self, peer, message):
        logging.info("handling LATEST_BLOCK message")
        peer_latest_block = message.data
        self.lock.acquire()
        if self.blockchain.latest_block_matches(peer_latest_block):
            logging.info("latest block matches - I'm up to date")
        else:
            logging.info(
                "my latest block didn't match peers latest - requesting the blockchain"
            )
            self.__broadcast_to_peers(BlockchainMessage.GET_BLOCKCHAIN)
        self.lock.release()

    # handles GET_MAGIC_NUM message type
    # params:
    #   -peer: the peer who sent the message
    #   -message: the message to process
    def __handle_get_magic_num_msg(self, peer, message):
        logging.info("handling GET_MAGIC_NUM message")
        self.lock.acquire()
        if self.blockchain.magic_num != None:
            peer.send_msg(self.id, BlockchainMessage.NEW_MAGIC_NUM,
                          self.blockchain.magic_num)
        else:
            logging.debug("my magic num isn't set - ignoring message")
        self.lock.release()

    # handles NEW_MAGIC_NUM message type
    # params:
    #   -peer: the peer who sent the message
    #   -message: the message to process
    def __handle_new_magic_num_msg(self, peer, message):
        logging.info("handling NEW_MAGIC_NUM message")
        magic_num = message.data
        self.lock.acquire()
        self.blockchain.set_magic_number(magic_num)
        self.lock.release()

    # attemps to establish a connection and store references to peers
    # params:
    #   -peerlist: command line supplied list of peers, each peer is in the
    #   form <host>:<port>
    # returns:
    #   -a dictionary of id's to BlockchainPeer objects
    def __establish_peers(self, peerlist):
        established_peers = {}
        for peer in peerlist:
            peer = self.__peer_from_peerid(peer)
            if peer != None:
                try:
                    peer.send_msg(self.id, BlockchainMessage.PEER_INIT)
                    established_peers[peer.id] = peer
                except socket.error as e:
                    logging.error(
                        "socket error sending message to potential peer: %s" %
                        e)
                    logging.info(
                        "check the validity of peers passed in from the command line"
                    )
                    sys.exit(1)
            else:
                raise AttributeError(
                    "invalid peer format, expecting host:port")

        return established_peers

    # creates a BlockchainPeer object from an id (ip:port)
    # params:
    #   -peerid: the string peerid to be converted to a BlockchainPeer object
    # returns:
    #   -a BlockchainPeer object if peerid is valid, otherwise None
    def __peer_from_peerid(self, peerid):
        if string.count(peerid, ":") == 1:
            peer_split = string.split(peerid, ":", 1)
            peer_host = peer_split[0]
            peer_port = int(peer_split[1])
            return BlockchainPeer(peer_host, peer_port)
        return None

    # sends a message to all known peers
    # params:
    #   -msg_type: the type of message to send
    #   -data: the data to include in the message
    def __broadcast_to_peers(self, msg_type, data=None):
        self.lock.acquire()
        for peer in self.peers.values():
            peer.send_msg(self.id, msg_type, data)
        self.lock.release()
示例#27
0
class Server(object):
    def __init__(self, loop, initial_peers=None):
        self.blockchain = Blockchain()
        self.peer_connections = []
        self.session = None
        self.app = web.Application(loop=loop)
        self.loop = loop

        if initial_peers:
            self.connect_to_peers(initial_peers)

        self.app.router.add_get('/blocks', self.blocks)
        self.app.router.add_post('/mineBlock', self.mine_block)
        self.app.router.add_post('/addPeer', self.add_peer)
        self.app.router.add_get('/ws', self.ws_handler)

    async def connect_to_peers(self, peers: List[str]):
        if not self.session:
            self.session = aiohttp.ClientSession(loop=self.loop)

        for peer in peers:
            connection = await self.session.ws_connect(peer)
            self.peer_connections.append(connection)

    async def broadcast(self, msg: str):
        for peer_connection in self.peer_connections:
            print('broadcast')
            print(msg)
            await peer_connection.send_str(msg)

    async def blocks(self, request):
        return web.Response(text=self.blockchain.json(),
                            content_type='application/json')

    async def mine_block(self, request):
        data = convert_loads((await request.read()).decode('utf-8'))['data']
        new_block = self.blockchain.generate_new_block(data)
        self.blockchain.add_block(new_block)
        await self.broadcast(self.get_response_latest_msg())
        print('block added ', new_block.json())
        return web.Response(text=new_block.json(),
                            content_type='application/json')

    async def add_peer(self, request):
        peer = convert_loads((await request.read()).decode('utf-8'))['peer']
        await self.connect_to_peers([peer])
        return web.Response(text='', content_type='application/json')

    async def handle_query_all(self, ws):
        ws.send_str(
            convert_dumps({
                'type': MessageTypes.RESPONSE_BLOCKCHAIN,
                'data': self.blockchain.dict()
            }))

    async def handle_query_latest(self, ws):
        ws.send_str(
            convert_dumps({
                'type': MessageTypes.RESPONSE_BLOCKCHAIN,
                'data': self.blockchain.latest_block.dict()
            }))

    async def handle_response_blockchain(self, ws, msg):
        received_blocks = convert_loads(msg.data)['data']
        latest_block_received = received_blocks[-1]

        if latest_block_received['index'] > self.blockchain.latest_block.index:
            print('blockchain possibly behind. We got: {} Peer got: {}'.format(
                self.blockchain.length, len(received_blocks)))

            if self.blockchain.latest_block.hash == latest_block_received[
                    'previous_hash']:
                print('We can append received block to our chain')
                self.blockchain.add_block(Block(**latest_block_received))
                await self.broadcast(self.get_response_latest_msg())
            elif len(received_blocks) == 1:
                print('We have to query the chain from our peer')
                await self.broadcast(self.get_query_all_msg())
            else:
                print('Received blockchain is longer than current blockchain')
                self.blockchain.replace_chain(received_blocks)
                await self.broadcast(self.get_response_latest_msg())
            await ws.send_str(msg.data)
        else:
            await ws.send_str(msg.data)

    def get_response_latest_msg(self) -> str:
        return convert_dumps({
            'type': MessageTypes.RESPONSE_BLOCKCHAIN,
            'data': [self.blockchain.latest_block.dict()]
        })

    def get_query_all_msg(self) -> str:
        return convert_dumps({'type': MessageTypes.QUERY_ALL})

    async def ws_handler(self, request):
        ws = web.WebSocketResponse()
        await ws.prepare(request)

        async for msg in ws:
            if msg.type == aiohttp.WSMsgType.TEXT:
                data = convert_loads(msg.data)

                if 'type' not in data:
                    raise ValueError('Wrong message format')

                if data['type'] == MessageTypes.QUERY_LATEST:
                    await self.handle_query_latest(ws)
                elif data['type'] == MessageTypes.QUERY_ALL:
                    await self.handle_query_all(ws)
                elif data['type'] == MessageTypes.RESPONSE_BLOCKCHAIN:
                    await self.handle_response_blockchain(ws, msg)
                else:
                    raise ValueError('Unknown message type')
            elif msg.type == aiohttp.WSMsgType.ERROR:
                print('ws connection closed with exception ', ws.exception())

        return ws
示例#28
0
from blockchain import Blockchain

new_transactions = [{'amount': '30', 'sender':'alice', 'receiver':'bob'},
               	{'amount': '55', 'sender':'bob', 'receiver':'alice'}]

my_blockchain = Blockchain()
my_blockchain.add_block(new_transactions)
my_blockchain.print_blocks()

my_blockchain.chain[1].transactions = "fake_transactions"
my_blockchain.validate_chain()
示例#29
0
B2.add_message(Message("Fourth message"))
B2.add_message(Message("Fifth message", "Eve", "Steve"))
B2.seal()

B3 = Block()
B3.add_message(Message("Sixth message"))
B3.add_message(Message("Seventh Son of a Seventh Son is Iron Maiden's best album", "Me", "Everyone"))
B3.seal()

B4 = Block()
B4.add_message(Message("Eighth message", "Bob", "Charlie"))
B4.add_message(Message("Ninth message", "Charlie", "Daniels"))
B4.add_message(Message("Tenth message", "Charlie", "Brown"))

chain = Blockchain()
chain.add_block(B1)
chain.add_block(B2)
chain.add_block(B3)
chain.add_block(B4)

print("Validating blockchain...")
chain.validate()   # all messages and inter-message links are valid, and all blocks and inter-block links are valid

print("Serializing...")
pickle.dump(chain, open('chain.p', 'wb'))

print("Deserializing and validating...")
chain2 = pickle.load(open('chain.p', 'rb'))
chain2.validate()

print("Serializing for tampering...")
示例#30
0
import random
import time

from blockchain import Block, Blockchain, Transaction

USERS = ['Alice', 'James', 'Smith', 'David', 'Adams', 'Isaac', 'Lewis']

SLEEP_TIME = 0

if __name__ == '__main__':

    chain = Blockchain()

    for _ in range(random.randint(1, 5)):
        block = Block()

        for _ in range(random.randint(1, 3)):
            sender, receiver = random.sample(USERS, k=2)
            transaction = Transaction(sender=sender,
                                      receiver=receiver,
                                      value=random.randint(10, 100))
            block.add_transaction(transaction)
            time.sleep(SLEEP_TIME)
        chain.add_block(block)
        print(chain)
        time.sleep(SLEEP_TIME)
示例#31
0
from block import Block
from blockchain import Blockchain
from config import *
import random
import json

bc = Blockchain()

bc.add_block(Block(index=1, data_dict={'token': random.randint(0, 1000)}))

bc.add_block(Block(index=2, data_dict={'token': random.randint(0, 1000)}))

bc.add_block(Block(index=3, data_dict={'token': random.randint(0, 1000)}))

print("Is valid blockchain -> " + str(bc.chain_validator()))

for c in bc.chain:
    print(c.info())
示例#32
0
class TestBlockchain(unittest.TestCase):
    def setUp(self):
        self.bc = Blockchain()
        self.bc2 = Blockchain()

    def test_starts_with_genesis_block(self):
        self.assertEqual(self.bc.chain[0].block_hash,
                         Block.genesis().block_hash)

    def test_add_new_block(self):
        data = 'foo'
        self.bc.add_block(data)
        self.assertEqual(self.bc.chain[-1].data, data)

    def test_validates_a_valid_chain(self):
        self.bc2.add_block('foo')
        self.assertTrue(self.bc.is_vaild_chain(self.bc2.chain))
        self.assertTrue(self.bc.is_vaild_chain_from_json(self.bc2.to_json()))

    def test_bad_genesis_block_is_invalid(self):
        self.bc2.chain[0].data = 'bad data'

        self.assertFalse(self.bc.is_vaild_chain(self.bc2.chain))
        self.assertFalse(self.bc.is_vaild_chain_from_json(self.bc2.to_json()))

    def test_bad_block_is_invalid(self):
        self.bc2.add_block('foo')
        self.bc2.chain[1].data = 'bad data'

        self.assertFalse(self.bc.is_vaild_chain(self.bc2.chain))
        self.assertFalse(self.bc.is_vaild_chain_from_json(self.bc2.to_json()))

    def test_replace_the_chain_with_a_valid_chain(self):
        self.bc2.add_block('bar')
        self.bc.replace_chain(self.bc2.chain)
        self.assertEqual(self.bc.chain, self.bc2.chain)

    def test_replace_the_chain_with_a_valid_chain_json(self):
        self.bc2.add_block('bar')
        self.bc.replace_chain_from_json(self.bc2.to_json())
        self.assertEqual(self.bc.to_json(), self.bc2.to_json())

    def test_not_replace_with_less_chain(self):
        self.bc.add_block('foo')
        self.bc.replace_chain(self.bc2.chain)

        self.assertNotEqual(self.bc.chain, self.bc2.chain)

    def test_not_replace_with_less_chain_json(self):
        self.bc.add_block('foo')
        self.bc.replace_chain_from_json(self.bc2.to_json())

        self.assertNotEqual(self.bc.to_json(), self.bc2.to_json())