Beispiel #1
0
    def run(cls, config, mongo, to, value):
        Peers.init(config, mongo, config.network)

        try:
            transaction = TransactionFactory(
                block_height=config.BU.get_latest_block()['index'],
                fee=0.01,
                public_key=config.public_key,
                private_key=config.private_key,
                outputs=[
                    {'to': to, 'value': value}
                ]
            )
        except NotEnoughMoneyException as e:
            print("not enough money yet")
            return
        except:
            raise
        try:
            transaction.transaction.verify()
        except:
            print('transaction failed')
        TU.save(config, mongo, transaction.transaction)
        print('Transaction generated successfully. Sending:', value, 'To:', to)
        for peer in Peers.peers:
            try:
                with SocketIO(peer.host, peer.port, ChatNamespace, wait_for_connection=False) as socketIO:
                    chat_namespace = socketIO.define(ChatNamespace, '/chat')
                    chat_namespace.emit('newtransaction', transaction.transaction.to_dict())
                    socketIO.disconnect()
                    print('Sent to:', peer.host, peer.port)
            except Exception as e:
                print(e)
Beispiel #2
0
    def from_dict(cls, config):
        from yadacoin.transactionutils import TU

        cls.seed = config.get('seed', '')
        cls.xprv = config.get('xprv', '')
        cls.username = config.get('username', '')
        cls.use_pnp = config.get('use_pnp', True)
        cls.ssl = config.get('ssl', True)
        cls.origin = config.get('origin', True)
        cls.polling = config.get('polling', -1)
        cls.network = config.get('network', 'mainnet')
        cls.public_key = config['public_key']
        cls.address = str(P2PKHBitcoinAddress.from_pubkey(bytes.fromhex(cls.public_key)))

        cls.private_key = config['private_key']
        cls.wif = cls.generate_wif(cls.private_key)
        cls.bulletin_secret = TU.generate_deterministic_signature(config, config['username'], config['private_key'])

        cls.mongodb_host = config['mongodb_host']
        cls.database = config['database']
        cls.site_database = config['site_database']
        cls.web_server_host = config['web_server_host']
        cls.web_server_port = config['web_server_port']
        if config['peer_host'] == '0.0.0.0' or config['peer_host'] == 'localhost':
            raise Exception("cannot use localhost or 0.0.0.0, must specify public ipv4 address")
        if config['peer_host'] == '[my public ip]':
            raise Exception("please configure your peer_post to your public ipv4 address")
        cls.peer_host = config['peer_host']
        cls.peer_port = config['peer_port']
        cls.serve_host = config['serve_host']
        cls.serve_port = config['serve_port']
        cls.callbackurl = config['callbackurl']
        cls.fcm_key = config['fcm_key']
Beispiel #3
0
    def get_transaction_by_rid(self, selector, wif=None, bulletin_secret=None, rid=False, raw=False,
                               theirs=False, my=False, public_key=None):
        # from block import Block
        # from transaction import Transaction
        from yadacoin.crypt import Crypt
        if not rid:
            ds = bulletin_secret
            selectors = [
                TU.hash(ds + selector),
                TU.hash(selector + ds)
            ]
        else:
            if not isinstance(selector, list):
                selectors = [selector, ]
            else:
                selectors = selector

            
                    
        def txn_gen():
            res = self.mongo.db.blocks.find(
                {"transactions": {"$elemMatch": {"relationship": {"$ne": ""}, "rid": {"$in": selectors}}}})
            for x in res:
                yield x
        
            res = self.mongo.db.fastgraph_transactions.find(
                {"txn": {"$elemMatch": {"relationship": {"$ne": ""}, "rid": {"$in": selectors}}}})
            for x in res:
                yield x
        
        for block in txn_gen():
            for transaction in block.get('transactions'):
                if theirs and public_key == transaction['public_key']:
                    continue
                if my and public_key != transaction['public_key']:
                    continue
                if not raw:
                    try:
                        cipher = Crypt(wif)
                        decrypted = cipher.decrypt(transaction['relationship'])
                        relationship = json.loads(decrypted.decode('latin1'))
                        transaction['relationship'] = relationship
                    except:
                        continue
                if 'rid' in transaction and transaction['rid'] in selectors:
                    return transaction
Beispiel #4
0
    def run(cls, config, mongo):
        used_inputs = []
        new_inputs = []
        for x in mongo.site_db.faucet.find({'active': True}):
            balance = BU.get_wallet_balance(config, mongo, x['address'])
            if balance >= 25:
                mongo.site_db.faucet.update({'_id': x['_id']}, {'active': False, 'address': x['address']})

                continue
            last_id_in_blockchain = x.get('last_id')
            if last_id_in_blockchain and not mongo.db.blocks.find({'transactions.id': last_id_in_blockchain}).count():

                continue

            try:
                transaction = TransactionFactory(
                    block_height=BU.get_latest_block(config, mongo)['index'],
                    fee=0.01,
                    public_key=config.public_key,
                    private_key=config.private_key,
                    outputs=[
                        Output(to=x['address'], value=5)
                    ]
                )
            except NotEnoughMoneyException as e:
                print("not enough money yet")
                return
            except Exception as e:
                print(e)
            try:
                transaction.transaction.verify()
            except:
                mongo.site_db.failed_faucet_transactions.insert(transaction.transaction.to_dict())
                print('faucet transaction failed')
            TU.save(config, mongo, transaction.transaction)
            x['last_id'] = transaction.transaction.transaction_signature
            mongo.site_db.faucet.update({'_id': x['_id']}, x)
            print('saved. sending...', x['address'])
            for peer in Peers.peers:
                try:
                    socketIO = SocketIO(peer.host, peer.port, wait_for_connection=False)
                    chat_namespace = socketIO.define(ChatNamespace, '/chat')
                    chat_namespace.emit('newtransaction', transaction.transaction.to_dict())
                    socketIO.disconnect()
                except Exception as e:
                    print(e)
Beispiel #5
0
 def get_bulletin_secret(cls, private_key=None, username=''):
     from yadacoin.transactionutils import TU
     return TU.generate_deterministic_signature(username, private_key)
Beispiel #6
0
 def inst_get_bulletin_secret(self):
     from yadacoin.transactionutils import TU
     return TU.generate_deterministic_signature(self, self.username,
                                                self.private_key)
Beispiel #7
0
    def get_transactions_by_rid(self, selector, bulletin_secret, wif=None, rid=False, raw=False,
                                returnheight=True, lt_block_height=None, requested_rid=False):
        # selectors is old code before we got an RID by sorting the bulletin secrets
        # from block import Block
        # from transaction import Transaction
        from yadacoin.crypt import Crypt

        if not rid:
            ds = bulletin_secret
            selectors = [
                TU.hash(ds + selector),
                TU.hash(selector + ds)
            ]
        else:
            if not isinstance(selector, list):
                selectors = [selector, ]
            else:
                selectors = selector

        transactions_by_rid_cache = self.mongo.db.transactions_by_rid_cache.find(
            {
                'raw': raw,
                'rid': rid,
                'bulletin_secret': bulletin_secret,
                'returnheight': returnheight,
                'selector': {'$in': selectors},
                'requested_rid': requested_rid
            }
        ).sort([('height', -1)])
        latest_block = self.config.BU.get_latest_block()

        transactions = []
        if lt_block_height:
            query = {"transactions.rid": {"$in": selectors}, "transactions": {"$elemMatch": {"relationship": {"$ne": ""}}},
                 'index': {'$lte': lt_block_height}}
            if requested_rid:
                query["transactions.requested_rid"] = {"$in": selectors}
            blocks = self.mongo.db.blocks.find(query)
        else:
            if transactions_by_rid_cache.count():
                transactions_by_rid_cache = transactions_by_rid_cache[0]
                block_height = transactions_by_rid_cache['height']
            else:
                block_height = 0
                
            query = {"transactions.rid": {"$in": selectors}, "transactions": {"$elemMatch": {"relationship": {"$ne": ""}}},
                 'index': {'$gt': block_height}}
            if requested_rid:
                query = {
                    "$or": [
                        {
                            "transactions.rid": {
                                "$in": selectors
                            }
                        },
                        {
                            "transactions.requested_rid": {
                                "$in": selectors
                            }
                        }
                    ],
                    "transactions": {
                        "$elemMatch": {
                            "relationship": {
                                "$ne": ""
                            }
                        }
                    },
                    'index': {
                        '$gt': block_height
                    }
                }
            else:
                query = {
                    "transactions.rid": {
                        "$in": selectors
                    },
                    "transactions": {
                        "$elemMatch": {
                            "relationship": {
                                "$ne": ""
                            }
                        }
                    },
                    'index': {
                        '$gt': block_height
                    }
                }
            blocks = self.mongo.db.blocks.find(query)

        cipher = Crypt(self.config.wif)
        for block in blocks:
            for transaction in block.get('transactions'):
                if 'relationship' in transaction and transaction['relationship']:
                    if returnheight:
                        transaction['height'] = block['index']
                    if not raw:
                        try:
                            decrypted = cipher.decrypt(transaction['relationship'])
                            relationship = json.loads(decrypted.decode('latin1'))
                            transaction['relationship'] = relationship
                        except:
                            continue
                    for selector in selectors:
                        self.app_log.debug('caching transactions_by_rid at height: {}'.format(block['index']))
                        self.mongo.db.transactions_by_rid_cache.insert(
                            {
                                'raw': raw,
                                'rid': rid,
                                'bulletin_secret': bulletin_secret,
                                'returnheight': returnheight,
                                'selector': selector,
                                'txn': transaction,
                                'height': block['index'],
                                'requested_rid': requested_rid
                            }
                        )
                    transactions.append(transaction)
        if not transactions:
            for selector in selectors:
                self.mongo.db.transactions_by_rid_cache.insert(
                    {
                        'raw': raw,
                        'rid': rid,
                        'bulletin_secret': bulletin_secret,
                        'returnheight': returnheight,
                        'selector': selector,
                        'height': latest_block['index'],
                        'requested_rid': requested_rid
                    }
                )

        for ftxn in self.mongo.db.fastgraph_transactions.find({'txn.rid': {'$in': selectors}}):
            if 'txn' in ftxn:
                yield ftxn['txn']

        last_id = ''
        for x in self.mongo.db.transactions_by_rid_cache.find({
            'raw': raw,
            'rid': rid,
            'returnheight': returnheight,
            'selector': {'$in': selectors},
            'requested_rid': requested_rid
        }).sort([('txn.id', 1)]):
            if 'txn' in x and x['txn']['id'] != last_id:
                last_id = x['txn']['id']
                yield x['txn']
Beispiel #8
0
    async def get(self):
        graph = self.get_base_graph()
        config = self.config
        address = self.get_query_argument('address')
        bulletin_secret = self.get_query_argument('bulletin_secret').replace(
            ' ', "+")
        amount_needed = self.get_query_argument('amount_needed', None)
        if amount_needed:
            amount_needed = int(amount_needed)
        rid = TU.generate_rid(config, bulletin_secret)

        unspent_transactions = [
            x for x in BU().get_wallet_unspent_transactions(address)
        ]
        spent_txn_ids = []

        for x in unspent_transactions:
            spent_txn_ids.extend([y['id'] for y in x['inputs']])

        unspent_fastgraph_transactions = [
            x for x in BU().get_wallet_unspent_fastgraph_transactions(address)
            if x['id'] not in spent_txn_ids
        ]
        spent_fastgraph_ids = []
        for x in unspent_fastgraph_transactions:
            spent_fastgraph_ids.extend([y['id'] for y in x['inputs']])
        regular_txns = []
        txns_for_fastgraph = []
        chain_balance = 0
        fastgraph_balance = 0
        for txn in unspent_transactions + unspent_fastgraph_transactions:
            if 'signatures' in txn and txn['signatures']:
                fastgraph = FastGraph.from_dict(0, txn)
                origin_fasttrack = fastgraph.get_origin_relationship(rid)
                if origin_fasttrack or (('rid' in txn and txn['rid'] == rid)
                                        or txn.get('requester_rid') == rid
                                        or txn.get('requested_rid') == rid):
                    txns_for_fastgraph.append(txn)
                    for output in txn['outputs']:
                        if output['to'] == address:
                            fastgraph_balance += int(output['value'])
                else:
                    regular_txns.append(txn)
                    for output in txn['outputs']:
                        if output['to'] == address:
                            chain_balance += int(output['value'])
            elif 'dh_public_key' in txn and txn['dh_public_key'] and (
                ('rid' in txn and txn['rid'] == rid)
                    or txn.get('requester_rid') == rid
                    or txn.get('requested_rid') == rid):
                txns_for_fastgraph.append(txn)
                for output in txn['outputs']:
                    if output['to'] == address:
                        fastgraph_balance += int(output['value'])
            else:
                regular_txns.append(txn)
                for output in txn['outputs']:
                    if output['to'] == address:
                        chain_balance += int(output['value'])

        wallet = {
            'chain_balance': chain_balance,
            'fastgraph_balance': fastgraph_balance,
            'balance': fastgraph_balance + chain_balance,
            'unspent_transactions': regular_txns,
            'txns_for_fastgraph': txns_for_fastgraph
        }
        self.render_as_json(wallet, indent=4)
Beispiel #9
0
    async def post(self):
        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
            for x in BU().get_wallet_unspent_transactions(
                    address, [body.get('input')]):
                if body.get('input') == x['id']:
                    found = True

            if not found:
                for x in 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})
Beispiel #10
0
    async def post(self):
        config = self.config
        mongo = self.config.mongo
        kwargs = json.loads(self.request.body.decode('utf-8'))
        bulletin_secret = kwargs.get('bulletin_secret', '')
        username = kwargs.get('username', '')
        to = kwargs.get('to', '')

        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 = TransactionFactory(
            block_height=BU().get_latest_block()['index'],
            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
            }])

        mongo.db.miner_transactions.insert(transaction.transaction.to_dict())
        """
        # TODO: integrate new socket/peer framework for transmitting txns

        job = Process(target=TxnBroadcaster.txn_broadcast_job, args=(transaction.transaction,))
        job.start()
        """

        self.render_as_json({"success": True})
Beispiel #11
0
 def generate_transaction_signature(self):
     return TU.generate_signature(self.hash, self.private_key)
Beispiel #12
0
 def __init__(
     self,
     block_height,
     bulletin_secret='',
     username='',
     value=0,
     fee=0.0,
     requester_rid='',
     requested_rid='',
     public_key='',
     dh_public_key='',
     private_key='',
     dh_private_key='',
     to='',
     inputs='',
     outputs='',
     coinbase=False,
     chattext=None,
     signin=None,
     no_relationship=False
 ):
     self.config = get_config()
     self.mongo = self.config.mongo
     self.app_log = getLogger('tornado.application')
     self.block_height = block_height
     self.bulletin_secret = bulletin_secret
     self.username = username
     self.requester_rid = requester_rid
     self.requested_rid = requested_rid
     self.public_key = public_key
     self.dh_public_key = dh_public_key
     self.private_key = private_key
     self.value = value
     self.fee = float(fee)
     self.dh_private_key = dh_private_key
     self.to = to
     self.time = str(int(time.time()))
     self.outputs = []
     self.no_relationship = no_relationship
     for x in outputs:
         self.outputs.append(Output.from_dict(x))
     self.inputs = []
     for x in inputs:
         if 'signature' in x and 'public_key' in x and 'address' in x:
             self.inputs.append(ExternalInput.from_dict(x))
         else:
             self.inputs.append(Input.from_dict(x))
     self.coinbase = coinbase
     self.chattext = chattext
     self.signin = signin
     self.do_money()
     inputs_concat = self.get_input_hashes()
     outputs_concat = self.get_output_hashes()
     if bulletin_secret:
         self.rid = self.generate_rid()
         if self.chattext:
             self.relationship = json.dumps({
                 "chatText": self.chattext
             })
             self.cipher = Crypt(self.config.wif)
             self.encrypted_relationship = self.cipher.encrypt(self.relationship)
         elif self.signin:
             for shared_secret in TU.get_shared_secrets_by_rid(self.rid):
                 self.relationship = SignIn(self.signin)
                 self.cipher = Crypt(shared_secret.hex(), shared=True)
                 self.encrypted_relationship = self.cipher.shared_encrypt(self.relationship.to_json())
                 break
         elif self.no_relationship:
             self.encrypted_relationship = ''
         else:
             if not self.dh_public_key or not self.dh_private_key:
                 a = os.urandom(32).decode('latin1')
                 self.dh_public_key = scalarmult_base(a).encode('latin1').hex()
                 self.dh_private_key = a.encode().hex()
             self.relationship = self.generate_relationship()
             if not private_key:
                 raise Exception('missing private key')
             self.cipher = Crypt(self.config.wif)
             self.encrypted_relationship = self.cipher.encrypt(self.relationship.to_json())
     else:
         self.rid = ''
         self.encrypted_relationship = ''
     
     self.header = (
         self.public_key +
         self.time +
         self.dh_public_key +
         self.rid +
         self.encrypted_relationship +
         "{0:.8f}".format(self.fee) +
         self.requester_rid +
         self.requested_rid +
         inputs_concat +
         outputs_concat
     )
     self.hash = hashlib.sha256(self.header.encode('utf-8')).digest().hex()
     if self.private_key:
         self.transaction_signature = TU.generate_signature_with_private_key(private_key, self.hash)
     else:
         self.transaction_signature = ''
     self.transaction = self.generate_transaction()