async def challenge(self, body, stream): challenge = body.get('params', {}).get('token') signed_challenge = TU.generate_signature(challenge, self.config.private_key) await self.write_result( stream, 'authenticate', { 'peer': self.config.peer.to_dict(), 'signed_challenge': signed_challenge }, body['id'])
async def create_relationship(self, bulletin_secret, username, to): config = self.config mongo = self.config.mongo if not bulletin_secret: return 'error: "bulletin_secret" missing', 400 if not username: return 'error: "username" missing', 400 if not to: return 'error: "to" missing', 400 rid = TU.generate_rid(config, bulletin_secret) dup = mongo.db.blocks.find({'transactions.rid': rid}) if dup.count(): found_a = False found_b = False for txn in dup: if txn['public_key'] == config.public_key: found_a = True if txn['public_key'] != config.public_key: found_b = True if found_a and found_b: return json.dumps({ "success": False, "status": "Already added" }) miner_transactions = mongo.db.miner_transactions.find() mtxn_ids = [] for mtxn in miner_transactions: for mtxninput in mtxn['inputs']: mtxn_ids.append(mtxninput['id']) checked_out_txn_ids = mongo.db.checked_out_txn_ids.find() for mtxn in checked_out_txn_ids: mtxn_ids.append(mtxn['id']) a = os.urandom(32).decode('latin1') dh_public_key = scalarmult_base(a).encode('latin1').hex() dh_private_key = a.encode('latin1').hex() transaction = await Transaction.generate( bulletin_secret=bulletin_secret, username=username, fee=0.00, public_key=config.public_key, dh_public_key=dh_public_key, private_key=config.private_key, dh_private_key=dh_private_key, outputs=[{ 'to': to, 'value': 0 }]) return transaction
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'}) args = json.loads(self.request.body) if not args.get('uid'): return self.render_as_json({ "error": True, "message": "no user account provided" }) keyhash = hashlib.sha256( TU.generate_deterministic_signature( self.config, 'child_wallet').encode()).hexdigest() exkey = BIP32Key.fromExtendedKey(self.config.xprv) last_child_key = self.config.mongo.db.child_keys.find( {'signature': keyhash}, sort=[('inc', -1)]) inc = last_child_key.count() + 1 key = exkey.ChildKey(inc) child_key = BIP32Key.fromExtendedKey(key.ExtendedKey()) child_key = child_key.ChildKey(inc) public_key = child_key.PublicKey().hex() address = str( P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(public_key))) private_key = child_key.PrivateKey().hex() wif = self.to_wif(private_key) await self.config.mongo.async_db.child_keys.insert_one({ 'account': args.get('uid'), 'inc': inc, 'extended': child_key.ExtendedKey(), 'public_key': public_key, 'address': address, 'private_key': private_key, 'wif': wif, 'signature': keyhash }) return self.render_as_json({"address": address})
async def challenge(self, body, stream): self.ensure_protocol_version(body, stream) params = body.get('params', {}) challenge = params.get('token') signed_challenge = TU.generate_signature(challenge, self.config.private_key) if stream.peer.protocol_version > 1: await self.write_params( stream, 'authenticate', { 'peer': self.config.peer.to_dict(), 'signed_challenge': signed_challenge }) else: await self.write_result( stream, 'authenticate', { 'peer': self.config.peer.to_dict(), 'signed_challenge': signed_challenge }, body['id'])
async def generate( cls, transactions=None, public_key=None, private_key=None, force_version=None, index=0, force_time=None, prev_hash=None, nonce=None, target=CHAIN.MAX_TARGET ): config = get_config() app_log = getLogger("tornado.application") if force_version is None: version = CHAIN.get_version_for_height(index) else: version = force_version if force_time: xtime = str(int(force_time)) else: xtime = str(int(time.time())) index = int(index) if index == 0: prev_hash = '' elif prev_hash is None and index != 0: prev_hash = LatestBlock.block.hash transactions = transactions or [] transaction_objs = [] fee_sum = 0.0 used_sigs = [] used_inputs = {} for txn in transactions: try: if isinstance(txn, Transaction): transaction_obj = txn else: transaction_obj = Transaction.from_dict(txn) if transaction_obj.transaction_signature in used_sigs: print('duplicate transaction found and removed') continue await transaction_obj.verify() used_sigs.append(transaction_obj.transaction_signature) except: raise InvalidTransactionException("invalid transactions") try: if int(index) > CHAIN.CHECK_TIME_FROM and (int(transaction_obj.time) > int(xtime) + CHAIN.TIME_TOLERANCE): config.mongo.db.miner_transactions.remove({'id': transaction_obj.transaction_signature}, multi=True) app_log.debug("Block embeds txn too far in the future {} {}".format(xtime, transaction_obj.time)) continue if transaction_obj.inputs: failed = False used_ids_in_this_txn = [] for x in transaction_obj.inputs: if config.BU.is_input_spent(x.id, transaction_obj.public_key): failed = True if x.id in used_ids_in_this_txn: failed = True if (x.id, transaction_obj.public_key) in used_inputs: failed = True used_inputs[(x.id, transaction_obj.public_key)] = transaction_obj used_ids_in_this_txn.append(x.id) if failed: continue transaction_objs.append(transaction_obj) fee_sum += float(transaction_obj.fee) except Exception as e: await config.mongo.async_db.miner_transactions.delete_many({'id': transaction_obj.transaction_signature}) config.app_log.debug('Exception {}'.format(e)) continue block_reward = CHAIN.get_block_reward(index) coinbase_txn = await Transaction.generate( public_key=public_key, private_key=private_key, outputs=[{ 'value': block_reward + float(fee_sum), 'to': str(P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(public_key))) }], coinbase=True ) transaction_objs.append(coinbase_txn) transactions = transaction_objs block = await cls.init_async( version=version, block_time=xtime, block_index=index, prev_hash=prev_hash, transactions=transactions, public_key=public_key, target=target ) txn_hashes = block.get_transaction_hashes() block.set_merkle_root(txn_hashes) block.target = target block.header = block.generate_header() if nonce: block.nonce = str(nonce) block.hash = block.generate_hash_from_header( block.index, block.header, str(block.nonce) ) block.signature = TU.generate_signature(block.hash, private_key) return block
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 generate_transaction_signature(self): return TU.generate_signature(self.hash, self.private_key)
async def generate(cls, bulletin_secret='', username='', value=0, fee=0.0, rid='', requester_rid='', requested_rid='', public_key='', dh_public_key='', private_key='', dh_private_key='', to='', inputs='', outputs='', coinbase=False, chattext=None, signin=None, relationship='', no_relationship=False, exact_match=False): cls_inst = cls() cls_inst.config = get_config() cls_inst.mongo = cls_inst.config.mongo cls_inst.app_log = getLogger('tornado.application') cls_inst.bulletin_secret = bulletin_secret cls_inst.username = username cls_inst.rid = rid cls_inst.requester_rid = requester_rid cls_inst.requested_rid = requested_rid cls_inst.public_key = public_key cls_inst.dh_public_key = dh_public_key cls_inst.private_key = private_key cls_inst.value = value cls_inst.fee = float(fee) cls_inst.dh_private_key = dh_private_key cls_inst.to = to cls_inst.time = str(int(time.time())) cls_inst.outputs = [] cls_inst.relationship = relationship cls_inst.no_relationship = no_relationship cls_inst.exact_match = exact_match for x in outputs: cls_inst.outputs.append(Output.from_dict(x)) cls_inst.inputs = [] for x in inputs: if 'signature' in x and 'public_key' in x and 'address' in x: cls_inst.inputs.append(ExternalInput.from_dict(x)) else: cls_inst.inputs.append(Input.from_dict(x)) cls_inst.coinbase = coinbase cls_inst.chattext = chattext cls_inst.signin = signin await cls_inst.do_money() inputs_concat = ''.join([ x.id for x in sorted(cls_inst.inputs, key=lambda x: x.id.lower()) ]) outputs_concat = cls_inst.get_output_hashes() if bulletin_secret or rid: if not cls_inst.rid: cls_inst.rid = cls_inst.generate_rid() if cls_inst.chattext: cls_inst.relationship = json.dumps( {"chatText": cls_inst.chattext}) cls_inst.encrypted_relationship = cls_inst.config.cipher.encrypt( cls_inst.relationship) elif cls_inst.signin: for shared_secret in cls_inst.config.GU.get_shared_secrets_by_rid( cls_inst.rid): cls_inst.relationship = SignIn(cls_inst.signin) cls_inst.cipher = Crypt(shared_secret.hex(), shared=True) cls_inst.encrypted_relationship = cls_inst.cipher.shared_encrypt( cls_inst.relationship.to_json()) break elif cls_inst.relationship: cls_inst.encrypted_relationship = cls_inst.relationship elif cls_inst.no_relationship: cls_inst.encrypted_relationship = '' else: if not cls_inst.dh_public_key or not cls_inst.dh_private_key: a = os.urandom(32).decode('latin1') cls_inst.dh_public_key = scalarmult_base(a).encode( 'latin1').hex() cls_inst.dh_private_key = a.encode().hex() cls_inst.relationship = cls_inst.generate_relationship() if not private_key: raise Exception('missing private key') cls_inst.encrypted_relationship = cls_inst.config.cipher.encrypt( cls_inst.relationship.to_json().encode()) else: cls_inst.rid = '' cls_inst.encrypted_relationship = '' cls_inst.header = (cls_inst.public_key + cls_inst.time + cls_inst.dh_public_key + cls_inst.rid + cls_inst.encrypted_relationship + "{0:.8f}".format(cls_inst.fee) + cls_inst.requester_rid + cls_inst.requested_rid + inputs_concat + outputs_concat) cls_inst.hash = hashlib.sha256( cls_inst.header.encode('utf-8')).digest().hex() if cls_inst.private_key: cls_inst.transaction_signature = TU.generate_signature_with_private_key( private_key, cls_inst.hash) else: cls_inst.transaction_signature = '' return cls(cls_inst.time, cls_inst.rid, cls_inst.transaction_signature, cls_inst.encrypted_relationship, cls_inst.public_key, cls_inst.dh_public_key, float(cls_inst.fee), cls_inst.requester_rid, cls_inst.requested_rid, cls_inst.hash, inputs=[x.to_dict() for x in cls_inst.inputs], outputs=[x.to_dict() for x in cls_inst.outputs], coinbase=cls_inst.coinbase)
def get_username_signature(self): from yadacoin.core.transactionutils import TU return TU.generate_deterministic_signature(self, self.username, self.private_key)