Esempio n. 1
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})
Esempio n. 2
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()