Esempio n. 1
0
    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))
Esempio n. 2
0
    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))
Esempio n. 3
0
    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')
Esempio n. 4
0
    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))
Esempio n. 5
0
    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})
Esempio n. 6
0
def test_verify_signature():
    assert verify_signature(SIGNATURE, MESSAGE, PUBLIC_KEY_COMPRESSED)
    assert verify_signature(SIGNATURE, MESSAGE, PUBLIC_KEY_UNCOMPRESSED)
Esempio n. 7
0
    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
Esempio n. 8
0
    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
Esempio n. 9
0
    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')