def validate_block(self, block, merkle_root): if block.block_header.merkle_root != merkle_root: logger.warn("invalid merkle root") return False if not self.check_block_reward(block): logger.warn("Invalid block reward") return False return True
def validate_block_transactions_inv(self, transactions_inv): """ Checks a list of transaction hashes, checks for double-spends and/or entries in the mempool Returns a list of unknown transaction hashes :param transactions_inv: :return: block_transactions, missing_transactions_inv :rtype: tuple(list, list) """ missing_transactions_inv = [] block_transactions = [] for tx_hash in transactions_inv: if self.blockchain.find_duplicate_transactions(tx_hash): logger.warn( 'Transaction not valid. Double-spend prevented: {}'. format(tx_hash)) return False transaction = self.mempool.get_unconfirmed_transaction(tx_hash) if transaction is None: missing_transactions_inv.append(tx_hash) else: block_transactions.append(transaction) return block_transactions, missing_transactions_inv
def validate_block_header(self, block_header, transactions_inv): if self.blockchain.get_block_header_by_hash(block_header.hash): logger.warn('Block Header already exists') return False if block_header.version != config['network']['version']: logger.warn('Incompatible version') return False if block_header.merkle_root != self.calculate_merkle_root( transactions_inv): logger.warn('Invalid merkle root') return False previous_block = self.blockchain.get_block_header_by_hash( block_header.previous_hash) if previous_block is None: return None previous_block_header, previous_block_branch, previous_block_height = previous_block if self.blockchain.calculate_hash_difficulty( previous_block_height + 1) > block_header.hash_difficulty: logger.warn('Invalid hash difficulty') return False return previous_block_height + 1
def check_block_reward(self, block): reward_amount = self.blockchain.get_reward(block.height) for transaction in block.transactions[1:]: if TransactionType( transaction.tx_type) == TransactionType.COINBASE: logger.warn("Block not valid. Multiple coinbases detected") return False reward_amount += transaction.fee # first transaction is coinbase reward_transaction = block.transactions[0] if TransactionType( reward_transaction.tx_type) != TransactionType.COINBASE: logger.warn("Block not valid. Missing coinbase") return False if reward_transaction.amount != reward_amount: logger.warn("Invalid block reward {} should be {}".format( reward_transaction.amount, reward_amount)) return False if reward_transaction.source != "0": logger.warn("Invalid Coinbase source") return False return True
def validate_transaction(self, transaction): """ Validate a single transaction. Check for double-spend, invalid signature, and insufficient funds :param transaction: :return: boolean :rtype: boolean """ if self.blockchain.find_duplicate_transactions(transaction.tx_hash): logger.warn( 'Transaction not valid. Double-spend prevented: {}'.format( transaction.tx_hash)) return False if not transaction.verify(): logger.warn( 'Transaction not valid. Invalid transaction signature: {}'. format(transaction.tx_hash)) return False balance = self.blockchain.get_balance(transaction.source) if transaction.amount + transaction.fee > balance: logger.warn( 'Transaction not valid. Insufficient funds: {}'.format( transaction.tx_hash)) return False return True
def client(): helptext = ''' Available commands: =================== balance <public key (optional)> send <destination> <amount> <fee> publickey privatekey history <public key (optional)> quit or exit ''' peers = Peers() api_client = ApiClient(peers) encrypted = config['user']['encrypted_private_key'] if not encrypted.strip(): print( "\n\nNo private key provided. A new wallet will be generated for you...\n\n" ) wallet = Client(peers, api_client) else: passphrase = getpass("Enter passphrase: ") encrypted = codecs.decode(encrypted, 'hex') nonce = encrypted[0:16] tag = encrypted[16:32] ciphertext = encrypted[32:] hashedpass = hashlib.sha256(passphrase.encode('utf-8')).digest() cipher = AES.new(hashedpass, AES.MODE_EAX, nonce) try: private_key = cipher.decrypt_and_verify(ciphertext, tag) wallet = Client(peers, api_client, private_key) except ValueError as ve: logger.warn('Invalid passphrase') print("\n\nInvalid passphrase\n\n") sys.exit(1) while True: cmd = input("{} ({}) wallet > ".format( config['network']['name'], config['network']['ticker_symbol'])) cmd_split = cmd.split() try: if cmd_split[0] == "balance": if len(cmd_split) == 2: print(wallet.get_balance(cmd_split[1])) else: print(wallet.get_balance()) elif cmd_split[0] == "send": if len(cmd_split) == 4: print( wallet.create_transaction(cmd_split[1], float(cmd_split[2]), float(cmd_split[3]))) else: print("\nRequires destination, amount, fee\n") elif cmd_split[0] == "publickey": print(wallet.get_public_key()) elif cmd_split[0] == "privatekey": print(wallet.get_private_key()) elif cmd_split[0] == "history": if len(cmd_split) == 2: print(wallet.get_transaction_history(cmd_split[1])) else: print(wallet.get_transaction_history()) elif cmd_split[0] in ("quit", "exit"): sys.exit(0) else: # help print(helptext) except IndexError: pass