Ejemplo n.º 1
0
def run_sanity_test():
    hash_difficulty_value = 15

    bc = BlockChain()

    for i in range(10):
        prev_block = bc.get_target_block()
        timestamp = int(time.time())
        data = str(timestamp)
        new_counter = prev_block.get_counter() + 1

        block = Block(prev_block.get_hash_value(), timestamp, data,
                      new_counter, hash_difficulty_value)

        set_nonce(block)
        success = bc.add_block(block)
        if not success:
            print "Unable to add block"
            raise Exception()

    success = bc.audit()
    if not success:
        print "Unable to audit the block chain"
        raise Exception

    print "== Successfully ran the simple sanity check test"
Ejemplo n.º 2
0
def run_illegal_hash_value_block_test():
    hash_difficulty_value = 15
    bc = BlockChain()

    prev_block = bc.get_target_block()
    timestamp = int(time.time())
    data = str(timestamp)
    new_counter = prev_block.get_counter() + 1

    wrong_hash_value = "asdasdfasdfasdf"

    block = Block(
        wrong_hash_value,  # prev_block.get_hash_value(),
        timestamp,
        data,
        new_counter,
        hash_difficulty_value)

    set_nonce(block)
    success = bc.add_block(block)
    if success:
        print "Should not have been able to add illegal block !!!"
        raise Exception()

    print "== Successfully ran the run_illegal_hash_value_block_test"
Ejemplo n.º 3
0
def illegal_signatures_test():
    block_chain_name = "stupid_block_chain"

    genesis_key = RSAWrapper.keygen()
    client_keys = [RSAWrapper.keygen()]
    client_ids = [Common.client_id_from_public_key(client_keys[0].publickey())]
    client_amounts = [10]

    bc = BlockChain(block_chain_name, genesis_key, client_ids, client_keys,
                    client_amounts)

    verifies = bc.audit()
    if not verifies:
        raise Exception("Empty BC does not verify")

    # Add transactions from account with 10 to a new account
    new_client_key = RSAWrapper.keygen()
    client_keys.append(new_client_key)
    client_public_keys = [key.publickey() for key in client_keys]
    client_ids.append(
        Common.client_id_from_public_key(new_client_key.publickey()))
    num_clients = len(client_ids)

    signature_message_text = "Just some incorrect bullshit"
    signatures = [
        RSAWrapper.sign(signature_message_text, key) for key in client_keys
    ]

    new_block = bc.create_block(num_clients, client_ids, client_public_keys,
                                [-5, 5], signatures)
    if new_block:
        raise Exception(
            "New block should not be created since signatures don't match")

    print "== Successfully ran illegal_signatures_test()"
Ejemplo n.º 4
0
    def get_correctAccount(self, sychroTable, chash):
        #初始化账本
        if self.chain:
            hc = self.chain.blockchain
        else:
            bc = BlockChain()
            bc.synchro_fromDatabase()  #如果关机重启了,从数据库同步账本
            hc = bc.blockchain

        #统计认可度最高的hash
        t = collections.Counter(sychroTable.values())
        a = sorted(collections.Counter(sychroTable.values()))
        b = 0
        righthash = 0
        for i in t.keys():
            if t[i] > b:
                b = t[i]
                righthash = i
        #righthash=max(t.values())

        #Sfor m in
        for k in sychroTable.keys():
            if sychroTable[k] == righthash:
                ipaddress = k
                break

        #查自身的链表
        if righthash != chash:
            return {righthash: ipaddress}
        for i in range(1, len(hc)):
            print hc[i - 1].hash()
            print hc[i].get_previoushash()
            if hc[i - 1].hash() != hc[i].get_previoushash():
                return {righthash: ipaddress}
        return None
Ejemplo n.º 5
0
    def __init__(self, node_id: str):
        """
        Constructor for the Node class.

        :param str node_id: one of '0', '1', '2', or '3', the possible nodes in network
        """
        ##############################################
        self.difficulty = 5
        _max = 'f' * 64
        self.hash_difficulty = _max.replace('f', '0', self.difficulty)

        self.node_id = node_id
        self.file_path = '../files/blockchain' + node_id + '.txt'
        self.ledger = Ledger(node_id)
        self.blockchain = BlockChain(self.node_id, self.ledger)

        self.messenger = Messenger(self.node_id, self)
        self.peers = [
            peer for peer in ['0', '1', '2', '3'] if peer != self.node_id
        ]
        self.transaction_queue = []
        self.reset_mine_function = False
        self.stop_mine_function = False
        self.received_blocks = collections.deque(
        )  # d.append() to add, d.popleft() to remove as queue
        self.mine_thread = self.start_mining_thread()
Ejemplo n.º 6
0
 def __init__(self):
     self.nodeList = []
     self.globalUnverifiedTxPool: Transaction = []
     myMVB = BlockChain()
     # create genesis Block via static method
     self.genesisBlock = BlockChain.createGenesisBlock(BlockChain)
     self.__startNodesThread(8)
     self.__readTxFromFile()
Ejemplo n.º 7
0
    def __init__(self):

        self.blockchain = BlockChain()

        self.neighbours = []
        self.address = 0
        self.pub_key_list = {}
        self.wallet = {}
Ejemplo n.º 8
0
 def __init__(self, policy, store, id, n):
     genesisBlock = Block().Mine(0, 0, None, datetime.utcnow(), [])
     self.blockChain = BlockChain(policy, store, id, genesisBlock)
     for i in range(n):
         print(
             "-----------------------------------------------------------")
         print("_________", i + 1,
               "' block Mining & Appending Start_________")
         block = self.MakeNewBlock(self.blockChain)
         self.blockChain.Append(block)
Ejemplo n.º 9
0
 def __init__(self, pubKey: str, privateKey: str, nNodes: int) -> None:
     blockchain = BlockChain()
     txQueue = Queue()
     blkQueue = Queue()
     self.blockchain: BlockChain = blockchain
     #print("blockchain: ", self.blockchain)
     self.txQueue: Queue = txQueue
     self.blkQueue: Queue = blkQueue
     self.blkThreshold: Threshold = Threshold.BLK_THRESHOLD
     self.txnThreshold: Threshold = Threshold.TXN_THRESHOLD
     self.generatedTxns: List[Transaction] = []
     self.nodesList: List[BitCoinNode] = []
     self.nodesKeys: List[List[str]] = []
     self.txnCnt = 0
     self.nTxns = 0
     self.nNodes = nNodes
     #self.nTxns = nTxns
     #self.arrId = arrId
     #self.mempoolStatus = mempoolStatus
     BitCoinNode.id += 1
     self.id: int = BitCoinNode.id
     #self.target: str = "0000000000000000007e9e4c586439b0cdbe13b1370bdd9435d76a644d047523"
     #self.target: str = "0987892757f34247427e9e4c586439b0cdbe13b1370bdd9435d76a644d047523"
     self.target: str = "0007892757f34247427e9e4c586439b0cdbe13b1370bdd9435d76a644d047523"
     self.pubKeys: List[str] = []
     if pubKey:
         self.pubKeys.append(pubKey)
     self.privateKeys: List[str] = []
     if privateKey:
         self.privateKeys.append(privateKey)
Ejemplo n.º 10
0
	def __init__(self, env, id,  honest, manual_committee_size=2):
		self.env = env
		self.id = id
		self.chain=BlockChain()
		self.gossip_pipes = Links(self.env)
		#store peer AlgoNode for shuffling
		self.peers=list()
		self.pipe = simpy.Store(self.env)
		self.sk = vrftool.new_sk()
		self.pk= vrftool.get_pk(self.sk)
		self.proposers = 100

		self.manual_committee_size = manual_committee_size
		self.block_candidates = dict()
		#buffer structure: round:messages
		self.blocks_and_proof=dict()
		#record incoming msg
		self.message_buffer=dict()
		#store votes for each step
		self.vote_buffer = dict()
		#store voters and their votes for each round an step
		self.voters = dict()
		self.request = list()
		self.unprocessed_msg = list()
		self.waiting_block=dict()
		self.waiting_reply = False
		self.Tenative = False
		#set node type honest or malicious
		if honest:
			self.honest = True
		else:
			self.honest = False
    def constructChains(self):

        # Get directories in chains directory
        filesInChainsDir = os.listdir(self.chainsDir)
        dirInChainsDir = []

        for chainsFile in filesInChainsDir:

            print("- File In Chains: " + chainsFile)

            if (os.path.isdir(self.chainsDir + '/' + chainsFile)):
                print("\tIs a directory")
                dirInChainsDir += [chainsFile]

        # Construct the various chains (could add a bit more checking of files here as well)
        for someDir in dirInChainsDir:

            # pull out the name
            dirName = someDir.split('/')[-1]
            print("- adding chain <" + dirName + ">...")

            # create chain and append
            self.blockChains.append(BlockChain(someDir))

        print("- Chains constructed")
Ejemplo n.º 12
0
    def __init__(self, data_file_name, block_chain_file):
        self._key = self._load_keys("BBBPrivateKey.pem")
        self._client_public_keys = {
        }  # Stores {client_id, exported_client_public_key_that_needs_importing_to_work}
        self._data_file_name = data_file_name
        self._balances_dict = {}
        self._transactions_dict = {}
        self._next_transaction_int_id = 100
        self._load_data_from_file()
        self._host = "localhost"
        self._port = 10555

        # TODO missing block chain parameters
        self._block_chain = BlockChain(block_chain_file)

        self._s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self._s.bind((self._host, self._port))
Ejemplo n.º 13
0
    def __init__(self, node_id: str):
        """
        Constructor for the Node class.
        Synchronizes nodes.
        Starts messaging and mining threads.
        Creates files to store data.

        :param str node_id: one of '0', '1', '2', or '3', the possible nodes in network
        """
        self.node_id = node_id
        self.file_path = '../files/blockchain' + node_id + '.txt'
        self.ledger = Ledger(node_id)
        self.blockchain = BlockChain(self.node_id, self.ledger)
        self.probability = 0.1
        self.term_duration = 25
        self.le = LeaderElection(self.node_id)
        self.leader_counts = {'0': 0, '1': 0, '2': 0, '3': 0}
        # self.elected_boolean = False

        self.peers = [peer for peer in ['0', '1', '2', '3'] if peer != self.node_id]
        self.transaction_queue = []

        self.received_blocks = collections.deque()
        self.secret_message = b'SECRET TUNNEL!'
        self.nodes_online = []

        self.all_public_keys = {}
        self.private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
            backend=default_backend()
        )
        self.sig = self.private_key.sign(
            self.secret_message,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        ).hex()
        self.peer_signatures = {}
        self.all_public_keys[self.node_id] = self.private_key.public_key()
        self.messenger = Messenger(self.node_id, self)
        self.sync_nodes()
        self.genesis_time = 'not set'
        self.term = 0
    def constructNewChain(self, minerInfo, fundingChainName, newChainName):

        # get miner's balance at the given chain
        fundingChain = self.blockChains[self.getChainIndex(fundingChainName)]

        minerAddr = fundingChain.obtainUserAddr(minerInfo)

        fundingChainDerivLevel = fundingChain.getDerivationLevel()
        minerBalance = fundingChain.getMinerBalance(minerInfo.displayName,
                                                    minerAddr)

        # is enough to obtain new currency
        cost = (self.derMultiplier**(3 + fundingChainDerivLevel))

        if (minerBalance <= cost):
            return False

        # check if the chain name already exists
        if (self.getChainIndex(newChainName) == -1):
            return False

        # pay for it
        if (not (fundingChain.newTransaction(minerInfo, "0", "0", cost))):
            return False

        # produce chain directory
        newChainDir = self.chainDir + "/" + newChainName
        os.mkdir(newChainDir)

        # create the chain files
        chainFilePath = newChainDir + "/" + newChainName + ".chain"
        chainConfigPath = newChainDir + "/" + newChainName + ".config"
        chainUnconfPath = newChainDir + "/" + newChainName + ".transact"

        chainFile = open(chainFilePath, 'w')
        chainConfig = open(chainConfigPath, 'w')
        chainUnconf = open(chainUnconfPath, 'w')

        # write in the appropriate config
        configString = "owner:" + miner + "\n"
        configString += "owner address:" + minerAddr + "\n"
        configString += "block cap:265720\n"
        configString += "proofs per block:3\n"
        configString += "chain derivation depth:" + str(1 +
                                                        fundingChainDerivLevel)

        chainConfig.write(configString)

        # close files
        chainFile.close()
        chainConfig.close()
        chainUnconf.close()

        # create chain and append to list
        newChain = BlockChain(newChainName)
        self.blockChains.append(newChain)

        return True
Ejemplo n.º 15
0
def main():
    blockchain = BlockChain()

    print("***Mining kyleCoin about to start***")
    print(blockchain.chain)

    data = [{"sender": "0",  # it implies that this node has created a new block
             "receiver": "Kyle Galloway",
             # creating a new block (or identifying the proof number) is awarded with 1
             "quantity": 1
             },
            {"sender": "Jack Daniels", "receiver": "Kyle Galloway", "quantity": 3},
            {"sender": "Kyle Galloway", "receiver": "Jack Daniels", "quantity": 2}]

    for datum in data:
        last_block = blockchain.latest_block
        last_proof_no = last_block.proof_no
        proof_no = blockchain.proof_of_work(last_proof_no)

        blockchain.new_data(
            sender=datum["sender"],
            receiver=datum["receiver"],
            quantity=datum["quantity"],
        )

        last_hash = last_block.calculate_hash
        # block = blockchain.construct_block(proof_no, last_hash)
        blockchain.construct_block(proof_no, last_hash)

        print("***Mining kyleCoin has been successful***")
        print(blockchain.chain)
Ejemplo n.º 16
0
def withdraw_without_funds_test():
    block_chain_name = "stupid_block_chain"

    genesis_key = RSAWrapper.keygen()
    client_keys = [RSAWrapper.keygen()]
    client_ids = [Common.client_id_from_public_key(client_keys[0].publickey())]
    client_amounts = [10]

    bc = BlockChain(block_chain_name, genesis_key, client_ids, client_keys,
                    client_amounts)

    verifies = bc.audit()
    if not verifies:
        raise Exception("Empty BC does not verify")

    # Try to subtract 15 from an account that only has 10
    new_client_key = RSAWrapper.keygen()
    client_keys.append(new_client_key)
    client_public_keys = [key.publickey() for key in client_keys]
    client_ids.append(
        Common.client_id_from_public_key(new_client_key.publickey()))
    num_clients = len(client_ids)

    signature_message_text = Common.transaction_signature_text(
        num_clients, client_ids, [10, 0], [-5, 15])
    signatures = [
        RSAWrapper.sign(signature_message_text, key) for key in client_keys
    ]

    new_block = bc.create_block(num_clients, client_ids, client_public_keys,
                                [-15, 15], signatures)
    if new_block:
        raise Exception(
            "New block should not be created since there are not enough funds on the account"
        )

    print "== Successfully ran widthdraw_without_funds_test()"
Ejemplo n.º 17
0
def run_action(block_chain: BlockChain, action: Action):
    """This function calls the required methods which are needed for the user's input """
    if action == Action.ADD_TRANSACTION:
        transaction = Transaction()
        block_chain.add_transaction(transaction)
    if action == Action.MINE_BLOCK:
        block_chain.mine_new_block()
    if action == Action.SHOW_CHAIN:
        block_chain.print_blocks()
    if action == Action.EXIT_PROGRAM:
        sys.exit("See ya later alligator, we hope you enjoyed our small Blockchain application")
Ejemplo n.º 18
0
    def __init__(self, address, addresses):
        #u ip表示进程所在的位置
        self.address = address
        #获取所有进程所在位置
        self.addresses = addresses
        #创建缓冲区
        self.blockBuffer = BlockBuffer()
        #创建一个字典
        self.directory = {}
        #同步进程
        self.processManage = ProcessManage(self.address, self.addresses)

        self.chain = BlockChain()

        # t1=threading.Thread(target=self.watch(), args=())
        # t1.start()
        # t1.setb
        #t1.setDaemon(True)

        #启动一个监听线程,时刻监听指定端口是否有数据传来
        p = threading.Thread(target=self.waitData, args=())
        p.start()
        #p.join()

        #周期性调用,每隔3秒对缓冲区内的块进行排序
        # t1 = threading.Timer(3, self.blockBuffer.sortBufer())
        # t1.start()
        # t1.join()

        # t1 = threading.Thread(target=self.watch, args=())
        # t1.start()

        #t1 = threading.Timer(3, self.watch())
        #t1.start()
        #t1.join()

        #周期性调用,每隔5秒将缓冲区的块数据写入数据库和本地链条
        self.writData()
        #t2 = threading.Timer(5, self.writData)
        #t2.start()
        #t2.join()

        #每隔一定时间通知进程执行同步操作
        sleep(30)
        self.processManage.sync()
Ejemplo n.º 19
0
def miner(transaction_pool):
    last_block_header = '0'*64 # genesis header
    last_block_target = '%064x' % (0x7ffff * 2 ** (8 * (0x20 - 3)))
    #uncomment the line below for harder difficulty
    #last_block_target = '000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
    # init the block chains
    block_chain = BlockChain()
    block = Block(Header(last_block_header), last_block_target)
    # use variable to keep track of where in the pool we left off reading from
    # so that we're not going to re-mine the same block
    left_off_in_pool = 0
    # add coinbase transaction
    block.add_transaction(CoinbaseTransaction(0))
    for i in range(1, 9):
        block.add_transaction(transaction_pool.transactions[i])
        left_off_in_pool = i
    # now that our block is full, we can start to mine it.
    while not block.mine_this_block():
        continue
    block_chain.add_block(block)
    print("current blockchain height ", block_chain.size_of_chain())
    sleep(5)
    # our new header for block 2 will need the hash of block 1
    last_block_header = double_hash(encode_and_concenate([block_chain.latest_block().BlockHash]))
    block_2 = Block(Header(last_block_header), last_block_target)
    block_2.add_transaction(CoinbaseTransaction(block.transactions[0].current_total))
    for i in range(left_off_in_pool+9):
        block_2.add_transaction(transaction_pool.transactions[i])
        left_off_in_pool = i
    # now that our block is full, we can start to mine it.
    while not block_2.mine_this_block():
        continue
    block_chain.add_block(block_2)
    print("current blockchain height ", block_chain.size_of_chain())
    print()
    for i, block_added in enumerate(block_chain.blocks):
        print('Block #{} was added. It took {} steps to find it.'.format(i, block_added.nonce))
Ejemplo n.º 20
0
class BlockChainTest:
    def __init__(self, policy, store, id, n):
        genesisBlock = Block().Mine(0, 0, None, datetime.utcnow(), [])
        self.blockChain = BlockChain(policy, store, id, genesisBlock)
        for i in range(n):
            print(
                "-----------------------------------------------------------")
            print("_________", i + 1,
                  "' block Mining & Appending Start_________")
            block = self.MakeNewBlock(self.blockChain)
            self.blockChain.Append(block)

    def MakeNewBlock(self, blocks):
        prevBlock = blocks.Tip()
        index = prevBlock.Index() + 1
        txs = []
        difficulty = BlockPolicy().GetNextBlockDifficulty(blocks)
        return Block().Mine(index, difficulty, prevBlock.Hash(),
                            (prevBlock.Timestamp() + timedelta(seconds=5000)),
                            txs)
Ejemplo n.º 21
0
    def __init__(self, env, id, honest, manual_committee_size=2000):
        self.env = env
        self.id = id
        self.chain = BlockChain()
        self.hashchain = dict()
        #store peer AlgoNode for shuffling
        self.peers = list()

        self.sk = vrftool.new_sk()
        self.pk = vrftool.get_pk(self.sk)

        #sortition parameters
        self.proposers = 26
        self.manual_committee_size = manual_committee_size

        self.Pipes = []
        self.Gossiped_Msg = []

        self.Max_Priority_Proposal = dict()
        self.block_candidates = dict()
        #buffer structure: round:messages
        self.Block_Proposals_Msg = dict()
        self.Vote_Msg = dict()
        self.voters = dict()
        self.vote_buffer = dict()
        self.wblock = dict()
        self.waiting_block = False
        self.SortForC = dict()
        self.SortForB = dict()
        self.Tenative = False
        self.ReductionTime = 0
        self.BBAtime = 0
        self.height = max(self.chain.chain.keys())
        self.counttime = 0
        self.Round_start_time = dict()
        #set node type honest or malicious
        if honest:
            self.honest = True
        else:
            self.honest = False
Ejemplo n.º 22
0
def sanity_test():
    block_chain_name = "stupid_block_chain"

    genesis_key = RSAWrapper.keygen()
    client_keys = [RSAWrapper.keygen()]
    client_ids = [Common.client_id_from_public_key(client_keys[0].publickey())]
    client_amounts = [10]

    bc = BlockChain(block_chain_name, genesis_key, client_ids, client_keys,
                    client_amounts)

    verifies = bc.audit()
    if not verifies:
        raise Exception("Empty BC does not verify")

    # Add transactions from account with 10 to a new account
    new_client_key = RSAWrapper.keygen()
    client_keys.append(new_client_key)
    client_public_keys = [key.publickey() for key in client_keys]
    client_ids.append(
        Common.client_id_from_public_key(new_client_key.publickey()))
    num_clients = len(client_ids)

    signature_message_text = Common.transaction_signature_text(
        num_clients, client_ids, [10, 0], [5, 5])
    signatures = [
        RSAWrapper.sign(signature_message_text, key) for key in client_keys
    ]

    new_block = bc.create_block(num_clients, client_ids, client_public_keys,
                                [-5, 5], signatures)
    block_added = bc.add_block(new_block)
    if not block_added:
        raise Exception("Unable to add new block")

    verifies = bc.audit()
    if not verifies:
        raise Exception(
            "Could not verify block chain after adding transaction")

    print "== Successfully ran sanity_test()"
Ejemplo n.º 23
0
    def run(self):
        try:
            waiting_for_blocks_from_client = False
            # start_time = int(time.time())

            while True:
                # Commented out code that was used to create forking data for graph

                # if int(time.time()) - start_time > 600:
                #     # Run for 10 minutes for this test
                #     difficulty_level = self.block_chain.get_hash_difficulty_level()
                #     print "All fork records for client {0} with difficulty level {1}: {2}".format(self.client_name, difficulty_level ,self.block_chain.get_fork_record())
                #
                #     for stop_queue in self.stop_work_queues:
                #         stop_queue.put(True)
                #
                #     if difficulty_level >= self.maximum_hash_difficulty_level:
                #         print "Done looping through all the difficulty levels"
                #         print "Here are all the difficulty levels and ending block number for that level: " + str(self.block_chain.debug_list)
                #         return
                #
                #     self.block_chain.debug_list.append((difficulty_level, self.block_chain.get_target_block().get_counter()))
                #
                #     self.block_chain.set_hash_difficulty_level(difficulty_level + 1)
                #     time.sleep(5)  # sleep 5 seconds to make sure the other clients also manage to clear block chains
                #
                #     for queue in self.block_update_queues:
                #         next_block = create_next_block(self.block_chain, "will_be_updated_by_client")
                #         queue.put(next_block)
                #
                #     for stop_queue in self.stop_work_queues:
                #         stop_queue.get()
                #
                #     start_time = int(time.time())

                # listen for new messages
                data, addr = self.sock.recvfrom(4096)
                deserialized_data = pickle.loads(data)

                command = deserialized_data[0]

                if self.central_register_ip == addr[
                        0] and self.central_register_port == addr[1]:
                    # New client

                    self.client_dict_lock.acquire()
                    self.client_dict[deserialized_data[0]] = (
                        deserialized_data[1],
                        RSA.importKey(deserialized_data[2]))
                    self.client_dict_lock.release()
                elif command == REQUEST_BLOCKS:
                    print "Got a request for blocks in my block chain"
                    hash_id_from_request = deserialized_data[1]
                    blocks_to_respond_with = self.block_chain.get_blocks_since_hash_id(
                        hash_id_from_request)
                    for block in blocks_to_respond_with:
                        msg = pickle.dumps(
                            (INCOMING_BLOCK_FROM_OUR_REQUEST, block))
                        self.sock.sendto(msg, addr)

                    # Send messages that we are done sending blocks
                    msg = pickle.dumps((FINISHED_SENDING_REQUESTED_BLOCKS, ""))
                    self.sock.sendto(msg, addr)
                    print "Finished sending blocks to client"
                elif command == INCOMING_BLOCK_FROM_OUR_REQUEST:
                    sent_block = deserialized_data[1]
                    # print "Got block number {0} from the other client".format(sent_block.get_counter())
                    self.block_chain.add_blocks_from_another_chain(
                        [sent_block])
                    # print "After adding my block chain has {0} blocks".format(self.block_chain.get_number_of_blocks())
                elif command == FINISHED_SENDING_REQUESTED_BLOCKS:
                    # New block for calculation threads
                    current_latest_counter = self.block_chain.get_target_block(
                    ).get_counter()
                    print "Finished receiving blocks from other client. Current latest block chain counter is " + str(
                        current_latest_counter)
                    for queue in self.block_update_queues:
                        next_block = create_next_block(
                            self.block_chain, "will_be_updated_by_client")
                        queue.put(next_block)

                    # Remove stop condition so calculation threads can restart their work
                    for stop_queue in self.stop_work_queues:
                        stop_queue.get()

                    waiting_for_blocks_from_client = False
                elif command == DISCOVERED_BLOCK:
                    if waiting_for_blocks_from_client:
                        continue
                    received_block = deserialized_data[1]
                    received_block_counter = received_block.get_counter()
                    target_block_counter = self.block_chain.get_target_block(
                    ).get_counter()

                    # Too high counter and we want to get the block chain from somebody else
                    block_has_too_high_counter = received_block_counter > target_block_counter + 1
                    if block_has_too_high_counter:
                        print "Got a higher block counter than expected. Expected counter is {0} but we got {1}. " \
                              "Maybe we are out of sync, so lets call some client and get his/her latest block chain". \
                            format(target_block_counter + 1, received_block_counter)

                        # Try to nuke the block chain and send the genesis hash
                        # to collect a fresh block chain from another client
                        previous_hash_difficulty_level = self.block_chain.get_hash_difficulty_level(
                        )
                        self.block_chain = BlockChain()
                        self.block_chain.set_hash_difficulty_level(
                            previous_hash_difficulty_level)
                        hash_id = self.block_chain.get_latest_safe_block_hash_id(
                        )
                        waiting_for_blocks_from_client = True
                        self.request_block_chain_from_random_client(hash_id)
                        continue

                    block_has_too_low_counter = received_block_counter < target_block_counter
                    if block_has_too_low_counter:
                        print "We got an older block. Our latest block counter is {0} but the new blocks counter " \
                              "is {1}. So we ignore it".format(target_block_counter, received_block_counter)
                        continue

                    block_fits_not_latest_block = self.block_chain.block_fits_any_latest_block(
                        received_block)
                    if not block_fits_not_latest_block:
                        print "Got a block with counter {0} that fits no latest block we have. " \
                              "Maybe it is coming from another fork but we are not going to bother " \
                              "with it since it's counter is not high enough".format(received_block_counter)

                    new_block_verified = ProofOfWork.verify_next_block_in_chain(
                        received_block, self.block_chain)
                    if new_block_verified:
                        block_added = self.block_chain.add_block(
                            received_block)
                        if block_added:
                            print "Block number {0} was added to the block chain by client '{1}'".format(
                                str(received_block.get_counter()),
                                received_block.get_data())

                            if self.run_mode == 1:
                                # We want the average number of seconds per block to be self.run_mode_data
                                # If we are below that number we increase the difficulty
                                # If we are above that number we decrease the difficulty
                                number_of_blocks = self.block_chain.get_number_of_blocks(
                                )
                                if number_of_blocks > 2:
                                    last_block = received_block
                                    first_block = self.block_chain.get_first_non_genesis_block(
                                    )
                                    total_seconds_passed = last_block.get_time_stamp(
                                    ) - first_block.get_time_stamp()

                                    average_time_per_block = float(
                                        total_seconds_passed
                                    ) / number_of_blocks

                                    distance_from_time_target = average_time_per_block - self.run_mode_data
                                    if math.fabs(
                                            distance_from_time_target) < 1:
                                        # Lets not do anything if difference is within one sec
                                        pass
                                    elif average_time_per_block > self.run_mode_data:
                                        # Decrease difficulty
                                        current_hash_level_difficulty = self.block_chain.get_hash_difficulty_level(
                                        )

                                        if current_hash_level_difficulty > self.minimum_hash_difficulty_level:
                                            self.block_chain.set_hash_difficulty_level(
                                                current_hash_level_difficulty -
                                                1)
                                            print "This is too difficult (Average time between blocks is {0} sec). Lets decrease the hash difficulty from {1} to {2}"\
                                                .format(int(average_time_per_block),current_hash_level_difficulty, current_hash_level_difficulty - 1)
                                    else:
                                        # Increase difficulty
                                        current_hash_level_difficulty = self.block_chain.get_hash_difficulty_level(
                                        )
                                        if current_hash_level_difficulty < self.maximum_hash_difficulty_level:
                                            self.block_chain.set_hash_difficulty_level(
                                                current_hash_level_difficulty +
                                                1)
                                            print "This is too easy (Average time between blocks is {0} sec). Lets increase the hash difficulty from {1} to {2}" \
                                                .format(int(average_time_per_block), current_hash_level_difficulty,
                                                        current_hash_level_difficulty + 1)
                            elif self.run_mode == 2:
                                # We want every client to on average have as many blocks as everybody else
                                num_clients = len(self.client_dict)
                                if num_clients > 1:
                                    num_blocks_in_chain = self.block_chain.get_number_of_blocks(
                                    ) - 1
                                    num_block_from_me = self.block_chain.get_number_of_blocks_from_client(
                                        self.client_name)
                                    client_ratio = 1 / float(num_clients)
                                    client_block_ratio = num_block_from_me / float(
                                        num_blocks_in_chain)

                                    if math.fabs(client_ratio -
                                                 client_block_ratio
                                                 ) / client_ratio < 0.1:
                                        # If we are within 10% we do no change
                                        pass
                                    elif client_ratio > client_block_ratio:
                                        # This is too hard for this client, he needs more blocks !
                                        current_hash_level_difficulty = self.block_chain.get_hash_difficulty_level(
                                        )
                                        if current_hash_level_difficulty > self.minimum_hash_difficulty_level:
                                            self.block_chain.set_hash_difficulty_level(
                                                current_hash_level_difficulty -
                                                1)
                                            print "Client only has a {0:.2f} share of the blocks ({3} client blocks). Lets decrease its hash difficulty from {1} to {2}" \
                                                .format(client_block_ratio, current_hash_level_difficulty,
                                                        current_hash_level_difficulty - 1, num_block_from_me)
                                    else:
                                        # This is too easy for this client, he needs less blocks !
                                        current_hash_level_difficulty = self.block_chain.get_hash_difficulty_level(
                                        )
                                        if current_hash_level_difficulty < self.maximum_hash_difficulty_level:
                                            self.block_chain.set_hash_difficulty_level(
                                                current_hash_level_difficulty +
                                                1)
                                            print "Client has a {0:.2f} share of the blocks ({3} client blocks). Lets increase its hash difficulty from {1} to {2}" \
                                                .format(client_block_ratio, current_hash_level_difficulty,
                                                        current_hash_level_difficulty + 1, num_block_from_me)

                            for queue in self.block_update_queues:
                                next_block = create_next_block(
                                    self.block_chain,
                                    "will_be_updated_by_client")
                                queue.put(next_block)
                        else:
                            print "Something went wrong. Could not add block to chain"
                    else:
                        print "Got a proposed new block but it did not verify"
        except Exception as e:
            print str(e)
Ejemplo n.º 24
0
def run(client_name, client_ip, client_port, central_register_ip,
        central_register_port, hash_difficulty_level, run_mode, run_mode_data):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind((client_ip, client_port))

    client_dict = {}

    key = RSAWrapper.keygen()
    pub_key = key.publickey()
    ID = Common.client_id_from_public_key(pub_key)

    client_dict[ID] = ((client_ip, client_port), pub_key)
    serialized_message = pickle.dumps(
        (ID, (client_ip, client_port), pub_key.exportKey()))
    sock.sendto(serialized_message,
                (central_register_ip, central_register_port))

    client_dict_lock = threading.Lock()

    block_chain = BlockChain()
    block_chain.set_hash_difficulty_level(hash_difficulty_level)
    block_without_nonce1 = create_next_block(block_chain, client_name)
    block_without_nonce2 = create_next_block(block_chain, client_name)
    block_without_nonce3 = create_next_block(block_chain, client_name)

    block_update_queue1 = Queue.Queue()
    block_update_queue2 = Queue.Queue()
    block_update_queue3 = Queue.Queue()

    stop_calculation_queue1 = Queue.Queue()
    stop_calculation_queue2 = Queue.Queue()
    stop_calculation_queue3 = Queue.Queue()

    minimum_hash_difficulty_level = 10
    maximum_hash_difficulty_level = 23

    if hash_difficulty_level > maximum_hash_difficulty_level:
        print "The max hash difficulty level is {0}. This is for your own sanity (unless you really like waiting)".format(
            maximum_hash_difficulty_level)
        return
    if hash_difficulty_level < minimum_hash_difficulty_level:
        print "The min hash difficulty level is {0}. Below is just way to fast".format(
            minimum_hash_difficulty_level)
        return

    listen = listeningThread(
        ID, 0, "Listening_Thread", sock, block_chain, client_name,
        [block_update_queue1, block_update_queue2, block_update_queue3], [
            stop_calculation_queue1, stop_calculation_queue2,
            stop_calculation_queue3
        ], central_register_ip, central_register_port, client_dict_lock,
        client_dict, run_mode, run_mode_data, minimum_hash_difficulty_level,
        maximum_hash_difficulty_level)
    calc_1 = calculationThread(1, "Calculation_Thread", sock,
                               block_without_nonce1, client_name,
                               block_update_queue1, stop_calculation_queue1,
                               client_dict_lock, client_dict)
    calc_2 = calculationThread(2, "Calculation_Thread", sock,
                               block_without_nonce2, client_name,
                               block_update_queue2, stop_calculation_queue2,
                               client_dict_lock, client_dict)
    calc_3 = calculationThread(3, "Calculation_Thread", sock,
                               block_without_nonce3, client_name,
                               block_update_queue3, stop_calculation_queue3,
                               client_dict_lock, client_dict)

    # Threads set in daemon mode so that they die when the main process dies
    listen.daemon = True
    listen.start()

    calc_1.daemon = True
    calc_2.daemon = True
    calc_3.daemon = True
    calc_1.start()
    calc_2.start()
    calc_3.start()

    run_mode_description = "Normal"
    if run_mode == 1:
        run_mode_description = "'Average time between blocks should be {0} seconds'".format(
            run_mode_data)
    elif run_mode == 2:
        run_mode_description = "'Every client should get equal amount of blocks'"

    print "Client {0} started in {1} mode with initial difficulty {2}".format(
        client_name, run_mode_description, hash_difficulty_level)

    while True:
        time.sleep(1)
Ejemplo n.º 25
0
from BlockChain import BlockChain
import threading
import socket

lock = threading.Lock()
lock2 = threading.Lock()
# 没写监听 广播加进去了 没写main 考虑用多进程

# Instantiate our Node
app = Flask(__name__)

# Generate a globally unique address for this node
node_identifier = str(uuid4()).replace('-', '')

# Instantiate the Blockchain
blockchain = BlockChain()

# global ip
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
s.close()


def listen():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

    port = 4000

    s.bind(('', port))
Ejemplo n.º 26
0
    def main(self, msg_qs, outputq):

        #         print(self.id, len(self.msg_ct_list))
        #         self.msg_ct_list.append(self.id)
        #         print(self.id, self.msg_ct_list)
        done = False
        self.public_keys_of_nodes = [None] * self.N
        self.public_keys_of_nodes[self.id] = self.public_key
        self.node_id_of_public_key = {}
        self.node_id_of_public_key[self.public_key] = self.id
        self.last_transaction_verified = True
        self.last_transaction_key = None
        ct = 0
        for i in range(0, self.N):
            if i != self.id:
                msg_qs[i].put(
                    Message("PUBLIC_KEY", self.public_key, self.id, i))
        ct = 0
        while ct < self.N - 1:
            try:
                msg = msg_qs[self.id].get(block=True, timeout=10)
                if msg.type == "PUBLIC_KEY":
                    self.update_public_key_of_node(msg.src, msg.msg)
                    ct += 1

            except Q.Empty:
                print(" No message and wait for the public keys")
        if self.debug:
            print("Received public key total from ct {} from every node to {}".
                  format(str(ct), str(self.id)))

        miner = Miner(self.id, self.N, self.narry, self.proof_of_work_zeros,
                      self.hash_type, self.confirmation_blocks,
                      self.private_key, self.public_keys_of_nodes,
                      self.node_id_of_public_key, self.debug)
        debug_block_creation_time = True
        if self.id == 0:  ## create a genesis block
            inputs = [Input('None', 'None')]
            outputs = []
            total_amount_generated = 0
            print("Initial money")
            for i in range(0, self.N):
                amount = 1000
                if i == 0:
                    amount += self.block_reward
                total_amount_generated += amount
                print(i, amount)
                outputs.append(
                    Output(self.public_keys_of_nodes[i].hex(), amount,
                           self.hash_type))
            coinbase_t = Transaction(self.public_keys_of_nodes[self.id],
                                     inputs,
                                     outputs,
                                     self.private_key,
                                     t_type='COINBASE',
                                     hash_type=self.hash_type)
            miner.blockchain = BlockChain(self.narry, self.proof_of_work_zeros,
                                          self.hash_type)
            if debug_block_creation_time:
                start_time_block = time.time()
            miner.blockchain.add_genesis_block([coinbase_t])
            if debug_block_creation_time:
                print("Time taken in genesis block creation,",
                      time.time() - start_time_block)
            for i in range(1, self.N):
                if self.debug:
                    print("Sending everyone else the genesis block ", self.id)
                msg_qs[i].put(
                    Message("GENESIS_BLOCK", miner.blockchain, self.id, i))
            self.update_unspent_btc_from_block(miner.blockchain.blockchain[0])
        else:  ### everyone else will receive the genesis block and use it further for transaction
            received_genesis_block = False
            while not received_genesis_block:
                try:
                    msg = msg_qs[self.id].get(block=True, timeout=10)
                    if msg.type == "GENESIS_BLOCK":
                        miner.blockchain = msg.msg
                        received_genesis_block = True

                except Q.Empty:
                    print(" Waiting for genesis block,", self.id)
            if self.debug:
                print(
                    "Received genesis block, now need to verify it and update its own money ",
                    self.id)
                #msg.msg.blockchain[0].nounce = '223'
            if miner.verify_genesis_block():
                if self.debug:
                    print("verfied genesis block")
                self.update_unspent_btc_from_block(
                    miner.blockchain.blockchain[0])

        done = False
        die_out_seconds = 120
        timeout_seconds = 1
        start_time = time.time()
        last_block_cor = time.time()
        last_transaction_time = time.time()
        waited_time = 0
        debug_size = False
        debug_smt_contract = False
        debug_multi_transaction = False
        debug_smt_execute_once = False
        debug_smt_repeat = False
        smt_contract = False
        debug_block_creation_time = False
        debug_block_creation_time_num_of_nodes = False
        if debug_smt_contract and self.id == 0:
            debug_smt_execute_once = True
            smt_contract = True

        if debug_smt_contract and self.id == 1:
            debug_smt_repeat = True
            smt_contract = True

        if debug_size and self.id == 0:
            print(self.id, " size of block chain ", miner.blockchain.size())
        while not done:
            try:
                #print(self.id , "main checking for message")
                msg = msg_qs[self.id].get(block=True, timeout=timeout_seconds)
                waited_time = 0
                if msg.type == "Transaction":
                    #print(self.id,"Transaction has been received from ", msg.src )
                    if msg.msg.verify_sign_transaction():
                        miner.transactions_collected.append(
                            msg.msg)  ###check if already exist in blockchain
                        last_transaction_time = time.time()
                elif msg.type == "Block":
                    if self.debug:
                        print("Node ", self.id, "Block has been received from",
                              msg.src)
                    status = miner.add_block(msg.msg)

                    if status:
                        #print(self.id, " Received block has been added to blockchain ")
                        last_block_cor = time.time()
                    else:
                        print(self.id, " Received block was not added")
                else:
                    print(
                        "Node ", self.id,
                        " Received message of type , I dont do what do i do with it",
                        msg.type, msg.src)

            except Q.Empty:
                waited_time += timeout_seconds

                if waited_time > die_out_seconds:
                    print("waited for transactions for more than ",
                          die_out_seconds,
                          "  seconds, seems none is using bitcoin, lets die")
                    #print("I {} had a amount of {} BTC".format(str(self.id),str(self.btc)))
                    self.print_self_balance()
                    return
                else:
                    if time.time(
                    ) - last_transaction_time > 15 and self.last_transaction_verified:
                        if coin_toss(1.0 /
                                     self.N) and (not debug_smt_contract or
                                                  (debug_smt_contract and
                                                   (self.id in [0, 1, 3, 4]))):
                            #if True:
                            self.msg_ct_list.append(self.id)
                            if len(self.msg_ct_list) <= self.msg_ct_limit:
                                send_to = pick_receiver(self.id, self.N)
                                if debug_smt_contract and self.id == 0:
                                    send_to = 8
                                if debug_smt_contract and self.id == 1:
                                    send_to = 9
                                amount = random.randint(1, 4)
                                if debug_smt_execute_once and self.return_self_balance(
                                ) >= 700:
                                    amount = 100
                                    debug_smt_execute_once = False
                                    print(
                                        "############\nNode ", self.id,
                                        " : balance is ",
                                        self.return_self_balance(),
                                        " so as smart contract of execute once, sending ",
                                        amount, "btc to ", send_to,
                                        "\n############")
                                else:
                                    if debug_smt_repeat and self.return_self_balance(
                                    ) >= 700:
                                        amount = 100
                                        print(
                                            "############\nNode ", self.id,
                                            " : balance is ",
                                            self.return_self_balance(),
                                            " so as smart contract of repeat, sending ",
                                            amount, "btc to ", send_to,
                                            "\n############")
                                    else:
                                        amount = random.randint(1, 4)
                                unspent_key = None
                                for key in self.unspent_btc.keys():
                                    if amount + 3 <= self.unspent_btc[key][1]:
                                        unspent_key = key

                                if unspent_key is None:
                                    print("{} has no money left , so dying".
                                          format(str(self.id)))
                                else:
                                    #key = list(self.unspent_btc.keys())[0]
                                    #print("{} has amount {} btc in selected key".format(str(self.id),str(self.unspent_btc[unspent_key][1])))
                                    if debug_multi_transaction:
                                        send_to_v = pick_receiver(
                                            self.id, self.N)
                                        inputs = [
                                            Input(
                                                self.unspent_btc[unspent_key]
                                                [2],
                                                self.unspent_btc[unspent_key]
                                                [3])
                                        ]
                                        outputs = [
                                            Output(
                                                self.public_keys_of_nodes[
                                                    send_to].hex(), amount,
                                                self.hash_type),
                                            Output(
                                                self.public_keys_of_nodes[
                                                    send_to_v].hex(),
                                                amount + 2, self.hash_type),
                                            Output(
                                                self.public_keys_of_nodes[
                                                    self.id].hex(),
                                                self.unspent_btc[unspent_key]
                                                [1] - amount - amount - 2 - 1,
                                                self.hash_type)
                                        ]
                                        print(
                                            "Node {} Sending {} btc to node {} and {} btc to node {} "
                                            .format(str(self.id), str(amount),
                                                    str(send_to),
                                                    str(amount + 2),
                                                    str(send_to_v)))
                                    else:

                                        inputs = [
                                            Input(
                                                self.unspent_btc[unspent_key]
                                                [2],
                                                self.unspent_btc[unspent_key]
                                                [3])
                                        ]
                                        outputs = [
                                            Output(
                                                self.public_keys_of_nodes[
                                                    send_to].hex(), amount,
                                                self.hash_type),
                                            Output(
                                                self.public_keys_of_nodes[
                                                    self.id].hex(),
                                                self.unspent_btc[unspent_key]
                                                [1] - amount - 1,
                                                self.hash_type)
                                        ]

                                    transaction = Transaction(
                                        self.public_keys_of_nodes[self.id],
                                        inputs,
                                        outputs,
                                        self.private_key,
                                        t_type='Regular',
                                        hash_type=self.hash_type)
                                    for i in range(0, self.N):
                                        if i != self.id:
                                            msg_qs[i].put(
                                                Message(
                                                    "Transaction", transaction,
                                                    self.id, i))
                                    miner.transactions_collected.append(
                                        transaction)
                                    self.last_transaction_verified = False
                                    self.last_transaction_key = unspent_key
                                    #del self.unspent_btc[key] #### check for this and
                                    self.last_transaction_time = time.time()
                                    print("Node {} Sending {} btc to node {} ".
                                          format(str(self.id), str(amount),
                                                 str(send_to)))
                                    waited_time = 0

                    if time.time() - last_block_cor > self.block_creation_time:
                        #last_block_cor= time.time()
                        if coin_toss(1 * 1.0 / self.N):
                            #if True and self.id == 0:
                            print(self.id, " Creating a block ",
                                  len(miner.transactions_collected))

                            if debug_block_creation_time:
                                print("starting debug block time creatioin")
                                times = []
                                for i in range(0, 100):
                                    block_start_time = time.time()
                                    miner.create_block()
                                    block_end_time = time.time()
                                    times.append(block_end_time -
                                                 block_start_time)
                                print(self.id, " block chain creation times",
                                      times)

                            new_block = miner.create_block()
                            if new_block is not None:
                                #
                                if self.debug:
                                    print(
                                        self.id,
                                        " block has been created but first check if someone computed first"
                                    )
                                send_block_to_ee = False
                                empty_queue = False
                                temp_msgs = []
                                while not empty_queue:
                                    try:
                                        msg = msg_qs[self.id].get(
                                            block=True,
                                            timeout=timeout_seconds)
                                        if msg.type == "Block":
                                            if self.debug:
                                                print(
                                                    self.id,
                                                    " Ohh Received a block from ",
                                                    msg.src)

                                            miner.add_block(msg.msg)
                                            empty_queue = True
                                        else:
                                            temp_msgs.append(msg)
                                    except Q.Empty:
                                        send_block_to_ee = True
                                        empty_queue = True
                                        for msg in temp_msgs:
                                            msg_qs[self.id].put(
                                                Message(
                                                    msg.type, msg.msg, msg.src,
                                                    msg.dst)
                                            )  ## putting it back so can be fetched again in main loop

                                if send_block_to_ee:
                                    #if self.debug:
                                    waited_time = 0

                                    print(
                                        self.id,
                                        " No block has been recieved, so send it everyone"
                                    )
                                    print(self.id,
                                          " size of blockchain containing ",
                                          len(new_block.transactions),
                                          " and size of ",
                                          new_block.size_merkle())
                                    for i in range(0, self.N):
                                        if i != self.id:
                                            if self.debug:
                                                print(
                                                    self.id,
                                                    " sending created block to ",
                                                    i)
                                            msg_qs[i].put(
                                                Message(
                                                    "Block", new_block,
                                                    self.id, i))
                                    miner.add_block(new_block)
                                #last_block_cor = time.time()

                        res = miner.increase_verified_block()
                        #print(self.id, "after adding status",res)
                        last_block_cor = time.time()
                        if res:
                            if debug_size and self.id == 0:
                                print(self.id,
                                      " size of block chain after adding ",
                                      miner.blockchain.size())
                            self.update_unspent_btc_from_block(
                                miner.blockchain.blockchain[
                                    miner.blockchain.confirmed_block_index]
                            )  ## it will
                            ## also need to check if last payment by this node is verified
                            self.print_self_balance()
Ejemplo n.º 27
0
# -*- coding: utf-8 -*-
"""
Created on Thu Oct  4 09:04:35 2018

@author: Vitor Eller
"""

from BlockChain import BlockChain

transactions = [{
    'value': '500',
    'sender': 'eller',
    'receiver': 'henry'
}, {
    'value': '100',
    'sender': 'henry',
    'receiver': 'lipe'
}]

my_chain = BlockChain()

my_chain.print_chain_content()

my_chain.add_block(transactions)

my_chain.print_chain_content()
Ejemplo n.º 28
0
    def testMethods(self):
        genesis = Block(b'', scroogePubKey)
        genesis.finalize()
        blockChain = BlockChain(genesis)
        blockHandler = BlockHandler(blockChain)
        
        # Genesis block test
        self.assertEqual(genesis.getHash(), blockChain.getMaxHeightBlock().getHash(), \
                         'genesis should be max height block')
        self.assertEqual(blockChain.getMaxHeightBlock(), genesis, \
                         'genesis should be max height block')
        self.assertEqual(len(blockChain.getMaxHeightUTXOPool().getAllUTXO()), 1, \
                         'UTXOPool should have one output')
        self.assertEqual(len(blockChain.getTransactionPool().getTransactions()), 0, \
                         'transaction pool should be empty')

        # Spend the genesis coinbase transaction in many outputs
        tx = Transaction()
        tx.addInput(genesis.getCoinbase().getHash(), 0)
        numGenOuts = int(COINBASE)
        for i in range(numGenOuts):
            tx.addOutput(1.0, scroogePubKey)
        signInput(tx, scroogePriKey, 0)
        tx.finalize()
        
        # Add one transaction test. No block has been added.
        blockHandler.processTx(tx)       
        self.assertEqual(blockChain.getMaxHeightBlock(), genesis, \
                         'genesis should be max height block')
        self.assertEqual(len(blockChain.getMaxHeightUTXOPool().getAllUTXO()), 1, \
                         'UTXOPool should have one output')
        self.assertEqual(len(blockChain.getTransactionPool().getTransactions()), 1, \
                         'transaction pool should have one entry')
        self.assertIsNotNone(blockChain.getTransactionPool().getTransaction(tx.getHash()), \
                            'tx should be in txPool')
        
        # Build out the chain
        depth = 15;
        chainedBlocks = []
        for i in range(depth):
            # Spend the new outputs, one tx per block
            tx2 = Transaction()
            tx2.addInput(tx.getHash(), i)
            tx2.addOutput(1.0, scroogePubKey)
            signInput(tx2, scroogePriKey, 0)
            tx2.finalize()
            blockHandler.processTx(tx2);
            chainedBlocks.append(blockHandler.createBlock(scroogePubKey))
            
            # Deep chain test
            self.assertIsNotNone(chainedBlocks[i], 'ith block should exist')
            self.assertEqual(blockChain.getMaxHeightBlock(), chainedBlocks[i], \
                             'ith block should be max height')
            self.assertEqual(len(blockChain.getMaxHeightUTXOPool().getAllUTXO()), numGenOuts + i + 1, \
                             'wrong number UTXOs when i = ' + str(i))
            self.assertEqual(len(blockChain.getTransactionPool().getTransactions()), 0, \
                             'txPool should be empty')
        
        # Remember the current max height block
        maxBlockBefore = blockChain.getMaxHeightBlock()
        
        # Make another block on the deepest block that should still work
        sideBlock = Block(chainedBlocks[depth - CUT_OFF_AGE - 1].getHash(), scroogePubKey)
        sideBlock.finalize()
        retVal = blockChain.addBlock(sideBlock)
        
        # Add valid side chain block test
        self.assertTrue(retVal, 'side block should have been added')
        self.assertEqual(blockChain.getMaxHeightBlock(), maxBlockBefore, \
                         'max height block should not have changed')
        
        # Make another block that is too deep
        tooDeep = Block(chainedBlocks[depth - CUT_OFF_AGE - 2].getHash(), scroogePubKey)
        tooDeep.finalize()
        retVal2 = blockChain.addBlock(tooDeep)
        
        # Too deep test
        self.assertFalse(retVal2, 'too deep block should not be added')
 
        # Build on the side chain
        prevBlock = sideBlock
        for i in range(CUT_OFF_AGE - 1):
            # Spend the previous coinbase transaction
            tx2 = Transaction();
            tx2.addInput(prevBlock.getCoinbase().getHash(), 0)
            tx2.addOutput(10.0, scroogePubKey)
            signInput(tx2, scroogePriKey, 0)
            tx2.finalize();
            
            newBlock = Block(prevBlock.getHash(), scroogePubKey)
            newBlock.addTransaction(tx2)
            newBlock.finalize()
            retVal3 = blockChain.addBlock(newBlock)
            
            self.assertTrue(retVal3, 'side blocks should be added')
            
            prevBlock = newBlock
            
        # The side chain should be the same length as the previous chain
        # and so the max height block should not have changed.
        self.assertEqual(blockChain.getMaxHeightBlock(), maxBlockBefore, \
                    'max height block should not be changed')
        
        # Now add another to the side chain, making it the new highest
        # Spend the previous coinbase transaction
        tx3 = Transaction()
        tx3.addInput(prevBlock.getCoinbase().getHash(), 0)
        tx3.addOutput(10.0, scroogePubKey)
        signInput(tx3, scroogePriKey, 0)
        tx3.finalize()
        
        newBlock = Block(prevBlock.getHash(), scroogePubKey)
        newBlock.addTransaction(tx3)
        newBlock.finalize()
        retVal3 = blockChain.addBlock(newBlock)
        
        self.assertTrue(retVal3, 'block should be added')
        self.assertNotEqual(blockChain.getMaxHeightBlock(), maxBlockBefore, \
                         'max height block should be changed')
        self.assertEqual(blockChain.getMaxHeightBlock(), newBlock, \
                         'max height block should be the new block')
Ejemplo n.º 29
0
import socket
import select
import errno
import sys
from BlockChain import BlockChain
from Block import Block  
from Validations import isChainValid
from Cuenta import Cuenta
from tipoTrans import tipoTrans

Chain = BlockChain(2) 
# transfer valeria 20
# mining block 
# new block  info del bloque
# Collision 


def typeMessage(username,message):
    vec = message.split(" ")
    if(vec[0] == "transfer"):
        fromAdd = Chain.find(username)
        toAdd = Chain.find(vec[1])
        val = int(vec[2])
        Chain.createTransaction(fromAdd,toAdd,tipoTrans.TRANSFERENCIA, val)
        return 0

    elif (vec[0] == "newBlock"):
        for c in Chain.pendingTransactions:
            c.execute()
        blocklineal = transform(vec[1],Chain.pendingTransactions)
        Chain.pendingTransactions = []
Ejemplo n.º 30
0
class Node:

    def __init__(self, node_id: str):
        """
        Constructor for the Node class.
        Synchronizes nodes.
        Starts messaging and mining threads.
        Creates files to store data.

        :param str node_id: one of '0', '1', '2', or '3', the possible nodes in network
        """
        self.node_id = node_id
        self.file_path = '../files/blockchain' + node_id + '.txt'
        self.ledger = Ledger(node_id)
        self.blockchain = BlockChain(self.node_id, self.ledger)
        self.probability = 0.1
        self.term_duration = 25
        self.le = LeaderElection(self.node_id)
        self.leader_counts = {'0': 0, '1': 0, '2': 0, '3': 0}
        # self.elected_boolean = False

        self.peers = [peer for peer in ['0', '1', '2', '3'] if peer != self.node_id]
        self.transaction_queue = []

        self.received_blocks = collections.deque()
        self.secret_message = b'SECRET TUNNEL!'
        self.nodes_online = []

        self.all_public_keys = {}
        self.private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
            backend=default_backend()
        )
        self.sig = self.private_key.sign(
            self.secret_message,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        ).hex()
        self.peer_signatures = {}
        self.all_public_keys[self.node_id] = self.private_key.public_key()
        self.messenger = Messenger(self.node_id, self)
        self.sync_nodes()
        self.genesis_time = 'not set'
        self.term = 0

    def sync_nodes(self):
        """
        Method to synchronize all nodes for receiving and sending messages over the queue.
        Blockchain cannot start until all nodes are live and have generated their private/public key pairs.
        """
        start_time = datetime.now()
        self.nodes_online.append(start_time)
        self.send_blockchain_msg(type='sync', contents={'start_time': str(start_time)})

        public_key_string = self.all_public_keys[self.node_id].public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        ).decode("utf-8")
        self.send_blockchain_msg(type='key',
                                 contents={'key': public_key_string, 'sender': self.node_id, 'signature': self.sig})

    def start_mining_thread(self) -> Thread:
        """
        Starts the thread that continually mines new blocks to add to the chain.

        :return: mining thread
        """
        t = Thread(
            target=self.mining_thread,
            name=('Mining Threads' + self.node_id)
        )
        t.start()
        print('Mining thread started.')
        return t

    def mining_thread(self):
        """
        Waits to start mining until all nodes are initialized.
        Calculates current term based on genesis time and timestamp.
        Starts mining a block every time a new term begins (e.g. every 20 or 25 seconds)
        :return:
        """
        while True:
            if self.genesis_time != 'not set':
                term = self.term
                time_diff = datetime.now() - self.genesis_time
                time_diff = time_diff.seconds
                new_term = math.ceil(time_diff / self.term_duration)
                if new_term > term:
                    # reset all flags
                    self.term = new_term
                    self.mine_block()

    def mine_block(self):
        """
        The actual mining of a block.

        Generates a block with a certain probability, if a block was generated, the node requests leadership.
        Leadership is granted through the RAFT algorithm, which has been slightly adjusted to suit this purpose.
        Whichever node was elected sends generated block to all other nodes for verification and signing.
        """
        sleep(random.random() * 2)
        mined_probability = random.random()

        if mined_probability > self.probability and len(self.transaction_queue) != 0:
            tx_to_mine = self.transaction_queue
            new_index = self.blockchain.get_last_block().index + 1
            verify_boolean, change_or_bad_tx = self.ledger.verify_transaction(tx_to_mine, new_index)
            while not verify_boolean:
                self.transaction_queue = [tx for tx in self.transaction_queue if tx.unique_id not in change_or_bad_tx]
                verify_boolean, change_or_bad_tx = self.ledger.verify_transaction(tx_to_mine, new_index)
            new_block = Block(index=new_index, transactions=tx_to_mine)
            to_node = self.peers[random.randrange(len(self.peers))]

            self.le.request_leadership()
            sleep(5)
            if self.le.election_state != 'leader':
                return
            sleep(.5)
            print('I have been elected as leader.')
            self.send_peer_msg(type='Block',
                               contents={'block': str(new_block), 'leader_id': self.node_id, 'term': self.term,
                                         'history': json.dumps([self.node_id])}, peer=to_node)
            print(self.node_id, " has mined and sent a block to ", to_node)

            self.le.release_leadership()

    def handle_incoming_message(self, msg: dict):
        """
        Handles incoming messages from the Messenger class in dictionary format.
        Four types of messages exist: Transactions, Blocks, Sync, and Key messages.

        :param msg: dict. Message attributes represented as string key value pairs.
        :return: None
        """

        if msg['type'] == 'Transaction':  # if transaction append to tx queue
            contents = msg['contents']
            self.transaction_queue.append(Transaction(contents))

        elif msg['type'] == 'Block' and self.genesis_time != 'not set':  # if block process and reset mine function if valid
            msg_dict = json.loads(msg['contents'])
            incoming_block = Block(msg_dict['block'])
            leader_id = msg_dict['leader_id']
            block_term = int(msg_dict['term'])
            block_history = json.loads(msg_dict['history'])
            # print("\nIncoming Block received: \n", incoming_block, block_term, leader_id, '\n incoming term : ', block_term)
            self.process_incoming_block(block=incoming_block, term=block_term, leader_id=leader_id,
                                        block_history=block_history)

        elif msg['type'] == 'sync':
            msg_dict = json.loads(msg['contents'])
            start_time = date_parser.parse(msg_dict['start_time'])
            self.nodes_online.append(start_time)
            if len(self.nodes_online) > 3:
                # print("synched!")
                self.genesis_time = max(self.nodes_online)
                print('genesis time = ', self.genesis_time)

        elif msg['type'] == 'key':
            msg_dict = json.loads(msg['contents'])
            sender = msg_dict['sender']
            sig = msg_dict['signature']
            key_string = msg_dict['key'].encode("utf-8")

            incoming_public_key = serialization.load_pem_public_key(
                key_string,
                backend=default_backend()
            )
            self.all_public_keys[sender] = incoming_public_key
            self.peer_signatures[sig] = sender

    def add_to_blockchain(self, block, leader_id):
        """
        Method to add a block to the blockchain after it has been verified.
        Deletes block transactions from transaction queue to avoid double transactions.
        Keeps track of whichever node generated a block to determine whether generation rate exceeds probability.

        :param block: The block to be added, contains transactions to be removed
        :param leader_id: Who generated the block
        :return:
        """
        self.blockchain.add_block(block)
        self.ledger.add_transactions(block.transactions, block.index)
        if self.node_id == leader_id:
            print("leader ", self.node_id, "added block to blockchain")
        else:
            print("follower ", self.node_id, "added block to blockchain")
        self.leader_counts[leader_id] += 1
        # if the block is valid, then we need to remove all transactions from our own tx queue
        delete_transactions = copy.deepcopy(block.transactions)
        self.transaction_queue = [x for x in self.transaction_queue if x not in delete_transactions]

    def verify_all_signatures(self, block: Block) -> bool:
        """
        Verifies encoded signatures by using a secret message.
        This ensures the message came from one of the known, i.e., trustworthy nodes, by decoding using saved public keys.

        :param block:
        :return:
        """
        signatures = block.signatures
        valid_sig_count = 0
        for sig in signatures.keys():
            for public_key in self.all_public_keys.values():
                # print('what is this key: ', type(public_key), public_key)
                try:
                    public_key.verify(
                        bytes.fromhex(sig),
                        self.secret_message,
                        padding.PSS(
                            mgf=padding.MGF1(hashes.SHA256()),
                            salt_length=padding.PSS.MAX_LENGTH
                        ),
                        hashes.SHA256()
                    )
                    valid_sig_count += 1
                    print("signature validated!")
                except cryptography.exceptions.InvalidSignature:
                    pass
        if len(signatures) == valid_sig_count:
            return True
        else:
            return False

    def process_incoming_block(self, block: Block, term: int, leader_id: str, block_history: list):
        """
        check if incoming block is sufficently staked. If so add to blockchain. Otherwise, if leader send it for more
        signatures. if follower, sign and send back to leader.

        :param block: block in question
        :param term: blockchain cycle identifier
        :param leader_id: who generated the block
        :param block_history: List of nodes that have signed the block
        :return: None
        """
        # process block returns true if it is valid and added to blockchain and ledger
        if term == self.term and block.index == self.blockchain.get_last_block().index + 1:  # and self.verify_all_signatures(block):
            # if node is a follower
            if self.node_id != leader_id:
                # Check if there is enough stake
                if block.verify_proof_of_stake():
                    self.add_to_blockchain(block, leader_id)

                else:
                    # verify transactions through ledger
                    valid_boolean, change_or_bad_tx = self.ledger.verify_transaction(block.transactions, block.index)
                    # Check node that sent the block does not exceed generation rate. Otherwise, no block is added.
                    # This prevents a node from sending too many blocks (i.e., taking control of the chain).
                    if (self.leader_counts[leader_id] / self.term) < self.probability:
                        if valid_boolean and self.sig not in block.signatures.keys():
                            print('Signing block with stake: ', sum([tx.amount for tx in block.transactions]) / 2 + .1)
                            block.signatures[self.sig] = sum([tx.amount for tx in block.transactions]) / 2 + .1
                            block_history.append(self.node_id)
                            contents = {'block': str(block), 'leader_id': leader_id, 'term': str(term),
                                        'history': json.dumps(block_history)}

                            if block.verify_proof_of_stake():
                                self.send_peer_msg(type='Block', contents=contents, peer=leader_id)
                            else:
                                options = [peer for peer in self.peers if peer not in block_history]
                                to_node = options[random.randrange(len(options))]
                                self.send_peer_msg(type='Block', contents=contents, peer=to_node)
            # Node is leader
            else:
                # Check if there is enough stake
                if block.verify_proof_of_stake():
                    self.add_to_blockchain(block, leader_id)
                    rewardees = [self.peer_signatures[sig] for sig in block.signatures.keys()]
                    rewardees.append(self.node_id)
                    print('Reward these hard working folx: ', rewardees)
                    for peer in rewardees:
                        reward_tx = str(Transaction(_to=peer, _from='reward', amount=1))
                        for destination in ['0', '1', '2', '3']:
                            self.messenger.send({'type': 'Transaction', 'contents': reward_tx}, destination)

                # if stake was sufficient, block will be complete, otherwise block will go get more signatures
                else:
                    print("leader ", self.node_id, "needs more signatures")
                self.send_blockchain_msg(type='Block',
                                         contents={'block': str(block), 'leader_id': leader_id, 'term': term,
                                                   'history': json.dumps(block_history)})

    def send_blockchain_msg(self, contents: dict, type: str):
        """
        sends msgs to all peers

        :param contents: str. Newly mined blocks or new transactions in JSON string representation.
        :param type: str. indicates type of msg. 'Block' or 'Transaction'
        :return: None
        """
        # send block to all known peers
        msg_dict = {'contents': json.dumps(contents), 'type': type}
        for peer in self.peers:
            self.messenger.send(msg_dict, peer)

    def send_peer_msg(self, contents: dict, type: str, peer: str):
        """
        sends msgs to specific peer

        :param contents: str. ANYTHING YOU DAMN PLEASE
        :param type: str. indicates type of msg. 'Block' or 'Transaction'
        :param peer: str. destination
        :return: None
        """
        msg_dict = {'contents': json.dumps(contents), 'type': type}
        self.messenger.send(msg_dict, peer)
Ejemplo n.º 31
0
from BlockChain import BlockChain
from Block import Block

blockchain = BlockChain()

print(">>>>> Before Mining...")
print(blockchain.chain)

last_block = blockchain.get_last_block
last_proof = last_block.proof
proof = blockchain.create_proof_of_work(last_proof)

# Sender "0" means that this node has mined a new block
# For mining the Block(or finding the proof), we must be awarded with some amount(in our case this is 1)

blockchain.create_new_transaction(
    sender="0",
    recipient="address_x",
    amount=1,
)

last_hash = last_block.get_block_hash()
block = blockchain.create_new_block(proof, last_hash)

print(">>>>> After Mining...")
print(blockchain.chain)