def test_signature_correct(self): private_key = PrivateKey() public_key = private_key.public_key message = urandom(200) signature = private_key.sign(message) assert verify_signature(signature, message, public_key.format(compressed=True)) assert verify_signature(signature, message, public_key.format(compressed=False))
def verify(self): getcontext().prec = 8 if int(self.version) != int(CHAIN.get_version_for_height(self.index)): raise Exception("Wrong version for block height", self.version, CHAIN.get_version_for_height(self.index)) txns = self.get_transaction_hashes() verify_merkle_root = self.get_merkle_root(txns) if verify_merkle_root != self.merkle_root: raise Exception("Invalid block merkle root") header = self.generate_header() hashtest = self.generate_hash_from_header(self.index, header, str(self.nonce)) # print("header", header, "nonce", self.nonce, "hashtest", hashtest) if self.hash != hashtest: getLogger("tornado.application").warning("Verify error hashtest {} header {} nonce {}".format(hashtest, header, self.nonce)) raise Exception('Invalid block hash') address = P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(self.public_key)) try: # print("address", address, "sig", self.signature, "pubkey", self.public_key) result = verify_signature(base64.b64decode(self.signature), self.hash.encode('utf-8'), bytes.fromhex(self.public_key)) if not result: raise Exception("block signature1 is invalid") except: try: result = VerifyMessage(address, BitcoinMessage(self.hash.encode('utf-8'), magic=''), self.signature) if not result: raise except: raise Exception("block signature2 is invalid") # verify reward coinbase_sum = 0 for txn in self.transactions: if int(self.index) > CHAIN.CHECK_TIME_FROM and (int(txn.time) > int(self.time) + CHAIN.TIME_TOLERANCE): #yadacoin.core.config.CONFIG.mongo.db.miner_transactions.remove({'id': txn.transaction_signature}, multi=True) #raise Exception("Block embeds txn too far in the future") pass if txn.coinbase: for output in txn.outputs: coinbase_sum += float(output.value) fee_sum = 0.0 for txn in self.transactions: if not txn.coinbase: fee_sum += float(txn.fee) reward = CHAIN.get_block_reward(self.index) #if Decimal(str(fee_sum)[:10]) != Decimal(str(coinbase_sum)[:10]) - Decimal(str(reward)[:10]): """ KO for block 13949 0.02099999 50.021 50.0 Integrate block error 1 ('Coinbase output total does not equal block reward + transaction fees', 0.020999999999999998, 0.021000000000000796) """ if quantize_eight(fee_sum) != quantize_eight(coinbase_sum - reward): print(fee_sum, coinbase_sum, reward) raise Exception("Coinbase output total does not equal block reward + transaction fees", fee_sum, (coinbase_sum - reward))
def verify(self): super(FastGraph, self).verify() result = self.mongo.db.fastgraph_transactions.find_one({ 'txn.hash': self.hash }) if not self.signatures: raise InvalidFastGraphTransactionException('no signatures were provided') xaddress = str(P2PKHBitcoinAddress.from_pubkey(self.public_key.decode('hex'))) unspent = [x['id'] for x in BU.get_wallet_unspent_transactions(self.config, self.mongo, xaddress)] unspent_fastgraph = [x['id'] for x in BU.get_wallet_unspent_fastgraph_transactions(self.config, self.mongo, xaddress)] inputs = [x.id for x in self.inputs] if len(set(inputs) & set(unspent)) != len(inputs) and len(set(inputs) & set(unspent_fastgraph)) != len(inputs): raise InvalidFastGraphTransactionException('Input not found in unspent') txn_for_rids = self.get_origin_relationship() if not txn_for_rids: raise InvalidFastGraphTransactionException('no origin transactions found') public_key = txn_for_rids['public_key'] for signature in self.signatures: signature.passed = False signed = verify_signature( base64.b64decode(signature.signature), self.hash, public_key.decode('hex') ) if signed: signature.passed = True """ # This is for a later fork to include a wider consensus area for a larger spending group else: mutual_friends = [x for x in BU.get_transactions_by_rid(self.config, self.mongo, self.rid, self.config.bulletin_secret, raw=True, rid=True, lt_block_height=highest_height)] for mutual_friend in mutual_friends: mutual_friend = Transaction.from_dict(self.config, self.mongo, mutual_friend) if isinstance(mutual_friend.relationship, Relationship) and signature.bulletin_secret == mutual_friend.relationship.their_bulletin_secret: other_mutual_friend = mutual_friend for mutual_friend in mutual_friends: mutual_friend = Transaction.from_dict(self.config, self.mongo, mutual_friend) if mutual_friend.public_key != self.config.public_key: identity = verify_signature( base64.b64decode(other_mutual_friend.relationship.their_bulletin_secret), other_mutual_friend.relationship.their_username, mutual_friend.public_key.decode('hex') ) signed = verify_signature( base64.b64decode(signature.signature), self.hash, mutual_friend.public_key.decode('hex') ) if identity and signed: signature.passed = True """ for signature in self.signatures: if not signature.passed: raise InvalidFastGraphTransactionException('not all signatures verified')
def verify(self): getcontext().prec = 8 if int(self.version) != int(BU.get_version_for_height(self.index)): raise BaseException("Wrong version for block height", self.version, BU.get_version_for_height(self.index)) try: txns = self.get_transaction_hashes() self.set_merkle_root(txns) if self.verify_merkle_root != self.merkle_root: raise BaseException("Invalid block") except: raise try: header = BlockFactory.generate_header(self) hashtest = BlockFactory.generate_hash_from_header( header, str(self.nonce)) if self.hash != hashtest: raise BaseException('Invalid block') except: raise address = P2PKHBitcoinAddress.from_pubkey( self.public_key.decode('hex')) try: result = verify_signature(base64.b64decode(self.signature), self.hash, self.public_key.decode('hex')) if not result: raise Exception("block signature is invalid") except: try: result = VerifyMessage(address, BitcoinMessage(self.hash, magic=''), self.signature) if not result: raise except: raise BaseException("block signature is invalid") # verify reward coinbase_sum = 0 for txn in self.transactions: if txn.coinbase: for output in txn.outputs: coinbase_sum += float(output.value) fee_sum = 0.0 for txn in self.transactions: if not txn.coinbase: fee_sum += float(txn.fee) reward = BU.get_block_reward(self.config, self.mongo, self) if Decimal(str(fee_sum)[:10]) != (Decimal(str(coinbase_sum)[:10]) - Decimal(str(reward)[:10])): raise BaseException( "Coinbase output total does not equal block reward + transaction fees", fee_sum, (coinbase_sum - reward))
async def post(self): key_or_wif = self.get_secure_cookie("key_or_wif") if not key_or_wif and self.jwt.get('key_or_wif') != 'true': return self.render_as_json({'error': 'not authorized'}) config = self.config mongo = self.config.mongo body = json.loads(self.request.body.decode('utf-8')) try: fg = FastGraph.from_dict(0, body.get('txn'), raw=True) fg.verify() except: raise return 'invalid transaction', 400 res = mongo.db.signed_transactions.find_one({'hash': body.get('hash')}) if res: return 'no', 400 try: rid = TU.generate_rid(config, body.get('bulletin_secret')) my_entry_for_relationship = GU().get_transaction_by_rid( rid, config.wif, rid=True, my=True, public_key=config.public_key) their_entry_for_relationship = GU().get_transaction_by_rid( rid, rid=True, raw=True, theirs=True, public_key=config.public_key) verified = verify_signature( base64.b64decode(body.get('bulletin_secret')), my_entry_for_relationship['relationship'] ['their_username'].encode(), bytes.fromhex(their_entry_for_relationship['public_key'])) if not verified: return 'no', 400 verified = verify_signature( base64.b64decode(body.get('id')), body.get('hash').encode('utf-8'), bytes.fromhex(their_entry_for_relationship['public_key'])) address = str( P2PKHBitcoinAddress.from_pubkey( bytes.fromhex(their_entry_for_relationship['public_key']))) found = False async for x in self.config.BU.get_wallet_unspent_transactions( address, [body.get('input')]): if body.get('input') == x['id']: found = True if not found: for x in self.config.BU.get_wallet_unspent_fastgraph_transactions( address): if body.get('input') == x['id']: found = True if found: signature = mongo.db.signed_transactions.find_one({ 'input': body.get('input'), 'txn.public_key': body['txn']['public_key'] }) if signature: already_spent = mongo.db.fastgraph_transactions.find_one({ 'txn.inputs.id': body['input'], 'txn.public_key': body['txn']['public_key'] }) if already_spent: self.set_status(400) self.write('already spent!') self.finish() return True else: signature['txn']['signatures'] = [ signature['signature'] ] fastgraph = FastGraph.from_dict(0, signature['txn']) try: fastgraph.verify() except Exception as e: raise return 'did not verify', 400 result = mongo.db.fastgraph_transactions.find_one( {'txn.hash': fastgraph.hash}) if result: return 'duplicate transaction found', 400 spent_check = mongo.db.fastgraph_transactions.find_one( { 'txn.inputs.id': { '$in': [x.id for x in fastgraph.inputs] } }) if spent_check: return 'already spent input', 400 fastgraph.save() else: return 'no transactions with this input found', 400 if verified: transaction_signature = TU.generate_signature_with_private_key( config.private_key, body.get('hash')) signature = { 'signature': transaction_signature, 'hash': body.get('hash'), 'bulletin_secret': body.get('bulletin_secret'), 'input': body.get('input'), 'id': body.get('id'), 'txn': body.get('txn') } mongo.db.signed_transactions.insert(signature) if '_id' in signature: del signature['_id'] self.render_as_json(signature, indent=4) else: return 'no', 400 except Exception as e: raise self.render_as_json({'status': 'error', 'msg': e})
def test_verify_signature(): assert verify_signature(SIGNATURE, MESSAGE, PUBLIC_KEY_COMPRESSED) assert verify_signature(SIGNATURE, MESSAGE, PUBLIC_KEY_UNCOMPRESSED)
def dispatch_request(self): config = app.config['yada_config'] mongo = app.config['yada_mongo'] res = mongo.db.signed_transactions.find_one( {'hash': request.json.get('hash')}) if res: return 'no', 400 try: rid = TU.generate_rid(config, request.json.get('bulletin_secret')) my_entry_for_relationship = BU.get_transaction_by_rid( config, mongo, rid, config.wif, rid=True, my=True, public_key=config.public_key) their_entry_for_relationship = BU.get_transaction_by_rid( config, mongo, rid, rid=True, raw=True, theirs=True, public_key=config.public_key) verified = verify_signature( base64.b64decode(request.json.get('bulletin_secret')), my_entry_for_relationship['relationship']['their_username'], their_entry_for_relationship['public_key'].decode('hex')) if not verified: return 'no', 400 verified = verify_signature( base64.b64decode(request.json.get('id')), request.json.get('hash'), their_entry_for_relationship['public_key'].decode('hex')) address = str( P2PKHBitcoinAddress.from_pubkey( their_entry_for_relationship['public_key'].decode('hex'))) found = False for x in BU.get_wallet_unspent_transactions( config, mongo, address, [request.json.get('input')]): if request.json.get('input') == x['id']: found = True if found: res = mongo.db.signed_transactions.find( {'input': request.json.get('input')}) if res.count(): return 'already signed this input', 400 else: return 'no transactions with this input found', 400 if verified: transaction_signature = TU.generate_signature_with_private_key( config.private_key, request.json.get('hash')) signature = { 'signature': transaction_signature, 'hash': request.json.get('hash'), 'bulletin_secret': request.json.get('bulletin_secret'), 'input': request.json.get('input'), 'id': request.json.get('id') } mongo.db.signed_transactions.insert(signature) if '_id' in signature: del signature['_id'] return json.dumps(signature) else: return 'no', 400 except Exception as e: return json.dumps({'status': 'error', 'msg': e}), 400
def dispatch_request(self): config = app.config['yada_config'] mongo = app.config['yada_mongo'] try: fg = FastGraph.from_dict(0, request.json.get('txn'), raw=True) fg.verify() except: raise return 'invalid transaction', 400 res = mongo.db.signed_transactions.find_one({'hash': request.json.get('hash')}) print(request.json) if res: return 'no', 400 try: rid = TU.generate_rid(config, request.json.get('bulletin_secret')) my_entry_for_relationship = GU().get_transaction_by_rid(rid, config.wif, rid=True, my=True, public_key=config.public_key) their_entry_for_relationship = GU().get_transaction_by_rid(rid, rid=True, raw=True, theirs=True, public_key=config.public_key) verified = verify_signature( base64.b64decode(request.json.get('bulletin_secret')), my_entry_for_relationship['relationship']['their_username'].encode(), bytes.fromhex(their_entry_for_relationship['public_key']) ) if not verified: return 'no', 400 verified = verify_signature( base64.b64decode(request.json.get('id')), request.json.get('hash').encode('utf-8'), bytes.fromhex(their_entry_for_relationship['public_key']) ) address = str(P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(their_entry_for_relationship['public_key']))) found = False for x in BU().get_wallet_unspent_transactions(address, [request.json.get('input')]): if request.json.get('input') == x['id']: found = True if not found: for x in BU().get_wallet_unspent_fastgraph_transactions(address): if request.json.get('input') == x['id']: found = True if found: signature = mongo.db.signed_transactions.find_one({'input': request.json.get('input')}) if signature: already_spent = mongo.db.fastgraph_transactions.find_one({'txn.inputs.id': request.json.get('input')}) if already_spent: return 'already spent!', 400 return 'already signed!', 400 else: return 'no transactions with this input found', 400 if verified: transaction_signature = TU.generate_signature_with_private_key(config.private_key, request.json.get('hash')) signature = { 'signature': transaction_signature, 'hash': request.json.get('hash'), 'bulletin_secret': request.json.get('bulletin_secret'), 'input': request.json.get('input'), 'id': request.json.get('id'), 'txn': request.json.get('txn') } mongo.db.signed_transactions.insert(signature) if '_id' in signature: del signature['_id'] return json.dumps(signature) else: return 'no', 400 except Exception as e: raise return json.dumps({ 'status': 'error', 'msg': e }), 400
def verify(self): super(FastGraph, self).verify() if not self.signatures and not self.raw: raise InvalidFastGraphTransactionException( 'no signatures were provided') origin_relationship = self.get_origin_relationship() if not origin_relationship: raise InvalidFastGraphTransactionException( 'no origin transactions found') rids = [ origin_relationship['rid'] ] # for signin, we maybe sending messages directly to do the service provider if 'requester_rid' in origin_relationship and origin_relationship[ 'requester_rid']: rids.append(origin_relationship['requester_rid']) if 'requested_rid' in origin_relationship and origin_relationship[ 'requested_rid']: rids.append(origin_relationship['requested_rid']) # we need the public_key of the service provider, either requester_rid, or requested_rid, we don't know, so we try both txns_for_rids = [] for rid in rids: txn_for_rid = GU().get_transaction_by_rid( rid, raw=True, rid=True, theirs=True, public_key=self.public_key) if txn_for_rid: txns_for_rids.append(txn_for_rid) for signature in self.signatures: signature.passed = False for txn_for_rid in txns_for_rids: signed = verify_signature( base64.b64decode(signature.signature), self.hash.encode('utf-8'), bytes.fromhex(txn_for_rid['public_key'])) self.app_log.debug(signed) self.app_log.debug(signature.signature) self.app_log.debug(self.hash.encode('utf-8')) self.app_log.debug(txn_for_rid['public_key']) if signed: signature.passed = True break """ # This is for a later fork to include a wider consensus area for a larger spending group else: mutual_friends = [x for x in BU.get_transactions_by_rid(self.config, self.mongo, self.rid, self.config.bulletin_secret, raw=True, rid=True, lt_block_height=highest_height)] for mutual_friend in mutual_friends: mutual_friend = Transaction.from_dict(self.config, self.mongo, mutual_friend) if isinstance(mutual_friend.relationship, Relationship) and signature.bulletin_secret == mutual_friend.relationship.their_bulletin_secret: other_mutual_friend = mutual_friend for mutual_friend in mutual_friends: mutual_friend = Transaction.from_dict(self.config, self.mongo, mutual_friend) if mutual_friend.public_key != self.config.public_key: identity = verify_signature( base64.b64decode(other_mutual_friend.relationship.their_bulletin_secret), other_mutual_friend.relationship.their_username.encode('utf-8'), bytes.fromhex(mutual_friend.public_key) ) signed = verify_signature( base64.b64decode(signature.signature), self.hash.encode('utf-8'), bytes.fromhex(mutual_friend.public_key) ) if identity and signed: signature.passed = True """ for signature in self.signatures: if not signature.passed: raise InvalidFastGraphTransactionException( 'not all signatures verified')