def create_block(cls): last_block = Block.last() previous_hash = last_block.block_id proof_of_work = ProofOfWork(previous_hash, 10) proof_result = proof_of_work.prove() if not proof_result.isValid(): raise Exception('fail proof') transactions = UnconfirmedTransactionPool.transactions.copy() UnconfirmedTransactionPool.transactions.clear() block_number = len(Block.list()) + 1 block = Block.build( block_number = block_number, version = "1", previous_block_hash = previous_hash, timestamp = datetime.now().timestamp(), merkle_root = "", # TODO difficulty_target = 10, nonce = proof_result.nonce, transactions = transactions ) for tx in transactions: tx.block_id = block.block_id Block.create_block(block) db.session.commit() transaction = cls._create_transaction_to_miner() return block, proof_result, transaction
def test_block_mining(self): # Create example block h = "some hash" data = "some random data" block = Block(h, 0, [data], "1234") block.mine() self.assertEqual( block.block["hash"], "00015080dc53b9ab05840ec3cbebe26bb4c13059b9b8c828404a730fa32e134c")
def _resolve_conflicts(cls, send_node_url): json = requests.get(send_node_url + '/blocks').json() send_node_blocks = decode_blocks(json) my_node_blocks = Block.list() forked_block_number = cls._search_forked_block_number(send_node_blocks, my_node_blocks) deleting_blocks = list(filter(lambda block: block.block_number > forked_block_number, my_node_blocks)) adding_blocks = list(filter(lambda block: block.block_number > forked_block_number, send_node_blocks)) Block.delete_blocks(deleting_blocks) Block.create_blocks(adding_blocks)
def block_delete(): meta = {} ids = request.values.get('ids', '') type = request.values.get('type', 1) if not ids: return jsonify(success=False, message='缺少请求参数!') try: arr = ids.split(',') for d in arr: block = Block.objects(_id=ObjectId(d)).first() if block: is_pass = check_role(block.role) if is_pass: block.mark_delete() if block else None except (Exception) as e: return jsonify(success=False, message=str(e)) return jsonify(success=True, message='操作成功!', data={ 'ids': ids, 'type': type }, redirect_to=url_for('admin.block_list'))
def receive_block(cls, block, proof_result, send_node_url): last_block = Block.last() if not proof_result.isValid(): raise Exception('received block is invalid') if last_block.block_id != block.previous_block_hash: if last_block.block_number < block.block_number: print('resolving conflicting...') cls._resolve_conflicts(send_node_url) if last_block.block_id == block.previous_block_hash: Block.create_block(block) UnconfirmedTransactionPool.transactions.clear() db.session.commit()
def test_block_creation(self): # Create genesis transaction transaction = Transaction("Genesis Addr", "Genesis Block") key = RSA.generate(1024) miner_id = "1234" # Create genesis block with genesis transaction, signing it genesis = Block("Genesis Block", 0, [transaction.get_signed_json(key)], miner_id) self.assertDictEqual( genesis.get_json(), { "miner": miner_id, "hash": "", "prevHash": "Genesis Block", "height": 0, "nonce": 0, "data": [transaction.get_signed_json(key)] })
def decode_block(dictionary): return Block(block_id=dictionary['block_id'], block_number=dictionary['block_number'], previous_block_hash=dictionary['previous_block_hash'], timestamp=dictionary['timestamp'], merkle_root=dictionary['merkle_root'], difficulty_target=dictionary['difficulty_target'], nonce=dictionary['nonce'], transactions=list( map(lambda tx_dict: decode_transaction(tx_dict), dictionary['transactions'])))
def block_list(): meta = { 'title': '配置管理', 'css_nav_sub_block': 'active', 'css_nav_system': 'active' } query = {} page = int(request.args.get('page', 1)) per_page = 20 status = int(request.args.get('status', 0)) deleted = int(request.args.get('deleted', 0)) page_url = url_for('admin.block_list', page="#p#", status=status) if status == -1: meta['css_disable'] = 'active' query['status'] = 0 elif status == 1: query['status'] = 1 meta['css_verify'] = 'active' elif status == 5: query['status'] = 5 meta['css_success'] = 'active' else: meta['css_all'] = 'active' query['deleted'] = deleted current_app.logger.debug(type(g.user)) data = Block.objects(**query).order_by('-created_at').paginate( page=page, per_page=per_page) total_count = Block.objects(**query).count() meta['data'] = data.items pager = Pager(page, per_page, total_count, page_url) meta['pager'] = pager.render_view() return render_template('admin/block/list.html', meta=meta)
def sync_local(): node_blocks = [] # Assuming that the folder and at least initial block exists data_dir = get_data_directory() if os.path.exists(data_dir): for filename in os.listdir(data_dir): # Check on the files that are stored in the required format. # No need to look in all the files if filename.endswith('.json'): filepath = '%s/%s' % (data_dir, filename) with open(filepath, 'r') as block_file: block_info = json.load(block_file) block_object = Block(**block_info) node_blocks.append(block_object) return node_blocks
def decode_block(dictionary): if dictionary['transactions'] is not None: transactions = decode_transactions(dictionary['transactions']) else: transactions = None return Block( block_id = dictionary['block_id'], block_number = dictionary['block_number'], version = dictionary['version'], previous_block_hash = dictionary['previous_block_hash'], timestamp = dictionary['timestamp'], merkle_root = dictionary['merkle_root'], difficulty_target = dictionary['difficulty_target'], nonce = dictionary['nonce'], transactions = transactions )
def get_block_content(mark, type=1): content = '' if not mark: return content try: query = {'mark': mark, 'status': 1} item = Block.objects(**query).first() if not item: return content if type == 1: content = item.code else: content = item.content return content except (Exception) as e: return content
def mine(last_block): index = int(last_block.index) + 1 timestamp = datetime.utcnow() # random string for now data = "I block #%s" % (int(last_block.index) + 1) prev_hash = last_block.hash nonce = 0 block_hash = calculate_hash(index, prev_hash, data, timestamp, nonce) while str(block_hash[0:num_zeores]) != '0' * num_zeores: nonce += 1 block_hash = calculate_hash(index, prev_hash, data, timestamp, nonce) block_data = {} block_data['index'] = int(last_block.index) + 1 block_data['timestamp'] = timestamp block_data['data'] = "I block #%s" % last_block.index block_data['prev_hash'] = last_block.hash block_data['hash'] = block_hash block_data['nonce'] = nonce return Block(**block_data)
def block_submit(): meta = { 'title': '配置管理', 'css_nav_sub_block': 'active', 'css_nav_system': 'active' } meta['referer_url'] = request.environ.get( 'HTTP_REFERER') if request.environ.get('HTTP_REFERER') else '' id = request.args.get('id', None) meta['data'] = None if id: block = Block.objects(_id=ObjectId(id)).first() meta['data'] = block form = SaveForm() #current_app.logger.debug(id) return render_template('admin/block/submit.html', meta=meta, form=form)
def create_and_add_block(self, miner_id): """ Using miner_id and current transaction_pool, create block and add to chain. """ block = None if not self.empty(): # Get last block prevBlock = self.storage[-1] # Use it to create new block with the current transactions in pool block = Block(prevBlock["hash"], prevBlock["height"] + 1, self.transaction_pool, miner_id) block.mine() logger.info("Block created: {}".format(block.get_json())) self.validate_and_add_block(block.get_json()) return block
def sync_overall(save=False): best_chain = Chain(sync_local()) for peer in PEERS: # try to connect to peer peer_blockchain_url = peer + 'blockchain.json' try: r = requests.get(peer_blockchain_url) peer_blockchain_dict = r.json() peer_blocks = [Block(**bdict) for bdict in peer_blockchain_dict] peer_chain = Chain(peer_blocks) if peer_chain.is_valid() and peer_chain > best_chain: best_chain = peer_chain except requests.exceptions.ConnectionError: print "Peer at %s not running. Continuing to next peer." % peer print "Longest blockchain is %s blocks" % len(best_chain) # for now, save the new blockchain over whatever was there if save: best_chain.save() return best_chain
def seed(cls): timestamp = 0 block = Block.build(block_number=1, version='1', previous_block_hash='1', timestamp=1, merkle_root='', difficulty_target=10, nonce=1) transaction = Transaction.build(block_id='1', locktime=0, timestamp=timestamp) transaction_output = TransactionOutput.build( transaction_id='1', amount=10000000000000000000, sender_address='coinbase', recipient_address= '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznjoHvzCJtQcIYd3yj7v\ngwaPlyiG6U/Qlw1G89n0bNt5anvRe+e2eKzvpy98aj6ShGu7hARE9SxAFA9bIHCB\nqdAyPnrUaw7qGkeZNPHBByHe9prJSn0ZwBtfySOSbzdetO5aAwvLj5qMudW2PDz1\n5mP2taGOvXqNnbcH78ZHQLvF6G+SbwuLHU5LEDSZlcy+CnvPqD67cg+QmJLneVmQ\nfOBtbFHz3yDQghNrHWa+UCspUMHVGsDG6OEK7MSpPieY6TzBEYQWsikosQ+V0zBN\nrSCADe3GBcJ7XzafM/gb+gzJ1eP78F1sA6Ja4ZtqInqN406PwerAXaUJa2twW652\n9wIDAQAB\n-----END PUBLIC KEY-----', timestamp=timestamp) db.session.add(block) db.session.add(transaction) db.session.add(transaction_output) db.session.commit()
def _create_block(cls): last_block = Blockchain.fetch_last_block() previous_hash = last_block.block_id block_number = Blockchain.fetch_block_count() + 1 proof_of_work = ProofOfWork(previous_hash, last_block.difficulty_target) proof_result = proof_of_work.prove() proof_result.assert_valid() transactions = UnconfirmedTxPool.transactions.copy() UnconfirmedTxPool.transactions.clear() target_transactions = Blockchain.search_new_transactions(transactions) block = Block.build( block_number=block_number, previous_block_hash=previous_hash, timestamp=datetime.now().timestamp(), merkle_root="", # TODO difficulty_target=last_block.difficulty_target, nonce=proof_result.nonce, transactions=target_transactions) last_block = Blockchain.fetch_last_block() if last_block.block_id != block.previous_block_hash: print('lost mining', block.block_id) raise LoseMiningException() Blockchain.create_block(block) print('block created', block.block_id) print('current block number', block.block_number) return block, proof_result
from app.models.chain import Chain from static.test import test_data block_zero_dir = test_data[0] block_one_dir = test_data[1] block_two_dir = test_data[2] block_three_dir = test_data[3] block_three_later_in_time_dir = test_data[4] ########################### # # Block time # ########################### block_zero = Block(**block_zero_dir) another_block_zero = Block(**block_zero_dir) assert block_zero.is_valid() assert block_zero == another_block_zero assert not block_zero != another_block_zero block_one = Block(**block_one_dir) another_block_one = Block(**block_one_dir) assert block_one.is_valid() assert block_one == another_block_one assert not block_one != another_block_one block_two = Block(**block_two_dir) another_block_two = Block(**block_two_dir) assert block_two.is_valid() assert block_two == another_block_two
def assert_new_block(cls, block_id): block = Block.find(block_id) return block is None
def list_blocks(cls): return Block.list()
def find_by_block_number(cls, block_number): return Block.find_by_block_number(block_number)
def test_block_validation(self): chain = Blockchain() private_key = RSA.generate(1024) miner_id = "1234" chain.create_genesis_block(private_key, miner_id) prevBlock = chain.storage[0] t = Transaction("1234", "4567") # Create Block with dummy transaction block = Block(prevBlock["hash"], prevBlock["height"] + 1, [t.get_signed_json(private_key)], miner_id) block.mine() # Check block validation is ok self.assertTrue(chain.validate_block(block.get_json(), prevBlock)) # Mess with blockchain structure block.block["prevHash"] = "00012345" self.assertFalse(chain.validate_block(block.get_json(), prevBlock)) # Mess with height block.block["prevHash"] = prevBlock["hash"] block.block["height"] = 5 self.assertFalse(chain.validate_block(block.get_json(), prevBlock)) # Mess with PoW block.block["height"] = 2 block.block["hash"] = "0111111111" self.assertFalse(chain.validate_block(block.get_json(), prevBlock)) # Mess with hash but keep PoW block.block["hash"] = "0001111111" self.assertFalse(chain.validate_block(block.get_json(), prevBlock)) # Mess with transaction integrity t.signature = "L7TBH0ahox4GOAdF8om2ijbNVPcO3Ys6+KdvfFhvfX/SysetaJw+0rlU6VMuzwB0rQ/X2+ioAdtXcstutSeRAfZTYP+utaNFL1nP48as/C6mca4sp+ya39AWWLIUuZeGMit9kSUavx6uX5cSAuqXB4tcK/bUSVghtMC9vG4JyC8=" block = Block(prevBlock["prevHash"], prevBlock["height"] + 1, [t.get_signed_json(private_key)], miner_id) block.mine() self.assertFalse(chain.validate_block(block.get_json(), prevBlock))
class Blockchain: blocks = [ Block.build( block_number=1, previous_block_hash="1", timestamp=0, merkle_root="", difficulty_target=20, nonce=0, transactions=[ Transaction.build( timestamp=1, tx_inputs=[], tx_outputs=[ TransactionOutput.build( amount=1000000000, sender_address=COINBASE_ADDRESS, recipient_address= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznjoHvzCJtQcIYd3yj7vgwaPlyiG6U/Qlw1G89n0bNt5anvRe+e2eKzvpy98aj6ShGu7hARE9SxAFA9bIHCBqdAyPnrUaw7qGkeZNPHBByHe9prJSn0ZwBtfySOSbzdetO5aAwvLj5qMudW2PDz15mP2taGOvXqNnbcH78ZHQLvF6G+SbwuLHU5LEDSZlcy+CnvPqD67cg+QmJLneVmQfOBtbFHz3yDQghNrHWa+UCspUMHVGsDG6OEK7MSpPieY6TzBEYQWsikosQ+V0zBNrSCADe3GBcJ7XzafM/gb+gzJ1eP78F1sA6Ja4ZtqInqN406PwerAXaUJa2twW6529wIDAQAB", timestamp=1) ]), Transaction.build( timestamp=1, tx_inputs=[], tx_outputs=[ TransactionOutput.build( amount=200000000, sender_address=COINBASE_ADDRESS, recipient_address= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznjoHvzCJtQcIYd3yj7vgwaPlyiG6U/Qlw1G89n0bNt5anvRe+e2eKzvpy98aj6ShGu7hARE9SxAFA9bIHCBqdAyPnrUaw7qGkeZNPHBByHe9prJSn0ZwBtfySOSbzdetO5aAwvLj5qMudW2PDz15mP2taGOvXqNnbcH78ZHQLvF6G+SbwuLHU5LEDSZlcy+CnvPqD67cg+QmJLneVmQfOBtbFHz3yDQghNrHWa+UCspUMHVGsDG6OEK7MSpPieY6TzBEYQWsikosQ+V0zBNrSCADe3GBcJ7XzafM/gb+gzJ1eP78F1sA6Ja4ZtqInqN406PwerAXaUJa2twW6529wIDAQAB", timestamp=1) ]), Transaction.build( timestamp=1, tx_inputs=[], tx_outputs=[ TransactionOutput.build( amount=300003, sender_address=COINBASE_ADDRESS, recipient_address= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznjoHvzCJtQcIYd3yj7vgwaPlyiG6U/Qlw1G89n0bNt5anvRe+e2eKzvpy98aj6ShGu7hARE9SxAFA9bIHCBqdAyPnrUaw7qGkeZNPHBByHe9prJSn0ZwBtfySOSbzdetO5aAwvLj5qMudW2PDz15mP2taGOvXqNnbcH78ZHQLvF6G+SbwuLHU5LEDSZlcy+CnvPqD67cg+QmJLneVmQfOBtbFHz3yDQghNrHWa+UCspUMHVGsDG6OEK7MSpPieY6TzBEYQWsikosQ+V0zBNrSCADe3GBcJ7XzafM/gb+gzJ1eP78F1sA6Ja4ZtqInqN406PwerAXaUJa2twW6529wIDAQAB", timestamp=1) ]), ]) ] @classmethod def fetch_all_blocks(cls): return cls.blocks @classmethod def fetch_block_count(cls): return len(cls.blocks) @classmethod def fetch_last_block(cls): return cls.blocks[-1] @classmethod def fetch_unspent_tx_outputs_by_tx_output_ids(cls, tx_output_ids): blocks = cls.blocks if len(blocks) == 0: return [] transactions = reduce( add, list(map(lambda block: block.transactions, blocks))) if len(transactions) == 0: return [] tx_outputs = reduce(add, list(map(lambda tx: tx.tx_outputs, transactions))) tx_inputs = reduce(add, list(map(lambda tx: tx.tx_inputs, transactions))) spent_tx_output_ids = list( map(lambda tx_i: tx_i.transaction_output_id, tx_inputs)) unspent_tx_outputs = list( filter( lambda tx_o: tx_o.transaction_output_id not in spent_tx_output_ids, tx_outputs)) return list( filter(lambda tx_o: tx_o.transaction_output_id in tx_output_ids, unspent_tx_outputs)) @classmethod def fetch_unspent_tx_outputs_by_address(cls, address): blocks = cls.blocks if len(blocks) == 0: return [] transactions = reduce( add, list(map(lambda block: block.transactions, blocks))) if len(transactions) == 0: return [] tx_outputs = reduce(add, list(map(lambda tx: tx.tx_outputs, transactions))) tx_inputs = reduce(add, list(map(lambda tx: tx.tx_inputs, transactions))) spent_tx_output_ids = list( map(lambda tx_i: tx_i.transaction_output_id, tx_inputs)) return list( filter( lambda tx_o: tx_o.recipient_address == address and tx_o. transaction_output_id not in spent_tx_output_ids, tx_outputs)) @classmethod def create_block(cls, block): cls.blocks.append(block) @classmethod def search_new_transactions(cls, transactions): transactions_in_chain = reduce( add, list(map(lambda block: block.transactions, cls.blocks))) return list( filter(lambda tx: tx not in transactions_in_chain, transactions)) @classmethod def delete_block(cls, deleting_block): cls.blocks.remove(deleting_block) @classmethod def find_block(cls, block_id): blocks = list( filter(lambda block: block.block_id == block_id, cls.blocks)) if len(blocks) == 0: return None return blocks[0]