def mineInvalidBlock(self, tx: Transaction, isInvalidPrevHash = False, isInvalidPOW = False) -> None: """ This function is only used for testing. mine a new invalid block with the tx, either prev_hash or pow is invalid """ if not isInvalidPrevHash and not isInvalidPOW: return # tx not valid if not self.verifyTx(tx): # because this transaction is already in the ledger if not self.__verifyTxNotOnBlockchain(tx): log.error("Node " + self.id + " :" + "Tx Verification Failed! This Tx is already on the ledger") return blockPow = str(self.miningDifficulty + 1) hashTarget = self.miningDifficulty prevBlock = self.latestBlockTreeNode prevHash = sha256(prevBlock.nowBlock.toString().encode('utf-8')).hexdigest() txAndPrevHashMsg = tx.toString() + prevHash nonce = 0 while int(blockPow, base=16) > hashTarget: blockMessage = txAndPrevHashMsg + str(nonce) blockPow = sha256(blockMessage.encode('utf-8')).hexdigest() nonce += 1 nonce -= 1 newBlock = Block(tx, prevHash, nonce, blockPow) if isInvalidPrevHash: newBlock.prev += "1" # make the prev hash invalid elif isInvalidPOW: newBlock.pow = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" newBlockTreeNode = BlockTreeNode(prevBlock, newBlock, self.latestBlockTreeNode.blockHeight + 1) self.__updateNewMinedBlock(newBlock, newBlockTreeNode)
def data_blockchain(): blockchain = Blockchain() blockchain_table = table("blockchain", "number", "hash", "previous", "data","time", "nonce") for b in blockchain_table.getall(): blockchain.add(Block(int(b.get('number')), b.get('previous'), b.get('data'), b.get('time'),int(b.get('nonce')))) return blockchain
def bitcoin_tests(): bc = BitcoinBlockchain() bc.genesis() for i in range(10): block = Block(bc.last_block, 1) bc.add_block(block) print(bc)
def check_chain(): blockchain = Blockchain() database = ["hello", " here"] num = 0 for data in database: num += 1 blockchain.mine(Block(number=num, data=data)) update_blockchain(blockchain)
def create_test_blockchain(): miner_one = Miner(None, 1, [], 2, 0, None, None) miner_two = Miner(None, 1, [], 2, 1, None, None) b = Blockchain() block_one = generate_block_on_longest_chain(b.last_block[0], miner_one) b.extend(block_one) b.extend(generate_block_on_longest_chain(b.last_block[0], miner_one)) edge1 = generate_block_on_longest_chain(b.last_block[0], miner_one) b.extend(edge1) edge2 = Block([], 2, block_one, 2, miner_two) b.extend(edge2) return b, edge1, edge2, miner_one, miner_two
def verify_and_add_block(): block_data = request.get_json() block = Block(block_data["index"], block_data["transactions"], block_data["timestamp"], block_data["previous_hash"], block_data["nonce"]) proof = block_data['hash'] added = blockchain.add_block(block, proof) if not added: return "The block was discarded by the node", 400 return "Block added to the chain", 201
def create_chain_from_dump(chain_dump): generated_blockchain = Blockchain() generated_blockchain.create_genesis_block() for idx, block_data in enumerate(chain_dump): if idx == 0: continue # skip genesis block block = Block(block_data["index"], block_data["transactions"], block_data["timestamp"], block_data["previous_hash"], block_data["nonce"]) proof = block_data['hash'] added = generated_blockchain.add_block(block, proof) if not added: raise Exception("The chain dump is tampered!!") return generated_blockchain
def mine(): #Last proof of work last_block = blockchain[len(blockchain) - 1] last_proof = json.loads(last_block.data)['proof-of-work'] #The program will be stuck here #until a new valid proof of work #is found proof = proof_of_work(last_proof) #Once the proof is valid, new block #can be added and miner can be rewarded transaction_list.append( json.dumps(Transaction("network-reward", miner_address, 1).reprJSON(), cls=ComplexEncoder) ) #Data needed to create a new block new_block_data = json.dumps({ "proof-of-work": proof, "transactions": json.dumps(list(transaction_list), cls=ComplexEncoder) }, cls=ComplexEncoder) #Clear the transaction list transaction_list[:] = [] #New block mined_block = Block( last_block.index + 1, datetime.datetime.now(), new_block_data, last_block.hash ) blockchain.append(mined_block) #Response for new block mined return json.dumps(mined_block.reprJSON(), cls=ComplexEncoder) + "\n"
def extend_with_reference(self, block: Block) -> None: def iteratore_backwards_block(block_to_iterate): while block_to_iterate is not None: yield block_to_iterate block_to_iterate = block_to_iterate.previous_block for edge in self.edges: for b in iteratore_backwards_block(edge): if b == block.previous_block: block = block.copy(b) return self.extend(block) elif b.block_num < block.previous_block.block_num: break raise ValueError("There must be some error here")
def run(self): # Broadcast genesis blockchain without interference block = Block.genesis_block(self.difficulty) blockchain = Blockchain(block) self.broadcast(pickle.dumps(blockchain), interference=False) # Starting line for miners self.starting_line = threading.Barrier(total_miners + 1) # Start miners for miner in self.miners: miner.start() self.starting_line.wait() # Start mining once all miners ready self.stop_event.wait()
def test_creating_edges_correctly(): """ create a blockchain: 1 -> 2 -> 3 -> 2 :return: """ b, edge1, edge2, miner_one, miner_two = create_test_blockchain() assert len(b.edges) == 2 assert b.edges[0] == edge1 assert b.edges[1] == edge2 assert b.edges[1].previous_block == b.edges[ 0].previous_block.previous_block edge1 = Block([], 4, b.last_block[0], 4, miner_one) b.extend(edge1) assert b.edges[0] == edge1
def send_money(sender, recipient, amount): #verify that the amount is an integer or floating value try: amount = float(amount) except ValueError: raise InvalidTransactionException("Invalid Transaction.") if amount > get_balance(sender) and sender != "ROOT": raise InsufficientFundsException("Insufficient Funds.") elif sender == recipient or amount <= 0.00: raise InvalidTransactionException("Invalid Transaction.") elif isnewuser(recipient): raise InvalidTransactionException("User Does Not Exist.") blockchain = data_blockchain() number = len(blockchain.chain) + 1 data = "%s-->%s-->%s" %(sender, recipient, amount) blockchain.mine(Block(number, data=data)) update_blockchain(blockchain)
def create_chain_from_dump(chain_dump): """ Internally calls the `register_node` endpoint to register current node with the remote node specified in the request, and sync the blockchain as well with the remote node. Args: chain_dump (JSON): chain dump. Raises: Exception: If the chain was tempered. Returns: Object: retrns Blockchain """ blockchain = Blockchain() for index, block_data in enumerate(chain_dump): block = Block(block_data["index"], block_data["transactions"], block_data["timestamp"], block_data["previous_hash"]) proof = block_data["hash"] # Exclude the genesis block if index > 0: added = blockchain.add_block(block, proof) if not added: raise Exception("The chain dump is tampered!!") # For the genesis block else: blockchain.chain.append(block) return blockchain
def mineBlock(self, tx: Transaction) -> None: # mine a new block with the tx # tx not valid if not self.verifyTx(tx): # because this transaction is already in the ledger if not self.__verifyTxNotOnBlockchain(tx): log.error("Node " + self.id + " :" + "Tx Verification Failed! This Tx is already on the ledger") return blockPow = str(self.miningDifficulty + 1) hashTarget = self.miningDifficulty prevBlock = self.latestBlockTreeNode prevHash = sha256(prevBlock.nowBlock.toString().encode('utf-8')).hexdigest() txAndPrevHashMsg = tx.toString() + prevHash nonce = 0 while int(blockPow, base=16) > hashTarget: blockMessage = txAndPrevHashMsg + str(nonce) blockPow = sha256(blockMessage.encode('utf-8')).hexdigest() nonce += 1 nonce -= 1 newBlock = Block(tx, prevHash, nonce, blockPow) newBlockTreeNode = BlockTreeNode(prevBlock, newBlock, self.latestBlockTreeNode.blockHeight + 1) self.__updateNewMinedBlock(newBlock, newBlockTreeNode)
def __verifyBlockPrevHash(self, prevBlock: Block, newBlock: Block) -> bool: prevEncode = prevBlock.toString().encode('utf-8') prevHash = sha256(prevEncode).hexdigest() __flag = prevHash == newBlock.prev return __flag
def run(self): # Get initial blockchain from mailbox self.blockchain = pickle.loads(self.read_mail()) # Construct miner payload comment comment = "I, miner number {:d}, did this!".format(self.id_number) # Wait for supervisor's go signal self.supervisor.starting_line.wait() # Start mining! while not self.stopped: # Create new block miner wants on chain # Get latest block latest_block = self.blockchain.latest_block # Create hash pointer for block hash_pointer = latest_block.hash().digest() # Get milliseconds for block time_stamp = get_ms_since_epoch() # At this point the comment should be gotten, but it has already been made # comment = comment # Get new counter by incrementing old counter new_counter = latest_block.counter + 1 # Get difficulty from latest block difficulty = latest_block.difficulty # Get nonce, but it is not known yet! no_nonce = b"" # Calculate base hash no_nonce_block = Block( hash_pointer , time_stamp , comment , new_counter , difficulty , no_nonce ) base_hash = no_nonce_block.hash() # Create new slave to find good nonce self.slave = Slave(self, base_hash, difficulty) self.slave.start() while True: # Wait for notification from: # - Supervisor stopping the "gold rush"/mining # - Other miners sending messages # - Slave having found nonce self.wait() # Check if supervisor announced stop if self.stopped: break # Read mail if self.has_mail(): with self.mailbox_lock: blockchain_replaced = False while self.has_mail(): # Read messages message = self.read_mail() received_blockchain = pickle.loads(message) if len(received_blockchain) > len(self.blockchain): # Take up blockchain if bigger self.blockchain = received_blockchain blockchain_replaced = True if blockchain_replaced: self.supervisor.refresh.set() break # Check on slave if not self.slave.is_alive(): # Slave has found nonce! self.slave.join() if self.stopped: break block = Block( hash_pointer , time_stamp , comment , new_counter , difficulty , self.slave.result ) self.blockchain.append(block) self.blockchain.verify() self.supervisor.refresh.set() self.supervisor.broadcast(pickle.dumps(self.blockchain), exclude=self) break # Take care of the slave self.slave.stop() self.slave.join()
def generate_block_on_longest_chain(prev_block, miner): return Block([], prev_block.block_time + 1, prev_block, prev_block.block_num + 1, miner)