コード例 #1
0
ファイル: block.py プロジェクト: icook/yadacoin
 def save(self):
     self.verify()
     for txn in self.transactions:
         if txn.inputs:
             address = str(
                 P2PKHBitcoinAddress.from_pubkey(
                     txn.public_key.decode('hex')))
             unspent = BU.get_wallet_unspent_transactions(
                 self.config, self.mongo, address,
                 [x.id for x in txn.inputs])
             unspent_ids = [x['id'] for x in unspent]
             failed = False
             used_ids_in_this_txn = []
             for x in txn.inputs:
                 if x.id not in unspent_ids:
                     failed = True
                 if x.id in used_ids_in_this_txn:
                     failed = True
                 used_ids_in_this_txn.append(x.id)
             if failed:
                 raise BaseException('double spend',
                                     [x.id for x in txn.inputs])
     res = self.mongo.db.blocks.find({"index": (int(self.index) - 1)})
     if res.count() and res[0]['hash'] == self.prev_hash or self.index == 0:
         self.mongo.db.blocks.insert(self.to_dict())
     else:
         print "CRITICAL: block rejected..."
コード例 #2
0
ファイル: fastgraph.py プロジェクト: BadPirateX/yadacoin
    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')
コード例 #3
0
    def do_money(self):
        my_address = str(P2PKHBitcoinAddress.from_pubkey(self.public_key.decode('hex')))
        input_txns = BU.get_wallet_unspent_transactions(self.config, self.mongo, my_address)
        miner_transactions = self.mongo.db.miner_transactions.find()
        mtxn_ids = []
        for mtxn in miner_transactions:
            for mtxninput in mtxn['inputs']:
                mtxn_ids.append(mtxninput['id'])

        inputs = self.inputs or [Input.from_dict(input_txn) for input_txn in input_txns if input_txn['id'] not in mtxn_ids]

        input_sum = 0
        if self.coinbase:
            self.inputs = []
        else:
            if inputs:
                needed_inputs = []
                done = False
                for y in inputs:
                    print y.id
                    txn = BU.get_transaction_by_id(self.config, self.mongo, y.id, instance=True)
                    for txn_output in txn.outputs:
                        if txn_output.to == my_address:
                            input_sum += txn_output.value
                            needed_inputs.append(y)
                            if input_sum >= (sum([x.value for x in self.outputs])+self.fee):
                                done = True
                                break
                    if done == True:
                        break

                if not done:
                    raise NotEnoughMoneyException('not enough money')
                self.inputs = needed_inputs
            else:
                self.inputs = []

            remainder = input_sum-(sum([x.value for x in self.outputs])+self.fee)

            found = False
            for x in self.outputs:
                if my_address == x.to:
                    found = True
                    x.value += remainder
            if not found:
                return_change_output = Output(
                    to=my_address,
                    value=remainder
                )
                self.outputs.append(return_change_output)
コード例 #4
0
    def __init__(self, transactions, public_key, private_key, version, index=None, force_time=None):
        self.version = version
        if force_time:
            self.time = str(int(force_time))
        else:
            self.time = str(int(time.time()))
        blocks = BU.get_blocks()
        self.index = index
        if self.index == 0:
            self.prev_hash = '' 
        else:
            self.prev_hash = blocks[blocks.count()-1]['hash']
        self.public_key = public_key
        self.private_key = private_key

        transaction_objs = []
        fee_sum = 0.0
        unspent_indexed = {}
        used_sigs = []
        for txn in transactions:
            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
            used_sigs.append(transaction_obj.transaction_signature)
            transaction_obj.verify()
            #check double spend
            address = str(P2PKHBitcoinAddress.from_pubkey(transaction_obj.public_key.decode('hex')))
            if address in unspent_indexed:
                unspent_ids = unspent_indexed[address]
            else:
                res = BU.get_wallet_unspent_transactions(address)
                unspent_ids = [x['id'] for x in res]
                unspent_indexed[address] = unspent_ids

            failed = False
            used_ids_in_this_txn = []
            for x in transaction_obj.inputs:
                if x.id not in unspent_ids:
                    failed = True
                if x.id in used_ids_in_this_txn:
                    failed = True
                used_ids_in_this_txn.append(x.id)
            if not failed:
                transaction_objs.append(transaction_obj)
                fee_sum += float(transaction_obj.fee)
        block_reward = BU.get_block_reward()
        coinbase_txn_fctry = TransactionFactory(
            public_key=self.public_key,
            private_key=self.private_key,
            outputs=[Output(
                value=block_reward + float(fee_sum),
                to=str(P2PKHBitcoinAddress.from_pubkey(self.public_key.decode('hex')))
            )],
            coinbase=True
        )
        coinbase_txn = coinbase_txn_fctry.generate_transaction()
        transaction_objs.append(coinbase_txn)

        self.transactions = transaction_objs
        txn_hashes = self.get_transaction_hashes()
        self.set_merkle_root(txn_hashes)
        self.block = Block(
            version=self.version,
            block_time=self.time,
            block_index=self.index,
            prev_hash=self.prev_hash,
            transactions=self.transactions,
            merkle_root=self.merkle_root,
            public_key=self.public_key
        )
コード例 #5
0
ファイル: block.py プロジェクト: icook/yadacoin
    def __init__(self,
                 config,
                 mongo,
                 transactions,
                 public_key,
                 private_key,
                 version,
                 index=None,
                 force_time=None):
        self.config = config
        self.mongo = mongo
        self.version = BU.get_version_for_height(index)
        if force_time:
            self.time = str(int(force_time))
        else:
            self.time = str(int(time.time()))
        blocks = BU.get_blocks(self.config, self.mongo)
        self.index = index
        if self.index == 0:
            self.prev_hash = ''
        else:
            self.prev_hash = BU.get_latest_block(self.config,
                                                 self.mongo)['hash']
        self.public_key = public_key
        self.private_key = private_key

        transaction_objs = []
        fee_sum = 0.0
        unspent_indexed = {}
        unspent_fastgraph_indexed = {}
        used_sigs = []
        for txn in transactions:
            try:
                if isinstance(txn, Transaction):
                    transaction_obj = txn
                else:
                    transaction_obj = Transaction.from_dict(
                        self.config, self.mongo, txn)

                if transaction_obj.transaction_signature in used_sigs:
                    print 'duplicate transaction found and removed'
                    continue

                used_sigs.append(transaction_obj.transaction_signature)
                transaction_obj.verify()

                if not isinstance(transaction_obj,
                                  FastGraph) and transaction_obj.rid:
                    for input_id in transaction_obj.inputs:
                        input_block = BU.get_transaction_by_id(self.config,
                                                               self.mongo,
                                                               input_id.id,
                                                               give_block=True)
                        if input_block['index'] > (BU.get_latest_block(
                                self.config, self.mongo)['index'] - 2016):
                            continue

            except:
                try:
                    if isinstance(txn, FastGraph):
                        transaction_obj = txn
                    else:
                        transaction_obj = FastGraph(**txn)

                    if transaction_obj.transaction.transaction_signature in used_sigs:
                        print 'duplicate transaction found and removed'
                        continue
                    used_sigs.append(
                        transaction_obj.transaction.transaction_signature)
                    if not transaction_obj.verify():
                        raise InvalidTransactionException(
                            "invalid transactions")
                    transaction_obj = transaction_obj.transaction
                except:
                    raise InvalidTransactionException("invalid transactions")

            address = str(
                P2PKHBitcoinAddress.from_pubkey(
                    transaction_obj.public_key.decode('hex')))
            #check double spend
            if address in unspent_indexed:
                unspent_ids = unspent_indexed[address]
            else:
                res = BU.get_wallet_unspent_transactions(
                    self.config, self.mongo, address)
                unspent_ids = [x['id'] for x in res]
                unspent_indexed[address] = unspent_ids

            if address in unspent_fastgraph_indexed:
                unspent_fastgraph_ids = unspent_fastgraph_indexed[address]
            else:
                res = BU.get_wallet_unspent_fastgraph_transactions(
                    self.config, self.mongo, address)
                unspent_fastgraph_ids = [x['id'] for x in res]
                unspent_fastgraph_indexed[address] = unspent_fastgraph_ids

            failed = False
            used_ids_in_this_txn = []

            for x in transaction_obj.inputs:
                if x.id not in unspent_ids:
                    failed = True
                if x.id in used_ids_in_this_txn:
                    failed = True
                used_ids_in_this_txn.append(x.id)
            if not failed:
                transaction_objs.append(transaction_obj)
                fee_sum += float(transaction_obj.fee)
        block_reward = BU.get_block_reward(self.config, self.mongo)
        coinbase_txn_fctry = TransactionFactory(
            config,
            mongo,
            public_key=self.public_key,
            private_key=self.private_key,
            outputs=[
                Output(value=block_reward + float(fee_sum),
                       to=str(
                           P2PKHBitcoinAddress.from_pubkey(
                               self.public_key.decode('hex'))))
            ],
            coinbase=True)
        coinbase_txn = coinbase_txn_fctry.generate_transaction()
        transaction_objs.append(coinbase_txn)

        self.transactions = transaction_objs
        txn_hashes = self.get_transaction_hashes()
        self.set_merkle_root(txn_hashes)
        self.block = Block(self.config,
                           self.mongo,
                           version=self.version,
                           block_time=self.time,
                           block_index=self.index,
                           prev_hash=self.prev_hash,
                           transactions=self.transactions,
                           merkle_root=self.merkle_root,
                           public_key=self.public_key)
コード例 #6
0
ファイル: miningpool.py プロジェクト: BadPirateX/yadacoin
    def get_pending_transactions(self):
        transaction_objs = []
        unspent_indexed = {}
        used_sigs = []
        for txn in self.combine_transaction_lists():
            try:
                if isinstance(txn, FastGraph) and hasattr(txn, 'signatures'):
                    transaction_obj = txn
                elif isinstance(txn, Transaction):
                    transaction_obj = txn
                elif isinstance(txn, dict) and 'signatures' in txn:
                    transaction_obj = FastGraph.from_dict(self.config, self.mongo, BU.get_latest_block(self.config, self.mongo)['index'], txn)
                elif isinstance(txn, dict):
                    transaction_obj = Transaction.from_dict(self.config, self.mongo, BU.get_latest_block(self.config, self.mongo)['index'], txn)
                else:
                    print 'transaction unrecognizable, skipping'
                    continue

                if transaction_obj.transaction_signature in used_sigs:
                    print 'duplicate transaction found and removed'
                    continue
                used_sigs.append(transaction_obj.transaction_signature)

                transaction_obj.verify()

                if not isinstance(transaction_obj, FastGraph) and transaction_obj.rid:
                    for input_id in transaction_obj.inputs:
                        input_block = BU.get_transaction_by_id(self.config, self.mongo, input_id.id, give_block=True)
                        if input_block and input_block['index'] > (BU.get_latest_block(self.config, self.mongo)['index'] - 2016):
                            continue

                #check double spend
                address = str(P2PKHBitcoinAddress.from_pubkey(transaction_obj.public_key.decode('hex')))
                if address in unspent_indexed:
                    unspent_ids = unspent_indexed[address]
                else:
                    needed_value = sum([float(x.value) for x in transaction_obj.outputs]) + float(transaction_obj.fee)
                    res = BU.get_wallet_unspent_transactions(self.config, self.mongo, address, needed_value=needed_value)
                    unspent_ids = [x['id'] for x in res]
                    unspent_indexed[address] = unspent_ids

                failed1 = False
                failed2 = False
                used_ids_in_this_txn = []

                for x in transaction_obj.inputs:
                    if x.id not in unspent_ids:
                        failed1 = True
                    if x.id in used_ids_in_this_txn:
                        failed2 = True
                    used_ids_in_this_txn.append(x.id)
                if failed1:
                    self.mongo.db.miner_transactions.remove({'id': transaction_obj.transaction_signature})
                    print 'transaction removed: input presumably spent already, not in unspent outputs', transaction_obj.transaction_signature
                    self.mongo.db.failed_transactions.insert({'reason': 'input presumably spent already', 'txn': transaction_obj.to_dict()})
                elif failed2:
                    self.mongo.db.miner_transactions.remove({'id': transaction_obj.transaction_signature})
                    print 'transaction removed: using an input used by another transaction in this block', transaction_obj.transaction_signature
                    self.mongo.db.failed_transactions.insert({'reason': 'using an input used by another transaction in this block', 'txn': transaction_obj.to_dict()})
                else:
                    transaction_objs.append(transaction_obj)
            except MissingInputTransactionException as e:
                #print 'missing this input transaction, will try again later'
                pass
            except InvalidTransactionSignatureException as e:
                print 'InvalidTransactionSignatureException: transaction removed'
                self.mongo.db.miner_transactions.remove({'id': transaction_obj.transaction_signature})
                self.mongo.db.failed_transactions.insert({'reason': 'InvalidTransactionSignatureException', 'txn': transaction_obj.to_dict()})
            except InvalidTransactionException as e:
                print 'InvalidTransactionException: transaction removed'
                self.mongo.db.miner_transactions.remove({'id': transaction_obj.transaction_signature})
                self.mongo.db.failed_transactions.insert({'reason': 'InvalidTransactionException', 'txn': transaction_obj.to_dict()})
            except Exception as e:
                print e
                #print 'rejected transaction', txn['id']
                pass
            except BaseException as e:
                print e
                #print 'rejected transaction', txn['id']
                pass
        return transaction_objs