Ejemplo n.º 1
0
def test1():
    """
    tests wallets without p2p network,
    the test is using common database
    for all wallets
    """
    logger = Logger('test1')
    logger.info('Test 1 starts')
    block_chain_db = BlockChainDB(logger)

    # creates two wallets in the system
    wallet1 = Wallet.new_wallet(block_chain_db, logger)
    wallet2 = Wallet.new_wallet(block_chain_db, logger)

    # check that their initial value is 0
    assert wallet1.balance == 0
    assert wallet2.balance == 0

    # creates the miner in the system
    wallet3 = Wallet.new_wallet(block_chain_db, logger)
    miner = Miner(wallet3)

    # mine the genesis block and check the miner balance
    miner.mine()
    first_balance = miner.wallet.get_balance()
    assert first_balance > 0

    # transfer from the miner to wallet1
    # and mine the new block
    assert miner.wallet.create_transaction(miner.wallet.balance,
                                           wallet1.address)
    miner.mine()

    # check the new balances
    assert wallet1.get_balance() == first_balance
    second_balance = miner.wallet.get_balance()
    assert second_balance > 0

    # creates new transactions from the miner
    # and wallet1 to wallet2 and mine the new block
    wallet1.create_transaction(wallet1.get_balance(), wallet2.address)
    miner.wallet.create_transaction(second_balance, wallet2.address)
    miner.mine()

    # check the new balances
    assert wallet2.get_balance() == (first_balance + second_balance)
    assert miner.wallet.get_balance() > 0

    # create new transaction that demands change
    # and mine the new block
    wallet2.create_transaction(first_balance + 1, wallet1.address)
    miner.mine()

    # check the balances
    assert wallet2.get_balance() == second_balance - 1
    assert not wallet2.create_transaction(second_balance, wallet1.address)

    logger.info('Finish successfully test 1')
    block_chain_db.close_connection()
Ejemplo n.º 2
0
 def _run(self, base_path):
     m = Miner([
         detection.WordpressDetector(),
         detection.Drupal7Detector(),
         detection.Drupal8Detector(),
     ])
     print(JSONEncoder().encode(m.mine(base_path)))
Ejemplo n.º 3
0
def mine(mineride, chain):
    global timetaken
    global blockarray
    global miner

    miner = Miner(chain)
    minerID = miner.publickey.to_string().hex()
    print ("Miner " +str(minerID)+" mining")
    starttime = time.time()
    block = miner.mine(chain)
    elapsedtime = time.time() - starttime
    timetaken.update({minerID:elapsedtime})
    blockarray.append(block)

    return block
Ejemplo n.º 4
0
def miner_thread(sock, User):
    miner = Miner(redis_connection, User)

    while True:
        print("trying to mine")
        block = miner.mine()
        if block == None:
            redis_connection.set("StopMining", "No")
            print("Puzzle solved by other node")
            continue

        print("have a block, broadcasting")
        #funcs.send_message(sock, block.to_redis())
        #funcs.send_object(block)
        serial = pickle.dumps(block)
        print("Serialized block = ")
        print(serial)
        print(json.dumps(block.to_json(), indent=4))
        #print(json.dumps(bl.to_json(),indent = 4))
        funcs.send_message(sock, "Block")
        funcs.send_bytes(sock, serial)
Ejemplo n.º 5
0
def start_mining(block_queue, transaction_queue, public_key, private_key):
    blockchain = BlockChain([args.ip_other])
    miner = Miner(blockchain, public_key)
    miner_status = False  # Checks if miner is ready to send

    # Variables for double-spending attack:
    start_attack = False
    announced_attack = False
    cease_attacks = False
    unsent_bad_tx = False
    sent_tx = False
    ignore_transactions = []
    private_fork = []
    skip_mine_count = 0
    trigger_block = 3
    trigger_block_hash = ""
    mine_private_blocks = False
    private_last_hash = ""
    original_blocks = []

    while True:
        blockchain.resolve()
        if args.attacker and start_attack:
            # Make sure new blocks don't include the bad_tx from attacker
            merkletree, ledger = miner.create_merkle(
                transaction_queue, tx_to_ignore=ignore_transactions)
        else:  # Not attacker or is an attacker and not attacking
            merkletree, ledger = miner.create_merkle(transaction_queue)

        if not cease_attacks:
            if args.attacker:
                # 'and sent_tx' ensures attacker only attacks at least one block after bad_tx is sent
                start_attack = len(
                    blockchain.cleaned_keys) > trigger_block and sent_tx
            else:
                start_attack = len(blockchain.cleaned_keys) > trigger_block

            # Send a bad transaction after trigger_block number of blocks in chain
            unsent_bad_tx = len(blockchain.cleaned_keys) == trigger_block

            # This if statement should only be True once
            # Send transaction with intent to double spend
            if args.attacker and unsent_bad_tx:
                bad_tx = Transaction(public_key, SigningKey.generate().get_verifying_key(), 50,
                                     "give me the goods", sender_pk=private_key).to_json().encode()
                print("Sending transaction with intent to double-spend...")
                print("Transaction sent.")
                ignore_transactions.append(bad_tx)
                unsent_bad_tx = False
                sent_tx = True

        while True:
            miner_status = False
            # This if statement should only be True once
            # Start of attack
            if not announced_attack and args.attacker and start_attack:
                # Take the hash of the block before the bad_tx
                trigger_block_hash = blockchain.cleaned_keys[trigger_block-1]
                private_last_hash = trigger_block_hash

                # Used to track which blocks to ignore in trying to build new longest chain
                original_blocks = copy.deepcopy(
                    blockchain.cleaned_keys[trigger_block:])
                print("=============\nSTART ATTACK!\n============")
                announced_attack = True

                # Generate new public key and empty out balance from old public key
                new_private_key = create_key()
                new_public_key = new_private_key.get_verifying_key()
                try:
                    print(
                        "Double-spending: Making transaction to empty out old account...")
                    empty_old_account = Transaction(public_key, new_public_key, amount=ledger.get_balance(
                        public_key), comment="transferring all money out", sender_pk=private_key)
                    print("sent transaction")
                except AssertionError:
                    # Old account already empty
                    pass
                public_key = new_public_key
                private_key = new_private_key

                # Take on a new identity
                miner = Miner(blockchain, new_public_key)
                # Need to create merkle again so coinbase goes to new_public_key
                merkletree, ledger = miner.create_merkle(
                    transaction_queue, tx_to_ignore=ignore_transactions)

            # If attack starts, slow down honest miner
            if not args.attacker and start_attack:
                if skip_mine_count % 500 == 0:
                    miner_status = miner.mine(merkletree, ledger)
                    # Keep range of skip_mine_count within (0,500]
                    skip_mine_count = 0
                skip_mine_count += 1
            elif args.attacker and start_attack:
                # Start mining from block before bad_tx
                miner_status = miner.mine_from_old_block(
                    merkletree, ledger, private_last_hash)
            else:
                # Mine normally if no attack
                miner_status = miner.mine(merkletree, ledger)

            mine_or_recv = ""
            # Check if mine is successful
            if miner_status:
                mine_or_recv = "Block MINED "

                if args.attacker and start_attack:
                    # sending_block might not be last block of blockchain
                    sending_block = find_private_block(
                        blockchain.chain, private_last_hash, original_blocks)
                    sending_block_header_hash = binascii.hexlify(
                        sending_block.header_hash()).decode()
                    mine_or_recv += sending_block_header_hash
                    private_fork.append(sending_block)
                    # Update private_last_hash
                    private_last_hash = sending_block_header_hash
                    if len(private_fork) == 3:
                        for block in private_fork:
                            block_data = pickle.dumps(block, protocol=2)
                            send_failed = True
                            while send_failed:
                                try:
                                    requests.post("http://"+args.ip_other +
                                                  "/block", data=block_data)
                                    send_failed = False
                                except:
                                    time.sleep(0.1)
                        private_fork = []
                        if not check_block_in_chain(blockchain, original_blocks[0]):
                            print("=============\nATTACK ENDED\n============")
                            # stop attack
                            start_attack = False
                            cease_attacks = True
                        else:
                            print(
                                "Block to void:", original_blocks[0], "Chain:", blockchain.cleaned_keys)
                            print(
                                "Block we want to void is still in chain! Continuing attack...")

                else:  # args.attacker and not start_attack or not args.attacker
                    sending_block = blockchain.last_block()
                    mine_or_recv += binascii.hexlify(
                        sending_block.header_hash()).decode()

                    data = pickle.dumps(sending_block, protocol=2)
                    send_failed = True
                    while send_failed:
                        try:
                            requests.post("http://" + args.ip_other +
                                          "/block", data=data)
                            send_failed = False
                        except:
                            time.sleep(0.2)
                break

            if miner.nonce % 1000 == 0:
                # Check if new blocks have been detected
                block_queue_status_initial = block_queue.empty()
                while not block_queue.empty():
                    mine_or_recv += "Block RECEIVED "
                    # If detected, add new block to blockchain
                    new_block = block_queue.get()
                    miner.network_block(new_block)
                    mine_or_recv += binascii.hexlify(
                        new_block.header_hash()).decode() + " "
                if not block_queue_status_initial:
                    break
                block_queue_status_initial = True
        print(color(args.color) + "PORT: {}\n".format(args.port) + mine_or_recv +
              str(miner.blockchain).split("~~~")[1])
        if start_attack and args.attacker:
            print(color(args.color) + "private fork:"+" "*14*(trigger_block-2), trigger_block_hash[:10]+" -> ",
                  [binascii.hexlify(private_block.header_hash()).decode()[:10] for private_block in private_fork])
Ejemplo n.º 6
0
w1 = Wallet(465)
print(w1.pubkey.exportKey)
w2 = Wallet(344)
w3 = Wallet(162)
poolz = TransactionPool()
blockchain = UCoin('Genesis test')
m1 = Miner(blockchain, poolz, w1)
m2 = Miner(blockchain, poolz, w2)
t1 = w1.create_transaction(w2.pubkey, 40, m1.pool)
t2 = w1.create_transaction(w2.pubkey, 16, m1.pool)
print('============================================================')
for p in m1.pool.transaction:
    print(p.id, p.input.amount, p.input.address)
    for o in p.output:
        print(o.string_repre())
m1.mine()
w1.update_balance(m1.blockchain)
w2.update_balance(m2.blockchain)
w3.update_balance(m1.blockchain)
print('current balance: ', w1.balance, w2.balance, w3.balance)
print('============================================================')
t3 = w1.create_transaction(w3.pubkey, 60, m1.pool)
t4 = w3.create_transaction(w1.pubkey, 19, m1.pool)
for p in m2.pool.transaction:
    print(p.id, p.input.amount, p.input.address)
    for o in p.output:
        print(o.string_repre())
m2.mine()
w1.update_balance(m1.blockchain)
w2.update_balance(m2.blockchain)
w3.update_balance(m1.blockchain)
Ejemplo n.º 7
0
    else:
        break

# Create Miner Accounts
miner1 = Miner()
miner2 = Miner()
miner3 = Miner()
print('Miners Generated...')

# Show Advertised Transactions to start Verification
print('Verification Start:')
transacts = miner1.show()

# Start Mining
print('Mining...')
h2 = miner1.mine(transacts.copy())

# Start of Consensus Mechanism. If Consensus happens, the block gets added to the Chain.
print('Trying to Achieve Consensus:')
if (miner2.consensus(h2) == 1 and miner3.consensus(h2) == 1):
    print('Verified.')
    print('Creating Block')
    print('Adding Block to Chain')
    blockchain.add_block(h2)
else:
    print("Can't Verify.")

# Show information in the Blockchain Now
print('Printing Complete Blockchain:')
c = 1
for i in blockchain.chn:
Ejemplo n.º 8
0
class Node:
    """
    The node class used to manage communication between other nodes in the peer to peer network and the miner
    that is being run on this node.
    """
    """
    The port that nodes in the network use to communicate with one another.
    """
    REQUEST_PORT = 10000

    def __init__(self):
        """
        Initialize the servers and miner required for a peer to peer node to operate.
        """
        self.node_id = randbits(32)  # Create a unique ID for this node
        self.node_pool = NodePool(self.node_id, 30, 105)

        self.miner = Miner()
        self.miner.mine_event.append(self.block_mined)
        self.heartbeat = p2p.Heartbeat(Node.REQUEST_PORT, 30, self.node_id)

        router = RequestRouter(self)
        router.handlers[request_pb2.BLOB] = self.handle_blob
        router.handlers[request_pb2.DISOVERY] = self.handle_discovery
        router.handlers[request_pb2.MINED_BLOCK] = self.handle_mined_block
        router.handlers[request_pb2.RESOLUTION] = self.handle_resolution
        router.handlers[
            request_pb2.BLOCK_RESOLUTION] = self.handle_block_resolution

        self.tcp_router = server.TCPServer(Node.REQUEST_PORT, TCPRouter)
        self.tcp_router.router = router

        self.udp_router = server.UDPServer(Node.REQUEST_PORT, UDPRouter)
        self.udp_router.router = router

        self.input_server = server.TCPServer(9999, DataServer)
        self.input_server.node = self

        self.output_server = server.TCPServer(9998, OutputServer)
        self.output_server.node = self

    def block_mined(self, block, chain_cost):
        """
        The block mined callback that is called when the miner has succeeded in mining a block and adding it
        to the end of the current chain.
        :param block: The block that was mined.
        :param chain_cost: The total cost of the currently mined chain.
        :return: None
        """
        msg = request_pb2.MinedBlockMessage()
        msg.chain_cost = chain_cost
        msg.block = block.encode()

        req = request_pb2.Request()
        req.request_type = request_pb2.MINED_BLOCK
        req.request_message = msg.SerializeToString()
        data = req.SerializeToString()

        self.node_pool.multicast(data, Node.REQUEST_PORT)

    def run(self):
        """
        Run the servers for receiving incoming requests and start mining.
        This method never returns.
        """
        self.node_pool.start()

        server.start_server(self.tcp_router)
        server.start_server(self.input_server)
        server.start_server(self.output_server)
        server.start_server(self.udp_router)

        self.heartbeat.start()
        self.miner.mine()

    def shutdown(self):
        """
        Shutdown the all TCP and UDP servers when the node is shutdown to ensure that all ports are properly closed.
        :return: None
        """
        self.tcp_router.shutdown()
        self.tcp_router.server_close()

        self.input_server.shutdown()
        self.input_server.server_close()

        self.output_server.shutdown()
        self.output_server.server_close()

        self.udp_router.shutdown()
        self.udp_router.server_close()

    def handle_blob(self, data, handler):
        """
        Handle a binary object that has been submitted to the block chain network by an outside client. This
        data will be forwarded to this nodes peers.
        :param data: The binary data that has been submitted to be added to the block chain.
        :param handler: The handler that received the message.
        :return: 
        """
        logging.debug("Got a blob " + str(data))

        if self.miner.add(data):
            logging.debug("forward blob to peers")
            req = request_pb2.Request()
            req.request_type = request_pb2.BLOB
            req.request_message = data
            msg = req.SerializeToString()

            self.node_pool.multicast(msg, Node.REQUEST_PORT)
        else:
            logging.debug("received duplicate blob")

    def handle_discovery(self, data, handler):
        """
        Handle a discovery message from a peer in the block chain network when it broadcasts that it is still alive.
        :param data: The discovery message containing the peer's unique identifier.
        :param handler: The handler that received the message.
        :return: None
        """
        logging.debug("Got discovery message")
        msg = request_pb2.DiscoveryMessage()
        try:
            msg.ParseFromString(data)
        except message.DecodeError:
            logging.error("Error decoding message: %s", data)
            return

        self.node_pool.add(msg.node_id, handler.client_address[0])

    def handle_output_request(self, idx, handler):
        """
        Handle an output request from a client outside the network that is requesting the data in a specific
        block within the block chain.
        :param idx: The index in the block chain of the block who's data is being requested.
        :param handler: The handler that received the client's request.
        :return: None
        """
        block = self.miner.get_block(idx)
        if block is None:
            handler.send("Index out of bounds.\n".encode())
            return

        output = str(self.node_id) + " : " + block.to_ascii()
        handler.send(output.encode())

    def handle_mined_block(self, data, handler):
        """
        Handle a message from a peer in the network notifying the current node that it mined a block.
        :param data: The data containing the data for the block that was mined.
        :param handler: The handler that received the message.
        :return: None
        """
        logging.debug("Got mined block")
        msg = request_pb2.MinedBlockMessage()
        try:
            msg.ParseFromString(data)
            block = Block.decode(msg.block)
        except message.DecodeError:
            logging.error("Error decoding message: %s", data)
            return

        chain = self.miner.receive_block(block, msg.chain_cost)
        if chain is None:
            # The block was added to an existing chain
            return
        self.start_chain_resolution(handler.client_address[0], chain)

    def handle_resolution(self, data, handler):
        """
        Handles a resolution message from a peer in the network when the peer asks for the current node's
        resolution chain. This causes the current node to send the headers for all blocks in the chain to
        allow the peer to undergo chain resolution so that the peer can determine if it should replace its
        chain with the chain currently being worked on by this node.
        :param data:  The message data which is unused because the resolution message only depends on the 
        message type, not the body.
        :param handler: The handler that received the message.
        :return: None
        """
        res_chain = self.miner.get_resolution_chain()
        msg = framing.frame_segment(res_chain)
        handler.send(msg)

        # handle block resolution with the same connection if
        # block resolution is required
        handler.handle()

    def handle_block_resolution(self, data, handler):
        """
        Handle a block resolution message from a peer in the network to fetch the block body data for
        all block's whose indices are provided in the message data.
        :param data: The block resolution message containing the block indices for which to fetch the body data.
        :param handler: The handler that received the message.
        :return: None
        """
        msg = request_pb2.BlockResolutionMessage()
        try:
            msg.ParseFromString(data)
        except message.DecodeError:
            return

        for idx in msg.indices:
            block_data = self.miner.get_resolution_block(idx)
            if block_data is None:
                # The index was invalid so close the connection and end the block resolution process
                handler.request.close()
                return

            data = framing.frame_segment(block_data)
            handler.send(data)

    def start_chain_resolution(self, peer_addr, chain):
        """
        Begin the chain resolution protocol for fetching all data associated with a higher cost chain in 
        the network to allow the current node to mine the correct chain.
        :param peer_addr: The address of the peer with the higher cost chain.
        :param chain: The incomplete higher cost chain that requires resolution.
        :return: None
        """
        # Connect to the peer with the higher cost chain
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            s.connect((peer_addr, Node.REQUEST_PORT))
        except socket.error:
            logging.debug(
                "Error: Unable to connect to peer for chain resolution.")
            return

        # Ask for the peer's block headers from the chain to find
        # the point where the current chain diverges from the higher
        # cost chain
        req = request_pb2.Request()
        req.request_type = request_pb2.RESOLUTION
        req_data = req.SerializeToString()
        msg = framing.frame_segment(req_data)

        logging.debug("Ask for resolution chain from: %s", peer_addr)
        s.sendall(msg)

        # Receive the resolution chain from the peer
        try:
            res_data = framing.receive_framed_segment(s)
        except RuntimeError:
            logging.error("Error receiving resolve chain")
            return
        logging.debug("Received resolution chain")

        # Decode the resolution chain's protocol buffer
        try:
            res_chain = Chain.decode(res_data, False)
        except message.DecodeError:
            logging.error("Error decoding resolve chain: %s", res_data)
            return

        # Notify the miner that the block headers for the longer chain
        # were received to verify if the chain has a higher cost than
        # the current chain and hashes correctly
        is_valid = self.miner.receive_resolution_chain(chain, res_chain)
        if not is_valid:
            logging.error("Invalid resolution chain")
            return

        self.start_block_resolution(s, chain)

    def start_block_resolution(self, sock, chain):
        """
        Start the block resolution process for the resolution chain. This involves fetching the block data for 
        any blocks in the chain that are missing their body data. The miner will be notified once the chain has 
        all of its data complete.
        :param sock: The socket to communicate with the peer who has the data.
        :param chain: The chain that has missing block body data.
        :return: None
        """
        res_block_indices = self.miner.get_resolution_block_indices(chain)

        # If all the blocks have both their header and body data
        # then the chain is complete and no block data needs resolving
        if len(res_block_indices) == 0:
            self.miner.receive_complete_chain(chain)
            sock.close()
            return

        logging.debug("Ask for block bodies to populate the resolution chain")

        # Fetch the bodies for any blocks in the chain that are missing them
        msg = request_pb2.BlockResolutionMessage()
        for idx in res_block_indices:
            msg.indices.append(idx)
        msg_data = msg.SerializeToString()

        req = request_pb2.Request()
        req.request_type = request_pb2.BLOCK_RESOLUTION
        req.request_message = msg_data
        req_data = req.SerializeToString()

        data = framing.frame_segment(req_data)
        sock.sendall(data)

        try:
            # Receive the block's body data in order by index
            for idx in res_block_indices:

                block_data = framing.receive_framed_segment(sock)

                # The segment was empty meaning the connection was closed
                # The peer will close the connection if an out of bounds block
                # was requested
                if block_data == b'':
                    logging.error(
                        "Error: Connection closed due to out of bounds index while resolving block data."
                    )
                    self.miner.remove_floating_chain(chain)
                    return

                block = Block.decode(block_data)

                # Bail if adding the received block's data to the chain caused the block's chain of hashes to fail
                if not self.miner.receive_resolution_block(block, idx, chain):
                    logging.error(
                        "Error: Invalid resolution block hash for chain..")
                    self.miner.remove_floating_chain(chain)
                    return

        # Unknown TCP error from the connection failing in the middle of receiving a message
        # Stop block resolution due to losing connection with the peer
        except RuntimeError:
            logging.error(
                "Error: Connection closed while resolving block data.")
            self.miner.remove_floating_chain(chain)
            return

        # Stop block resolution due to a block failing to decode meaning an error occurred with the peer
        except message.DecodeError:
            logging.error("Error: Failed decoding resolution block.")
            self.miner.remove_floating_chain(chain)
            return
        logging.debug("Received block resolution data and completed the chain")

        self.miner.receive_complete_chain(chain)
Ejemplo n.º 9
0
import sys
sys.path.insert(0, '/home/taiyi/job_finder/modules/')
from miner import Miner

job_titles = [

]

miner = Miner(mode = 'negative mine', debug = True)
miner.mine(job_titles)
def start_mining(block_queue, transaction_queue, blockchain_request_queue,
                 blockchain_reply_queue):
    blockchain = BlockChain(LIST_OF_MINER_IP)
    miner = Miner(blockchain, PUBLIC_KEY)
    miner_status = False
    list_of_blocks_selfish = []
    SELFISH_LENGTH = 5
    list_of_collected_selfish_blocks = []
    selfish_flush = False
    # Infinite loop
    while True:
        # Create a merkel tree from transaction queue
        merkletree, ledger = miner.create_merkle(transaction_queue)

        while True:
            # Mines the nonce every round
            miner_status = miner.mine(merkletree, ledger)
            mine_or_recv = ""
            # Check if that mine is successful
            if miner_status:
                mine_or_recv = "Block MINED "
                sending_block = blockchain.last_block()
                mine_or_recv += binascii.hexlify(
                    sending_block.header_hash()).decode()

                # Grab the last block and send to network
                # If regular miner
                if not SELFISH:
                    data = pickle.dumps(sending_block, protocol=2)
                    for miner_ip in LIST_OF_MINER_IP:
                        send_failed = True
                        while send_failed:
                            try:
                                requests.post("http://" + miner_ip + "/block",
                                              data=data)
                                send_failed = False
                            except:
                                print("Send failed.", miner_ip)
                                time.sleep(0.2)
                    sending_spv_block = SPVBlock(sending_block)
                    data = pickle.dumps(sending_spv_block, protocol=2)
                    for spv_ip in LIST_OF_SPV_IP:
                        send_failed = True
                        while send_failed:
                            try:
                                requests.post("http://" + spv_ip +
                                              "/block_header",
                                              data=data)
                                send_failed = False
                            except:
                                print("Send failed.", spv_ip)
                                time.sleep(0.2)
                # If selfish miner
                elif SELFISH:
                    mine_or_recv += "\nSELFISH MINING\n"
                    list_of_blocks_selfish.append(sending_block)
                    # It will send only every n blocks
                    if len(list_of_blocks_selfish) >= SELFISH_LENGTH:
                        mine_or_recv += "SENDING SELFISH BLOCKS\n"
                        selfish_flush = True
                        for block in list_of_blocks_selfish:
                            block_data = pickle.dumps(block, protocol=2)
                            for miner_ip in LIST_OF_MINER_IP:
                                send_failed = True
                                while send_failed:
                                    try:
                                        requests.post("http://" + miner_ip +
                                                      "/block",
                                                      data=block_data)
                                        send_failed = False
                                    except:
                                        time.sleep(0.1)
                        list_of_blocks_selfish = []
                break
            # Runs this area only once every 100 nonce, as checking queue every cycle makes it very laggy
            if miner.nonce % 100 == 0:
                # Check if new blocks have been detected
                block_queue_status_initial = block_queue.empty()
                while not block_queue.empty():
                    mine_or_recv += "Block RECEIVED "
                    new_block = block_queue.get()
                    if not SELFISH:
                        miner.network_block(new_block)
                    elif SELFISH:
                        list_of_collected_selfish_blocks.append(new_block)
                        if len(list_of_collected_selfish_blocks
                               ) > SELFISH_LENGTH or selfish_flush:
                            for i in list_of_collected_selfish_blocks:
                                miner.network_block(i)
                            for block in list_of_blocks_selfish:
                                block_data = pickle.dumps(block, protocol=2)
                                for miner_ip in LIST_OF_MINER_IP:
                                    send_failed = True
                                    while send_failed:
                                        try:
                                            requests.post("http://" +
                                                          miner_ip + "/block",
                                                          data=block_data)
                                            send_failed = False
                                        except:
                                            time.sleep(0.1)
                            miner.blockchain.resolve()
                            list_of_collected_selfish_blocks = []
                            list_of_blocks_selfish = []
                            selfish_flush = False
                    mine_or_recv += binascii.hexlify(
                        new_block.header_hash()).decode() + " "
                if not block_queue_status_initial:
                    mine_or_recv += "\n"
                    break
                # Checks if any of the endpoints requested a copy of the blockchain
                if not blockchain_request_queue.empty():
                    blockchain_request_queue.get()
                    blockchain_reply_queue.put(
                        (copy.deepcopy(blockchain.cleaned_keys),
                         copy.deepcopy(blockchain.chain),
                         copy.deepcopy(blockchain.retrieve_ledger())))
        # Section runs if the miner found a block or receives a block that has been broadcasted
        print(COLOR + "Public key: {}\n".format(PUBLIC_KEY_STRING) +
              "PORT: {}\n".format(MY_PORT) + mine_or_recv + "\n" +
              (str(miner.blockchain) if MODE ==
               1 else str(miner.blockchain).split("~~~\n")[1]))
Ejemplo n.º 11
0
def test():
    ## Generate Key
    sk = SigningKey.generate(curve=NIST192p)
    vk = sk.get_verifying_key()
    sk2 = SigningKey.generate(curve=NIST192p)
    vk2 = sk2.get_verifying_key()

    ## Create Transactions
    newTxn = Transaction(vk.to_string().hex(), 'receiverkey', 100)
    ## convert to JSON
    toJson = newTxn.to_json()
    ## Sign JSON
    signature = newTxn.sign(toJson, sk.to_string())
    print(signature)
    ## Validate
    validated = newTxn.validate_signature(toJson, signature, vk.to_string())

    txn1 = Transaction(vk.to_string().hex(), 'receiverkey1', 100).to_json()
    txn2 = Transaction(vk.to_string().hex(), 'client1', 100).to_json()
    txn3 = Transaction(vk2.to_string().hex(), 'client3', 100).to_json()
    transactionlist = [txn1, txn2, txn3]

    ## Create Block with transaction
    block = Block(transactionlist)
    block2 = Block([txn3])
    chain = Blockchain()
    chain.set_blockheader(block)
    chain.add(block, 1)
    chain.set_blockheader(block2)
    chain.add(block2, 2)

    #Populate blockchain with blocks
    for i in range(2):
        chain.set_blockheader(block)
        chain.add(block, 1)

    txn4 = Transaction('receiverkey1', 'receiverkey3', 100).to_json()
    txn5 = Transaction('receiverkey3', 'receiverkey1', 100).to_json()

    chain.transactionpool.append(txn4)
    chain.transactionpool.append(txn5)

    # Miner Test
    m1 = Miner(chain)
    m2 = Miner(chain)
    block4 = m1.mine(chain)
    chain.add(block4, m1.publickey.to_string().hex())
    block5 = m1.mine(chain)
    chain.add(block5, m1.publickey.to_string().hex())

    # SPV Test
    spvclient = SPVClient()
    checktransaction = spvclient.receive_transaction(txn3, m1)
    newtxn = spvclient.new_txn(m1.publickey.to_string().hex(), 100)
    nt = m1.new_txn(spvclient.publickey.to_string().hex(), 100)

    print(nt)
    miners_list = [m1, m2]

    #####selfish mining attack####
    m3 = SelfishMiner(chain)
    miners_list.append(m3)
    for miner in miners_list:
        block = miner.mine(chain)
        chain.add(block, miner.publickey.to_string().hex())

    #trying to show the number of blocks mined by selfish miners
    selfish_blocks = m3.selfish_mine(chain)
    print("Selfish miner's work: ", selfish_blocks)

    ###DOUBLE SPENDING attack###
    m4 = DoubleSpender(chain)

    #first let m4 have some money
    #m2 make txn to send 60 to m4
    txnToDS = m2.new_txn(m4.publickey.to_string().hex(), 60)

    #attacker mine the latest txn pool
    dsBlock = m4.mine(chain)
    chain.add(dsBlock, m4.publickey.to_string().hex())
    print("Attacker's balance (before) is",
          m4.get_balance(chain,
                         m4.publickey.to_string().hex()))

    #he then performs the attack
    dsBlocks = m4.attack(chain)
    print("Attacker's balance (after) is",
          m4.get_balance(chain,
                         m4.publickey.to_string().hex()))