示例#1
0
    def validate_transactions(self):
        """
        Checks if the incoming transactions are valid
        """

        # create a bigchain instance
        b = Bigchain()

        while True:
            self.monitor.gauge('tx_queue_gauge',
                               self.q_tx_to_validate.qsize(),
                               rate=bigchaindb.config['statsd']['rate'])
            tx = self.q_tx_to_validate.get()

            # poison pill
            if tx == 'stop':
                self.q_tx_delete.put('stop')
                self.q_tx_validated.put('stop')
                return

            self.q_tx_delete.put(tx['_id'])

            with self.monitor.timer('validate_transaction', rate=bigchaindb.config['statsd']['rate']):
                is_valid_transaction = b.is_valid_transaction(tx)

            if is_valid_transaction:
                self.q_tx_validated.put(tx)
示例#2
0
    def validate_transactions(self):
        """
        Checks if the incoming transactions are valid
        """

        # create a bigchain instance
        b = Bigchain()

        while True:
            self.monitor.gauge('tx_queue_gauge',
                               self.q_tx_to_validate.qsize(),
                               rate=bigchaindb.config['statsd']['rate'])
            tx = self.q_tx_to_validate.get()

            # poison pill
            if tx == 'stop':
                self.q_tx_delete.put('stop')
                self.q_tx_validated.put('stop')
                return

            self.q_tx_delete.put(tx['id'])

            with self.monitor.timer('validate_transaction', rate=bigchaindb.config['statsd']['rate']):
                is_valid_transaction = b.is_valid_transaction(tx)

            if is_valid_transaction:
                self.q_tx_validated.put(tx)
示例#3
0
    def validate_transactions(self):
        """
        Checks if the incoming transactions are valid
        """

        # create a bigchain instance
        b = Bigchain()

        while True:
            tx = self.q_tx_to_validate.get()

            # poison pill
            if tx == 'stop':
                self.q_tx_delete.put('stop')
                self.q_tx_validated.put('stop')
                return

            self.q_tx_delete.put(tx['id'])
            if b.is_valid_transaction(tx):
                self.q_tx_validated.put(tx)
示例#4
0
    def validate_transactions(self):
        """
        Checks if the incoming transactions are valid
        """

        # create a bigchain instance
        b = Bigchain()

        while True:
            tx = self.q_tx_to_validate.get()

            # poison pill
            if tx == 'stop':
                self.q_tx_delete.put('stop')
                self.q_tx_validated.put('stop')
                return

            self.q_tx_delete.put(tx['id'])
            if b.is_valid_transaction(tx):
                self.q_tx_validated.put(tx)
class Vote:
    """This class encapsulates the logic to vote on blocks.

    Note:
        Methods of this class will be executed in different processes.
    """

    def __init__(self):
        """Initialize the Block voter."""

        # Since cannot share a connection to RethinkDB using multiprocessing,
        # we need to create a temporary instance of BigchainDB that we use
        # only to query RethinkDB
        self.consensus = BaseConsensusRules

        # This is the Bigchain instance that will be "shared" (aka: copied)
        # by all the subprocesses
        self.bigchain = Bigchain()
        self.last_voted_id = Bigchain().get_last_voted_block().id

        self.counters = Counter()
        self.validity = {}

        self.invalid_dummy_tx = Transaction.create([self.bigchain.me],
                                                   [self.bigchain.me])

    def validate_block(self, block):
        if not self.bigchain.has_previous_vote(block['id'], block['block']['voters']):
            try:
                block = Block.from_dict(block)
            except (exceptions.InvalidHash, exceptions.InvalidSignature):
                # XXX: if a block is invalid we should skip the `validate_tx`
                # step, but since we are in a pipeline we cannot just jump to
                # another function. Hackish solution: generate an invalid
                # transaction and propagate it to the next steps of the
                # pipeline.
                return block['id'], [self.invalid_dummy_tx]
            try:
                self.consensus.validate_block(self.bigchain, block)
            except (exceptions.InvalidHash,
                    exceptions.OperationError,
                    exceptions.InvalidSignature):
                # XXX: if a block is invalid we should skip the `validate_tx`
                # step, but since we are in a pipeline we cannot just jump to
                # another function. Hackish solution: generate an invalid
                # transaction and propagate it to the next steps of the
                # pipeline.
                return block.id, [self.invalid_dummy_tx]
            return block.id, block.transactions

    def ungroup(self, block_id, transactions):
        """Given a block, ungroup the transactions in it.

        Args:
            block_id (str): the id of the block in progress.
            transactions (list(Transaction)): transactions of the block in
                progress.

        Returns:
            ``None`` if the block has been already voted, an iterator that
            yields a transaction, block id, and the total number of
            transactions contained in the block otherwise.
        """

        num_tx = len(transactions)
        for tx in transactions:
            yield tx, block_id, num_tx

    def validate_tx(self, tx, block_id, num_tx):
        """Validate a transaction.

        Args:
            tx (dict): the transaction to validate
            block_id (str): the id of block containing the transaction
            num_tx (int): the total number of transactions to process

        Returns:
            Three values are returned, the validity of the transaction,
            ``block_id``, ``num_tx``.
        """
        return bool(self.bigchain.is_valid_transaction(tx)), block_id, num_tx

    def vote(self, tx_validity, block_id, num_tx):
        """Collect the validity of transactions and cast a vote when ready.

        Args:
            tx_validity (bool): the validity of the transaction
            block_id (str): the id of block containing the transaction
            num_tx (int): the total number of transactions to process

        Returns:
            None, or a vote if a decision has been reached.
        """

        self.counters[block_id] += 1
        self.validity[block_id] = tx_validity and self.validity.get(block_id,
                                                                    True)

        if self.counters[block_id] == num_tx:
            vote = self.bigchain.vote(block_id,
                                      self.last_voted_id,
                                      self.validity[block_id])
            self.last_voted_id = block_id
            del self.counters[block_id]
            del self.validity[block_id]
            return vote

    def write_vote(self, vote):
        """Write vote to the database.

        Args:
            vote: the vote to write.
        """

        self.bigchain.write_vote(vote)
        return vote
示例#6
0
class Block:
    """This class encapsulates the logic to create blocks.

    Note:
        Methods of this class will be executed in different processes.
    """

    def __init__(self):
        """Initialize the Block creator"""
        self.bigchain = Bigchain()
        self.txs = []

    def filter_tx(self, tx):
        """Filter a transaction.

        Args:
            tx (dict): the transaction to process.

        Returns:
            The transaction if assigned to the current node,
            ``None`` otherwise.
        """

        if tx['assignee'] == self.bigchain.me:
            tx.pop('assignee')
            tx.pop('assignment_timestamp')
            return tx

    def validate_tx(self, tx):
        """Validate a transaction.
        Also checks if the transaction already exists in the blockchain. If it
        does, or it's invalid, it's deleted from the backlog immediately.
        Args:
            tx (dict): the transaction to validate.
        Returns:
            The transaction if valid, ``None`` otherwise.
        """
        if self.bigchain.transaction_exists(tx['id']):
            # if the transaction already exists, we must check whether
            # it's in a valid or undecided block
            tx, status = self.bigchain.get_transaction(tx['id'],
                                                       include_status=True)
            if status == self.bigchain.TX_VALID \
               or status == self.bigchain.TX_UNDECIDED:
                # if the tx is already in a valid or undecided block,
                # then it no longer should be in the backlog, or added
                # to a new block. We can delete and drop it.
                r.table('backlog').get(tx['id']) \
                        .delete(durability='hard') \
                        .run(self.bigchain.conn)
                return None

        tx_validated = self.bigchain.is_valid_transaction(tx)
        if tx_validated:
            return tx
        else:
            # if the transaction is not valid, remove it from the
            # backlog
            r.table('backlog').get(tx['id']) \
                    .delete(durability='hard') \
                    .run(self.bigchain.conn)
            return None

    def create(self, tx, timeout=False):
        """Create a block.

        This method accumulates transactions to put in a block and outputs
        a block when one of the following conditions is true:
        - the size limit of the block has been reached, or
        - a timeout happened.

        Args:
            tx (dict): the transaction to validate, might be None if
                a timeout happens.
            timeout (bool): ``True`` if a timeout happened
                (Default: ``False``).

        Returns:
            The block, if a block is ready, or ``None``.
        """
        if tx:
            self.txs.append(tx)
        if len(self.txs) == 1000 or (timeout and self.txs):
            block = self.bigchain.create_block(self.txs)
            self.txs = []
            return block

    def write(self, block):
        """Write the block to the Database.

        Args:
            block (dict): the block of transactions to write to the database.

        Returns:
            The block.
        """
        logger.info('Write new block %s with %s transactions',
                    block['id'],
                    len(block['block']['transactions']))
        self.bigchain.write_block(block)
        return block

    def delete_tx(self, block):
        """Delete transactions.
        Args:
            block (dict): the block containg the transactions to delete.
        Returns:
            The block.
        """
        r.table('backlog')\
         .get_all(*[tx['id'] for tx in block['block']['transactions']])\
         .delete(durability='hard')\
         .run(self.bigchain.conn)

        return block
示例#7
0
class Vote:
    """This class encapsulates the logic to vote on blocks.

    Note:
        Methods of this class will be executed in different processes.
    """

    def __init__(self):
        """Initialize the Block voter."""

        # Since cannot share a connection to RethinkDB using multiprocessing,
        # we need to create a temporary instance of BigchainDB that we use
        # only to query RethinkDB
        self.consensus = BaseConsensusRules

        # This is the Bigchain instance that will be "shared" (aka: copied)
        # by all the subprocesses
        self.bigchain = Bigchain()
        self.last_voted_id = Bigchain().get_last_voted_block().id

        self.counters = Counter()
        self.validity = {}

        self.invalid_dummy_tx = Transaction.create([self.bigchain.me],
                                                   [([self.bigchain.me], 1)])

    def validate_block(self, block):
        if not self.bigchain.has_previous_vote(block['id'],
                                               block['block']['voters']):
            try:
                block = Block.from_dict(block)
            except (exceptions.InvalidHash, exceptions.InvalidSignature):
                # XXX: if a block is invalid we should skip the `validate_tx`
                # step, but since we are in a pipeline we cannot just jump to
                # another function. Hackish solution: generate an invalid
                # transaction and propagate it to the next steps of the
                # pipeline.
                return block['id'], [self.invalid_dummy_tx]
            try:
                self.consensus.validate_block(self.bigchain, block)
            except (exceptions.InvalidHash,
                    exceptions.OperationError,
                    exceptions.InvalidSignature):
                # XXX: if a block is invalid we should skip the `validate_tx`
                # step, but since we are in a pipeline we cannot just jump to
                # another function. Hackish solution: generate an invalid
                # transaction and propagate it to the next steps of the
                # pipeline.
                return block.id, [self.invalid_dummy_tx]
            return block.id, block.transactions

    def ungroup(self, block_id, transactions):
        """Given a block, ungroup the transactions in it.

        Args:
            block_id (str): the id of the block in progress.
            transactions (list(Transaction)): transactions of the block in
                progress.

        Returns:
            ``None`` if the block has been already voted, an iterator that
            yields a transaction, block id, and the total number of
            transactions contained in the block otherwise.
        """

        num_tx = len(transactions)
        for tx in transactions:
            yield tx, block_id, num_tx

    def validate_tx(self, tx, block_id, num_tx):
        """Validate a transaction.

        Args:
            tx (dict): the transaction to validate
            block_id (str): the id of block containing the transaction
            num_tx (int): the total number of transactions to process

        Returns:
            Three values are returned, the validity of the transaction,
            ``block_id``, ``num_tx``.
        """
        return bool(self.bigchain.is_valid_transaction(tx)), block_id, num_tx

    def vote(self, tx_validity, block_id, num_tx):
        """Collect the validity of transactions and cast a vote when ready.

        Args:
            tx_validity (bool): the validity of the transaction
            block_id (str): the id of block containing the transaction
            num_tx (int): the total number of transactions to process

        Returns:
            None, or a vote if a decision has been reached.
        """

        self.counters[block_id] += 1
        self.validity[block_id] = tx_validity and self.validity.get(block_id,
                                                                    True)

        if self.counters[block_id] == num_tx:
            vote = self.bigchain.vote(block_id,
                                      self.last_voted_id,
                                      self.validity[block_id])
            self.last_voted_id = block_id
            del self.counters[block_id]
            del self.validity[block_id]
            return vote

    def write_vote(self, vote):
        """Write vote to the database.

        Args:
            vote: the vote to write.
        """

        self.bigchain.write_vote(vote)
        return vote
示例#8
0
testuser1_priv, testuser1_pub = crypto.generate_key_pair()
print("testuser1_priv:" + testuser1_priv)
print("testuser1_pub:" + testuser1_pub)
payload = {
    "msg": "first charge for user A",
    "issue": "charge",
    "category": "currency",
    "amount": 300,
    "asset": "",
    "account": 0,
    "previous": "genesis",
    "trader": ""
}
tx = b.create_transaction(b.me, testuser1_pub, None, 'CREATE', payload=payload)
tx_signed = b.sign_transaction(tx, b.me_private)
if b.is_valid_transaction(tx_signed):
    b.write_transaction(tx_signed)
    print(tx_signed)

# user B
testuser2_priv, testuser2_pub = crypto.generate_key_pair()
print("testuser2_priv:" + testuser2_priv)
print("testuser2_pub:" + testuser2_pub)
payload2 = {
    "msg": "first charge for user B",
    "issue": "charge",
    "category": "currency",
    "amount": 400,
    "asset": "",
    "account": 0,
    "previous": "genesis",
示例#9
0
class Block:
    """This class encapsulates the logic to create blocks.

    Note:
        Methods of this class will be executed in different processes.
    """
    def __init__(self):
        """Initialize the Block creator"""
        self.bigchain = Bigchain()
        self.txs = []

    def filter_tx(self, tx):
        """Filter a transaction.

        Args:
            tx (dict): the transaction to process.

        Returns:
            The transaction if assigned to the current node,
            ``None`` otherwise.
        """

        if tx['assignee'] == self.bigchain.me:
            tx.pop('assignee')
            return tx

    def delete_tx(self, tx):
        """Delete a transaction.

        Args:
            tx (dict): the transaction to delete.

        Returns:
            The transaction.
        """
        r.table('backlog')\
         .get(tx['id'])\
         .delete(durability='hard')\
         .run(self.bigchain.conn)

        return tx

    def validate_tx(self, tx):
        """Validate a transaction.

        Args:
            tx (dict): the transaction to validate.

        Returns:
            The transaction if valid, ``None`` otherwise.
        """
        tx = self.bigchain.is_valid_transaction(tx)
        if tx:
            return tx

    def create(self, tx, timeout=False):
        """Create a block.

        This method accumulates transactions to put in a block and outputs
        a block when one of the following conditions is true:
        - the size limit of the block has been reached, or
        - a timeout happened.

        Args:
            tx (dict): the transaction to validate, might be None if
                a timeout happens.
            timeout (bool): ``True`` if a timeout happened
                (Default: ``False``).

        Returns:
            The block, if a block is ready, or ``None``.
        """
        if tx:
            self.txs.append(tx)
        if len(self.txs) == 1000 or (timeout and self.txs):
            block = self.bigchain.create_block(self.txs)
            self.txs = []
            return block

    def write(self, block):
        """Write the block to the Database.

        Args:
            block (dict): the block of transactions to write to the database.

        Returns:
            The block.
        """
        logger.info('Write new block %s with %s transactions', block['id'],
                    len(block['block']['transactions']))
        self.bigchain.write_block(block)
        return block
示例#10
0
payload_A = {
            "msg" : "node send -50 to A,is -50",
            "issue" : "cost",
            "category" : "currency",
            "amount" : 50,
            "asset":"",
            # final owner 's account
            "account":300,
            "previous":testuser1_last['txid'],
            "trader":testuser2_pub
          }

tx_create= b.create_transaction(b.me, testuser1_pub, None, 'CREATE', payload=payload_A)
tx_create_signed = b.sign_transaction(tx_create, b.me_private)
if b.is_valid_transaction(tx_create_signed):
    b.write_transaction(tx_create_signed)

# node create transaction for b,
testuser2_last=b.get_owned_ids(testuser2_pub).pop()
payload_B = {
            "msg" : "node send +50 to B,is +50",
            "issue" : "earn",
            "category" : "currency",
            "amount" : 50,
            "asset":"",
            # final owner 's account
            "account":400,
            "previous":testuser2_last['txid'],
            "trader":testuser1_pub
          }
    'condition': {
        'uri': first_tx_condition.condition.serialize_uri()
    },
    'cid': 0,
    'new_owners': None
})

# Conditions have been updated, so hash needs updating
hashlock_tx['id'] = util.get_hash_data(hashlock_tx)

# The asset needs to be signed by the current_owner
hashlock_tx_signed = b.sign_transaction(hashlock_tx, b.me_private)

# Some validations
assert b.validate_transaction(hashlock_tx_signed) == hashlock_tx_signed
assert b.is_valid_transaction(hashlock_tx_signed) == hashlock_tx_signed

b.write_transaction(hashlock_tx_signed)
print(json.dumps(hashlock_tx_signed, sort_keys=True, indent=4, separators=(',', ':')))

sleep(8)

hashlockuser_priv, hashlockuser_pub = crypto.generate_key_pair()

# create hashlock fulfillment tx
hashlock_fulfill_tx = b.create_transaction(None, hashlockuser_priv, {'txid': hashlock_tx['id'], 'cid': 0}, 'TRANSFER')

# try a wrong secret
hashlock_fulfill_tx_fulfillment = cc.PreimageSha256Fulfillment(preimage=b'')
hashlock_fulfill_tx['transaction']['fulfillments'][0]['fulfillment'] = \
    hashlock_fulfill_tx_fulfillment.serialize_uri()
示例#12
0
testuser1_priv, testuser1_pub = crypto.generate_key_pair()
print("testuser1_priv:"+testuser1_priv)
print("testuser1_pub:"+testuser1_pub)
payload = {
            "msg" : "first charge for user A",
            "issue" : "charge",
            "category" : "currency",
            "amount" : 300,
            "asset":"",
            "account":0,
            "previous":"genesis",
            "trader":""
          }
tx = b.create_transaction(b.me, testuser1_pub, None, 'CREATE', payload=payload)
tx_signed = b.sign_transaction(tx, b.me_private)
if b.is_valid_transaction(tx_signed):
    b.write_transaction(tx_signed)
    print(tx_signed)


# user B
testuser2_priv, testuser2_pub = crypto.generate_key_pair()
print("testuser2_priv:"+testuser2_priv)
print("testuser2_pub:"+testuser2_pub)
payload2 = {
            "msg" : "first charge for user B",
            "issue" : "charge",
            "category" : "currency",
            "amount" : 400,
            "asset":"",
            "account":0,
示例#13
0
class ChainQuery(object):

    def __init__(self, host=None, port=None, dbname=None,pub_key=None,priv_key=None,keyring=[],
                 consensus_plugin=None):
         self.host = host
         self.port = port
         self.dbname = dbname
         self.conn =r.connect(host=host,port=port,db=dbname)
         self.bigchain=Bigchain(host=host,port=port,dbname=dbname,public_key=pub_key,private_key=priv_key,keyring=keyring,consensus_plugin=consensus_plugin)

    #test
    def test(self):
        tables=r.db('bigchain').table_list().run(self.conn)
        #print(tables)
        return tables

    # create key_pair for user
    def generate_key_pair(self):
        return crypto.generate_key_pair()

    # create asset
    def create_asset(self,public_key, digital_asset_payload):
        tx = self.bigchain.create_transaction(self.bigchain.me, public_key, None, 'CREATE', payload=digital_asset_payload)
        tx_signed = self.bigchain.sign_transaction(tx, self.bigchain.me_private)
        return self.bigchain.write_transaction(tx_signed)

    # get transaction by payload_uuid
    def getTxid_by_payload_uuid(self,payload_uuid):
        cursor = r.table('bigchain') \
            .get_all(payload_uuid, index='payload_uuid') \
            .pluck({'block':{'transactions':'id'}}) \
            .run(self.conn)

        transactions = list(cursor)
        return transactions

    # get transaction by payload
    def getTxid_by_payload(self,payload):
        pass


    # get currentowner of a payload(assert)
    def getOwnerofAssert(self,payload):
        return


    # get one's assert
    def get_owned_asserts(self,pub_key):
        return

    # if tx contains someone
    def tx_contains_one(self,tx,one_pub):
        for condition in tx['conditions']:
            if one_pub in condition['new_owners']:
                return True
        for fullfillment in tx['fulfillments']:
            if one_pub in fullfillment['current_owners']:
                return True


    # transfer assert to another, old_owner create this transaction,so need old_owner's pub/priv key.
    def transfer_assert(self,old_owner_pub,old_owner_priv,new_owner_pub,tx_id):
        tx_transfer=self.bigchain.create_transaction(old_owner_pub,new_owner_pub,tx_id,'TRANSFER')
        tx_transfer_signed=self.bigchain.sign_transaction(tx_transfer,old_owner_priv)
        #check if the transaction is valid
        check=self.bigchain.is_valid_transaction(tx_transfer_signed)
        if check:
            self.bigchain.write_transaction(tx_transfer_signed)
        else:
            logger.info('this transaction is invalid.')
示例#14
0
class BlockPipeline:
    """This class encapsulates the logic to create blocks.

    Note:
        Methods of this class will be executed in different processes.
    """
    def __init__(self):
        """Initialize the BlockPipeline creator"""
        self.bigchain = Bigchain()
        self.txs = []

    def filter_tx(self, tx):
        """Filter a transaction.

        Args:
            tx (dict): the transaction to process.

        Returns:
            dict: The transaction if assigned to the current node,
            ``None`` otherwise.
        """
        if tx['assignee'] == self.bigchain.me:
            tx.pop('assignee')
            tx.pop('assignment_timestamp')
            return tx

    def validate_tx(self, tx):
        """Validate a transaction.

        Also checks if the transaction already exists in the blockchain. If it
        does, or it's invalid, it's deleted from the backlog immediately.

        Args:
            tx (dict): the transaction to validate.

        Returns:
            :class:`~bigchaindb.models.Transaction`: The transaction if valid,
            ``None`` otherwise.
        """
        try:
            tx = Transaction.from_dict(tx)
        except (SchemaValidationError, InvalidHash, InvalidSignature,
                AmountError):
            return None

        # If transaction is in any VALID or UNDECIDED block we
        # should not include it again
        if not self.bigchain.is_new_transaction(tx.id):
            self.bigchain.delete_transaction(tx.id)
            return None

        # If transaction is not valid it should not be included
        if not self.bigchain.is_valid_transaction(tx):
            self.bigchain.delete_transaction(tx.id)
            return None

        return tx

    def create(self, tx, timeout=False):
        """Create a block.

        This method accumulates transactions to put in a block and outputs
        a block when one of the following conditions is true:
        - the size limit of the block has been reached, or
        - a timeout happened.

        Args:
            tx (:class:`~bigchaindb.models.Transaction`): the transaction
                to validate, might be None if a timeout happens.
            timeout (bool): ``True`` if a timeout happened
                (Default: ``False``).

        Returns:
            :class:`~bigchaindb.models.Block`: The block,
            if a block is ready, or ``None``.
        """
        if tx:
            self.txs.append(tx)
        if len(self.txs) == 1000 or (timeout and self.txs):
            block = self.bigchain.create_block(self.txs)
            self.txs = []
            return block

    def write(self, block):
        """Write the block to the Database.

        Args:
            block (:class:`~bigchaindb.models.Block`): the block of
                transactions to write to the database.

        Returns:
            :class:`~bigchaindb.models.Block`: The Block.
        """
        logger.info('Write new block %s with %s transactions', block.id,
                    len(block.transactions))
        self.bigchain.write_block(block)
        return block

    def delete_tx(self, block):
        """Delete transactions.

        Args:
            block (:class:`~bigchaindb.models.Block`): the block
                containg the transactions to delete.

        Returns:
            :class:`~bigchaindb.models.Block`: The block.
        """
        self.bigchain.delete_transaction(*[tx.id for tx in block.transactions])
        return block
示例#15
0
class ChainQuery(object):
    def __init__(
        self, host=None, port=None, dbname=None, pub_key=None, priv_key=None, keyring=[], consensus_plugin=None
    ):
        self.host = host
        self.port = port
        self.dbname = dbname
        self.conn = r.connect(host=host, port=port, db=dbname)
        self.bigchain = Bigchain(
            host=host,
            port=port,
            dbname=dbname,
            public_key=pub_key,
            private_key=priv_key,
            keyring=keyring,
            consensus_plugin=consensus_plugin,
        )

    # test
    def test(self):
        tables = r.db("bigchain").table_list().run(self.conn)
        # print(tables)
        return tables

    # create key_pair for user
    def generate_key_pair(self):
        return crypto.generate_key_pair()

    # create asset
    def create_asset(self, public_key, digital_asset_payload):
        tx = self.bigchain.create_transaction(
            self.bigchain.me, public_key, None, "CREATE", payload=digital_asset_payload
        )
        tx_signed = self.bigchain.sign_transaction(tx, self.bigchain.me_private)
        return self.bigchain.write_transaction(tx_signed)

    # get transaction by payload_uuid
    def getTxid_by_payload_uuid(self, payload_uuid):
        cursor = (
            r.table("bigchain")
            .get_all(payload_uuid, index="payload_uuid")
            .pluck({"block": {"transactions": "id"}})
            .run(self.conn)
        )

        transactions = list(cursor)
        return transactions

    # get transaction by payload
    def getTxid_by_payload(self, payload):
        pass

    # get currentowner of a payload(assert)
    def getOwnerofAssert(self, payload):
        return

    # get one's assert
    def get_owned_asserts(self, pub_key):
        return

    # if tx contains someone
    def tx_contains_one(self, tx, one_pub):
        for condition in tx["conditions"]:
            if one_pub in condition["new_owners"]:
                return True
        for fullfillment in tx["fulfillments"]:
            if one_pub in fullfillment["current_owners"]:
                return True

    # transfer assert to another, old_owner create this transaction,so need old_owner's pub/priv key.
    def transfer_assert(self, old_owner_pub, old_owner_priv, new_owner_pub, tx_id):
        tx_transfer = self.bigchain.create_transaction(old_owner_pub, new_owner_pub, tx_id, "TRANSFER")
        tx_transfer_signed = self.bigchain.sign_transaction(tx_transfer, old_owner_priv)
        # check if the transaction is valid
        check = self.bigchain.is_valid_transaction(tx_transfer_signed)
        if check:
            self.bigchain.write_transaction(tx_transfer_signed)
        else:
            logger.info("this transaction is invalid.")
示例#16
0
class Block:
    """This class encapsulates the logic to create blocks.

    Note:
        Methods of this class will be executed in different processes.
    """

    def __init__(self):
        """Initialize the Block creator"""
        self.bigchain = Bigchain()
        self.txs = []

    def filter_tx(self, tx):
        """Filter a transaction.

        Args:
            tx (dict): the transaction to process.

        Returns:
            The transaction if assigned to the current node,
            ``None`` otherwise.
        """

        if tx['assignee'] == self.bigchain.me:
            tx.pop('assignee')
            tx.pop('assignment_timestamp')
            return tx

    def validate_tx(self, tx):
        """Validate a transaction.

        Also checks if the transaction already exists in the blockchain. If it
        does, or it's invalid, it's deleted from the backlog immediately.

        Args:
            tx (dict): the transaction to validate.

        Returns:
            The transaction if valid, ``None`` otherwise.
        """
        if self.bigchain.transaction_exists(tx['id']):
            # if the transaction already exists, we must check whether
            # it's in a valid or undecided block
            tx, status = self.bigchain.get_transaction(tx['id'],
                                                       include_status=True)
            if status == self.bigchain.TX_VALID \
               or status == self.bigchain.TX_UNDECIDED:
                # if the tx is already in a valid or undecided block,
                # then it no longer should be in the backlog, or added
                # to a new block. We can delete and drop it.
                r.table('backlog').get(tx['id']) \
                        .delete(durability='hard') \
                        .run(self.bigchain.conn)
                return None

        tx_validated = self.bigchain.is_valid_transaction(tx)
        if tx_validated:
            return tx
        else:
            # if the transaction is not valid, remove it from the
            # backlog
            r.table('backlog').get(tx['id']) \
                    .delete(durability='hard') \
                    .run(self.bigchain.conn)
            return None 

    def create(self, tx, timeout=False):
        """Create a block.

        This method accumulates transactions to put in a block and outputs
        a block when one of the following conditions is true:
        - the size limit of the block has been reached, or
        - a timeout happened.

        Args:
            tx (dict): the transaction to validate, might be None if
                a timeout happens.
            timeout (bool): ``True`` if a timeout happened
                (Default: ``False``).

        Returns:
            The block, if a block is ready, or ``None``.
        """
        if tx:
            self.txs.append(tx)
        if len(self.txs) == 1000 or (timeout and self.txs):
            block = self.bigchain.create_block(self.txs)
            self.txs = []
            return block

    def write(self, block):
        """Write the block to the Database.

        Args:
            block (dict): the block of transactions to write to the database.

        Returns:
            The block.
        """
        logger.info('Write new block %s with %s transactions',
                    block['id'],
                    len(block['block']['transactions']))
        self.bigchain.write_block(block)
        return block

    def delete_tx(self, block):
        """Delete transactions.

        Args:
            block (dict): the block containg the transactions to delete.

        Returns:
            The block.
        """
        r.table('backlog')\
         .get_all(*[tx['id'] for tx in block['block']['transactions']])\
         .delete(durability='hard')\
         .run(self.bigchain.conn)

        return block
示例#17
0
class Block:
    """This class encapsulates the logic to create blocks.

    Note:
        Methods of this class will be executed in different processes.
    """

    def __init__(self):
        """Initialize the Block creator"""
        self.bigchain = Bigchain()
        self.txs = []

    def filter_tx(self, tx):
        """Filter a transaction.

        Args:
            tx (dict): the transaction to process.

        Returns:
            The transaction if assigned to the current node,
            ``None`` otherwise.
        """

        if tx['assignee'] == self.bigchain.me:
            tx.pop('assignee')
            return tx

    def delete_tx(self, tx):
        """Delete a transaction.

        Args:
            tx (dict): the transaction to delete.

        Returns:
            The transaction.
        """
        r.table('backlog')\
         .get(tx['id'])\
         .delete(durability='hard')\
         .run(self.bigchain.conn)

        return tx

    def validate_tx(self, tx):
        """Validate a transaction.

        Args:
            tx (dict): the transaction to validate.

        Returns:
            The transaction if valid, ``None`` otherwise.
        """
        tx = self.bigchain.is_valid_transaction(tx)
        if tx:
            return tx

    def create(self, tx, timeout=False):
        """Create a block.

        This method accumulates transactions to put in a block and outputs
        a block when one of the following conditions is true:
        - the size limit of the block has been reached, or
        - a timeout happened.

        Args:
            tx (dict): the transaction to validate, might be None if
                a timeout happens.
            timeout (bool): ``True`` if a timeout happened
                (Default: ``False``).

        Returns:
            The block, if a block is ready, or ``None``.
        """
        if tx:
            self.txs.append(tx)
        if len(self.txs) == 1000 or (timeout and self.txs):
            block = self.bigchain.create_block(self.txs)
            self.txs = []
            return block

    def write(self, block):
        """Write the block to the Database.

        Args:
            block (dict): the block of transactions to write to the database.

        Returns:
            The block.
        """
        logger.info('Write new block %s with %s transactions',
                    block['id'],
                    len(block['block']['transactions']))
        self.bigchain.write_block(block)
        return block