def new_block(self, miner, timestamp): fees = 0 for tx in self.transactions: fees += tx.fee reward = self.calculate_reward() latest_block = self.get_latest_block() index = latest_block.index + 1 previous_hash = latest_block.calculate_hash() transactions = list(self.transactions) # Sort by byte-price. transactions.sort(key=lambda t: t.fee / len(t.serialize())) fee_transaction = Transaction(version=config.VERSION, target=index, fee=0, name=misc.random_name(), source=config.NOWHERE_NAME, destination=miner, amount=fees, data=NoData(), signature=b'') transactions.append(fee_transaction) reward_transaction = Transaction(version=config.VERSION, target=index, fee=0, name=misc.random_name(), source=config.SUPPLY_NAME, destination=miner, amount=reward, data=NoData(), signature=b'') transactions.append(reward_transaction) diff = self.calculate_hash_difficulty() compressed_diff = difficulty.compress(diff) next_block = Block(index, timestamp, previous_hash, compressed_diff, transactions, 0) while len(next_block.serialize()) > config.MAX_BLOCK_SIZE: tx = next_block.transactions.pop(0) fee_transaction.amount -= tx.fee next_block.update_merkle_root() return next_block
async def mine(self, request): username = request.query.get('username', None) password = request.query.get('password', None) if username != self.username or password != self.password: return web.json_response(data = { 'ok': False, 'error': 'Auth failed!' }) miner_address = Address.from_string(request.query.get('address', None)) if self.blockchain.resolve(miner_address) is None: return web.json_response(data = {'ok': False, 'error': 'Miner not valid!'}) self.miner_address = miner_address print("Miner: " + str(self.miner_address)) if self.miner: await self.miner.close() self.miner = web.WebSocketResponse() await self.miner.prepare(request) await self.mine_next_block() async for msg in self.miner: response = msg.json() header = Block.deserialize(bytes.fromhex(response['data']), header_only = True) self.next_block.nonce = header.nonce self.next_block.timestamp = header.timestamp try: self.blockchain.is_valid_block(self.next_block) self.block_queue.put(self.next_block) except BlockchainException as e: print(e) await self.mine_next_block()
def get_block(self, index): block = Block.deserialize(self.root.get(World.HEADER_PREFIX + struct.pack('>L', index)), header_only=True) prefix = World.BLOCK_TRANSACTION_PREFIX + struct.pack('>L', index) txs = list(self.root.iterator(prefix=prefix, include_key=False)) block.transactions = [ Transaction.deserialize(self.root.get(tx)) for tx in txs ] return block
async def blocks(self, request): if request.method == 'GET': return web.Response(text='All blocks') elif request.method == 'POST': try: b = Block.deserialize(await request.content.read()) self.blockchain.is_valid_block(b) self.block_queue.put(b) return web.json_response(data={'ok': True}) except (CommonException, BlockchainException) as e: return web.json_response(data={'ok': False, 'error': str(e)})
async def block_range(self, request): header_only = 'header' in request.query start = int(request.match_info['start']) end = request.match_info['end'] if end == 'latest': end = self.blockchain.get_height() else: end = int(end) + 1 if end > start: result = self.blockchain.get_block_range(start, end) else: result = [] return web.Response(body=Block.serialize_list(result, header_only = header_only))
def get_block_from(self, index, peer, header_only=False): url = self.BLOCK_URL.format(peer, index) if header_only: url += '?header' try: response = requests.get(url) if response.status_code == 200: try: return Block.deserialize(requests.get(url).content, header_only=header_only) except CommonException: self.set_bad_peer(node) except requests.exceptions.RequestException as re: self.set_bad_peer(node)
def genesis_block(): supply_account = Transaction(version=0, target=0, fee=0, name='jbi5ji5bda7e6m78', source=NOWHERE_NAME, destination=SUPPLY_NAME, amount=SUPPLY_INITIAL_BALANCE, data=NoData(), signature=b'') founder_account = Transaction(version=0, target=0, fee=0, name='nsu6b7uyujbgemk6', source=NOWHERE_NAME, destination=FOUNDER_NAME, amount=FOUNDER_INITIAL_BALANCE, data=NoData(), signature=b'') contributors_account = Transaction(version=0, target=0, fee=0, name='d3ym5m81dcgtieh4', source=NOWHERE_NAME, destination=CONTRIBUTORS_NAME, amount=CONTRIBUTORS_INITIAL_BALANCE, data=NoData(), signature=b'') genesis_transactions = [ supply_account, founder_account, contributors_account ] genesis_block = Block(0, GENESIS_TIMESTAMP, b'\0' * 32, MINIMUM_HASH_DIFFICULTY_COMPRESSED, genesis_transactions, GENESIS_NONCE) return genesis_block