Exemplo n.º 1
0
    def from_dict(cls, block_body):
        """Transform a Python dictionary to a Block object.

        Args:
            block_body (dict): A block dictionary to be transformed.

        Returns:
            :class:`~Block`

        Raises:
            InvalidHash: If the block's id is not corresponding to its
                data.
        """
        # Validate block id
        block = block_body['block']
        block_serialized = serialize(block)
        block_id = hash_data(block_serialized)

        if block_id != block_body['id']:
            raise InvalidHash()

        transactions = [
            Transaction.from_dict(tx) for tx in block['transactions']
        ]

        signature = block_body.get('signature')

        return cls(transactions, block['node_pubkey'], block['timestamp'],
                   block['voters'], signature)
Exemplo n.º 2
0
    def test_sign_block(self, b, alice):
        from bigchaindb.common.crypto import PrivateKey, PublicKey
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transactions = [
            Transaction.create([alice.public_key], [([alice.public_key], 1)])
        ]
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected_block = {
            'timestamp': timestamp,
            'transactions': [tx.to_dict() for tx in transactions],
            'node_pubkey': alice.public_key,
            'voters': voters,
        }
        expected_block_serialized = serialize(expected_block).encode()
        expected = PrivateKey(
            alice.private_key).sign(expected_block_serialized)
        block = Block(transactions, alice.public_key, timestamp, voters)
        block = block.sign(alice.private_key)
        assert block.signature == expected.decode()

        public_key = PublicKey(alice.public_key)
        assert public_key.verify(expected_block_serialized, block.signature)
def test_valid_block_voting_sequential(b, genesis_block, monkeypatch):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.pipelines import vote

    monkeypatch.setattr('time.time', lambda: 1111111111)
    vote_obj = vote.Vote()
    block = dummy_block(b).to_dict()
    txs = block['block']['transactions']

    for tx, block_id, num_tx in vote_obj.ungroup(block['id'], txs):
        last_vote = vote_obj.vote(*vote_obj.validate_tx(tx, block_id, num_tx))

    vote_obj.write_vote(*last_vote)
    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block_id,
                                                    b.me)
    vote_doc = vote_rs.next()

    assert vote_doc['vote'] == {
        'voting_for_block': block['id'],
        'previous_block': genesis_block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
Exemplo n.º 4
0
    def vote(self, block_id, previous_block_id, decision, invalid_reason=None):
        """Create a signed vote for a block given the
        :attr:`previous_block_id` and the :attr:`decision` (valid/invalid).

        Args:
            block_id (str): The id of the block to vote on.
            previous_block_id (str): The id of the previous block.
            decision (bool): Whether the block is valid or invalid.
            invalid_reason (Optional[str]): Reason the block is invalid
        """

        if block_id == previous_block_id:
            raise exceptions.CyclicBlockchainError()

        vote = {
            'voting_for_block': block_id,
            'previous_block': previous_block_id,
            'is_block_valid': decision,
            'invalid_reason': invalid_reason,
            'timestamp': gen_timestamp()
        }

        vote_data = serialize(vote)
        signature = crypto.PrivateKey(self.me_private).sign(vote_data.encode())

        vote_signed = {
            'node_pubkey': self.me,
            'signature': signature.decode(),
            'vote': vote
        }

        return vote_signed
Exemplo n.º 5
0
    def test_block_invalid_signature(self, b, alice):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.exceptions import InvalidSignature
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transaction = Transaction.create([alice.public_key],
                                         [([alice.public_key], 1)])
        transaction.sign([alice.private_key])
        timestamp = gen_timestamp()

        block = {
            'timestamp': timestamp,
            'transactions': [transaction.to_dict()],
            'node_pubkey': alice.public_key,
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': 'an invalid signature',
        }

        with raises(InvalidSignature):
            Block.from_dict(block_body).validate(b)
Exemplo n.º 6
0
    def test_block_deserialization(self, b):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transaction = Transaction.create([b.me], [([b.me], 1)])
        transaction.sign([b.me_private])
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected = Block([transaction], b.me, timestamp, voters)

        block = {
            'timestamp': timestamp,
            'transactions': [transaction.to_dict()],
            'node_pubkey': b.me,
            'voters': voters,
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': None,
        }

        assert expected == Block.from_dict(block_body)
Exemplo n.º 7
0
    def to_dict(self):
        """Transform the Block to a Python dictionary.

        Returns:
            dict: The Block as a dict.

        Raises:
            OperationError: If the Block doesn't contain any transactions.
        """
        if len(self.transactions) == 0:
            raise OperationError('Empty block creation is not allowed')

        block = {
            'timestamp': self.timestamp,
            'transactions': [tx.to_dict() for tx in self.transactions],
            'node_pubkey': self.node_pubkey,
            'voters': self.voters,
        }
        block_serialized = serialize(block)
        block_id = hash_data(block_serialized)

        return {
            'id': block_id,
            'block': block,
            'signature': self.signature,
        }
Exemplo n.º 8
0
    def test_block_serialization(self, b, alice):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transactions = [
            Transaction.create([alice.public_key], [([alice.public_key], 1)])
        ]
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected_block = {
            'timestamp': timestamp,
            'transactions': [tx.to_dict() for tx in transactions],
            'node_pubkey': alice.public_key,
            'voters': voters,
        }
        expected = {
            'id': hash_data(serialize(expected_block)),
            'block': expected_block,
            'signature': None,
        }

        block = Block(transactions, alice.public_key, timestamp, voters)

        assert block.to_dict() == expected
Exemplo n.º 9
0
    def verify_vote_signature(cls, vote):
        """Verify the signature of a vote
        """
        signature = vote.get('signature')
        pk_base58 = vote.get('node_pubkey')

        if not (type(signature) == str and type(pk_base58) == str):
            raise ValueError('Malformed vote: %s' % vote)

        public_key = PublicKey(pk_base58)
        body = serialize(vote['vote']).encode()
        return public_key.verify(body, signature)
Exemplo n.º 10
0
def test_transaction_unicode(b, alice):
    from bigchaindb.common.utils import serialize
    from bigchaindb.models import Transaction

    # http://www.fileformat.info/info/unicode/char/1f37a/index.htm
    beer_python = {'beer': '\N{BEER MUG}'}
    beer_json = '{"beer":"\N{BEER MUG}"}'

    tx = (Transaction.create([alice.public_key], [([alice.public_key], 100)],
                             beer_python)).sign([alice.private_key])
    block = b.create_block([tx])
    b.write_block(block)
    assert b.get_block(block.id) == block.to_dict()
    assert block.validate(b) == block
    assert beer_json in serialize(block.to_dict())
Exemplo n.º 11
0
    def sign(self, private_key):
        """Create a signature for the Block and overwrite `self.signature`.

        Args:
            private_key (str): A private key corresponding to
                `self.node_pubkey`.

        Returns:
            :class:`~.Block`
        """
        block_body = self.to_dict()
        block_serialized = serialize(block_body['block'])
        private_key = PrivateKey(private_key)
        self.signature = private_key.sign(block_serialized.encode()).decode()
        return self
def test_transaction_unicode(b, alice):
    import copy
    from bigchaindb.common.utils import serialize
    from bigchaindb.models import Transaction

    # http://www.fileformat.info/info/unicode/char/1f37a/index.htm
    beer_python = {'beer': '\N{BEER MUG}'}
    beer_json = '{"beer":"\N{BEER MUG}"}'

    tx = (Transaction.create([alice.public_key], [([alice.public_key], 100)],
                             beer_python)).sign([alice.private_key])

    tx_1 = copy.deepcopy(tx)
    b.store_bulk_transactions([tx])

    assert beer_json in serialize(tx_1.to_dict())
Exemplo n.º 13
0
    def is_signature_valid(self):
        """Check the validity of a Block's signature.

        Returns:
            bool: Stating the validity of the Block's signature.
        """
        block = self.to_dict()['block']
        # cc only accepts bytestring messages
        block_serialized = serialize(block).encode()
        public_key = PublicKey(block['node_pubkey'])
        try:
            # NOTE: CC throws a `ValueError` on some wrong signatures
            #       https://github.com/bigchaindb/cryptoconditions/issues/27
            return public_key.verify(block_serialized, self.signature)
        except (ValueError, AttributeError):
            return False
Exemplo n.º 14
0
    def from_dict(cls, block_body):
        """Transform a Python dictionary to a Block object.

        Args:
            block_body (dict): A block dictionary to be transformed.

        Returns:
            :class:`~Block`

        Raises:
            InvalidHash: If the block's id is not corresponding to its
                data.
            InvalidSignature: If the block's signature is not corresponding
                to it's data or `node_pubkey`.
        """
        # TODO: Reuse `is_signature_valid` method here.
        block = block_body['block']
        block_serialized = serialize(block)
        block_id = hash_data(block_serialized)
        public_key = PublicKey(block['node_pubkey'])

        try:
            signature = block_body['signature']
        except KeyError:
            signature = None

        if block_id != block_body['id']:
            raise InvalidHash()

        if signature is not None:
            # NOTE: CC throws a `ValueError` on some wrong signatures
            #       https://github.com/bigchaindb/cryptoconditions/issues/27
            try:
                signature_valid = public_key\
                        .verify(block_serialized.encode(), signature)
            except ValueError:
                signature_valid = False
            if signature_valid is False:
                raise InvalidSignature('Invalid block signature')

        transactions = [
            Transaction.from_dict(tx) for tx in block['transactions']
        ]

        return cls(transactions, block['node_pubkey'], block['timestamp'],
                   block['voters'], signature)
def test_vote_creation_invalid(b):
    from bigchaindb.common import crypto
    from bigchaindb.common.utils import serialize

    # create valid block
    block = dummy_block(b)
    # retrieve vote
    vote = b.vote(block.id, DUMMY_SHA3, False)

    # assert vote is correct
    assert vote['vote']['voting_for_block'] == block.id
    assert vote['vote']['previous_block'] == DUMMY_SHA3
    assert vote['vote']['is_block_valid'] is False
    assert vote['vote']['invalid_reason'] is None
    assert vote['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(
        serialize(vote['vote']).encode(), vote['signature']) is True
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
                                               user2_output, user_priv):
    from bigchaindb.common.transaction import Transaction
    from bigchaindb.common.utils import serialize
    from .utils import validate_transaction_model

    expected = {
        'outputs': [user2_output.to_dict()],
        'metadata':
        None,
        'asset': {
            'id': tx.id,
        },
        'inputs': [{
            'owners_before': [user_pub],
            'fulfillment': None,
            'fulfills': {
                'transaction_id': tx.id,
                'output_index': 0
            }
        }],
        'operation':
        'TRANSFER',
        'version':
        Transaction.VERSION
    }
    inputs = tx.to_inputs([0])
    transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)],
                                       asset_id=tx.id)
    transfer_tx = transfer_tx.sign([user_priv])
    transfer_tx = transfer_tx.to_dict()

    expected_input = deepcopy(inputs[0])
    expected['id'] = transfer_tx['id']
    expected_input.fulfillment.sign(
        serialize(expected).encode(), b58decode(user_priv))
    expected_ffill = expected_input.fulfillment.serialize_uri()
    transfer_ffill = transfer_tx['inputs'][0]['fulfillment']

    assert transfer_ffill == expected_ffill

    transfer_tx = Transaction.from_dict(transfer_tx)
    assert transfer_tx.inputs_valid([tx.outputs[0]]) is True

    validate_transaction_model(transfer_tx)
def test_valid_block_voting_with_create_transaction(b, genesis_block,
                                                    monkeypatch):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.models import Transaction
    from bigchaindb.pipelines import vote

    # create a `CREATE` transaction
    test_user_priv, test_user_pub = crypto.generate_key_pair()
    tx = Transaction.create([b.me], [([test_user_pub], 1)])
    tx = tx.sign([b.me_private])

    monkeypatch.setattr('time.time', lambda: 1111111111)
    block = b.create_block([tx])
    block_dict = decouple_assets(b, block)

    inpipe = Pipe()
    outpipe = Pipe()

    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    inpipe.put(block_dict)
    vote_pipeline.start()
    vote_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block.id,
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block.id,
        'previous_block': genesis_block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
def test_invalid_content_in_tx_in_block_voting(monkeypatch, b, user_pk,
                                               genesis_block):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.models import Transaction
    from bigchaindb.pipelines import vote

    inpipe = Pipe()
    outpipe = Pipe()

    monkeypatch.setattr('time.time', lambda: 1111111111)
    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    # NOTE: `tx` is invalid, because its content is not corresponding to its id
    tx = Transaction.create([b.me], [([b.me], 1)])
    tx = tx.sign([b.me_private])
    block = b.create_block([tx]).to_dict()
    block['block']['transactions'][0]['id'] = 'an invalid tx id'

    inpipe.put(block)
    vote_pipeline.start()
    vote_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block['id'],
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block['id'],
        'previous_block': genesis_block.id,
        'is_block_valid': False,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
Exemplo n.º 19
0
    def test_get_last_voted_block_cyclic_blockchain(self, b, monkeypatch, alice):
        from bigchaindb.common.crypto import PrivateKey
        from bigchaindb.common.exceptions import CyclicBlockchainError
        from bigchaindb.common.utils import serialize
        from bigchaindb.models import Transaction

        tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
        tx = tx.sign([alice.private_key])
        monkeypatch.setattr('time.time', lambda: 1)
        block1 = b.create_block([tx])
        b.write_block(block1)

        # Manipulate vote to create a cyclic Blockchain
        vote = b.vote(block1.id, b.get_last_voted_block().id, True)
        vote['vote']['previous_block'] = block1.id
        vote_data = serialize(vote['vote'])
        vote['signature'] = PrivateKey(alice.private_key).sign(vote_data.encode())
        b.write_vote(vote)

        with pytest.raises(CyclicBlockchainError):
            b.get_last_voted_block()
Exemplo n.º 20
0
def verify_vote_signature(voters, signed_vote):
    """Verify the signature of a vote

    A valid vote should have been signed by a voter's private key.

    Args:
        voters (list): voters of the block that is under election
        signed_vote (dict): a vote with the `signature` included.

    Returns:
        bool: True if the signature is correct, False otherwise.
    """

    signature = signed_vote['signature']
    pk_base58 = signed_vote['node_pubkey']

    # immediately return False if the voter is not in the block voter list
    if pk_base58 not in voters:
        return False

    public_key = crypto.PublicKey(pk_base58)
    return public_key.verify(serialize(signed_vote['vote']).encode(), signature)
def test_valid_block_voting_multiprocessing(b, genesis_block, monkeypatch):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.pipelines import vote

    inpipe = Pipe()
    outpipe = Pipe()

    monkeypatch.setattr('time.time', lambda: 1111111111)
    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    block = dummy_block(b)
    block_dict = decouple_assets(b, block)

    inpipe.put(block_dict)
    vote_pipeline.start()
    vote_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block.id,
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block.id,
        'previous_block': genesis_block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
Exemplo n.º 22
0
    def test_block_deserialization(self, b, alice):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transaction = Transaction.create([alice.public_key],
                                         [([alice.public_key], 1)])
        transaction.sign([alice.private_key])
        timestamp = gen_timestamp()
        expected = Block([transaction], alice.public_key, timestamp)

        block = {
            'timestamp': timestamp,
            'transactions': [transaction.to_dict()],
            'node_pubkey': alice.public_key,
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': None,
        }

        assert expected == Block.from_dict(block_body)
Exemplo n.º 23
0
    def test_block_invalid_signature(self, b):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.exceptions import InvalidSignature
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transactions = [Transaction.create([b.me], [([b.me], 1)])]
        timestamp = gen_timestamp()

        block = {
            'timestamp': timestamp,
            'transactions': [tx.to_dict() for tx in transactions],
            'node_pubkey': b.me,
            'voters': list(b.federation),
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': 'an invalid signature',
        }

        with raises(InvalidSignature):
            Block.from_dict(block_body).validate(b)
def test_invalid_block_voting(monkeypatch, b, user_pk, genesis_block):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.pipelines import vote

    inpipe = Pipe()
    outpipe = Pipe()

    monkeypatch.setattr('time.time', lambda: 1111111111)
    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    block = dummy_block(b).to_dict()
    block['block']['id'] = 'this-is-not-a-valid-hash'

    inpipe.put(block)
    vote_pipeline.start()
    vote_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block['id'],
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block['id'],
        'previous_block': genesis_block.id,
        'is_block_valid': False,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
Exemplo n.º 25
0
 def _to_str(value):
     return serialize(value)
def test_valid_block_voting_with_transfer_transactions(monkeypatch, b,
                                                       genesis_block):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.models import Transaction
    from bigchaindb.pipelines import vote

    # create a `CREATE` transaction
    test_user_priv, test_user_pub = crypto.generate_key_pair()
    tx = Transaction.create([b.me], [([test_user_pub], 1)])
    tx = tx.sign([b.me_private])

    monkeypatch.setattr('time.time', lambda: 1000000000)
    block = b.create_block([tx])
    b.write_block(block)

    # create a `TRANSFER` transaction
    test_user2_priv, test_user2_pub = crypto.generate_key_pair()
    tx2 = Transaction.transfer(tx.to_inputs(), [([test_user2_pub], 1)],
                               asset_id=tx.id)
    tx2 = tx2.sign([test_user_priv])

    monkeypatch.setattr('time.time', lambda: 2000000000)
    block2 = b.create_block([tx2])
    b.write_block(block2)

    inpipe = Pipe()
    outpipe = Pipe()

    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    vote_pipeline.start()
    inpipe.put(block.to_dict())
    time.sleep(1)
    inpipe.put(block2.to_dict())
    vote_out = outpipe.get()
    vote2_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block.id,
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block.id,
        'previous_block': genesis_block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '2000000000'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True

    vote2_rs = query.get_votes_by_block_id_and_voter(b.connection, block2.id,
                                                     b.me)
    vote2_doc = vote2_rs.next()
    assert vote2_out['vote'] == vote2_doc['vote']
    assert vote2_doc['vote'] == {
        'voting_for_block': block2.id,
        'previous_block': block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '2000000000'
    }

    serialized_vote2 = utils.serialize(vote2_doc['vote']).encode()
    assert vote2_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote2,
                                         vote2_doc['signature']) is True
Exemplo n.º 27
0
 def to_str(self):
     return serialize(self.to_dict())
Exemplo n.º 28
0
def write_block(connection, block_dict):
    return connection.run(
            r.table('bigchain')
            .insert(r.json(serialize(block_dict)), durability=WRITE_DURABILITY))