Updated docs about blocks and votes

This commit is contained in:
Troy McConaghy 2017-11-14 15:51:36 +01:00
parent c2acefa6f0
commit 31a0bc846b
7 changed files with 232 additions and 47 deletions

View File

@ -28,4 +28,5 @@ Appendices
licenses
install-with-lxd
run-with-vagrant
run-with-ansible
run-with-ansible
vote-yaml

View File

@ -0,0 +1,16 @@
The vote.yaml File
==================
BigchainDB checks all :ref:`votes <The Vote Model>`
(JSON documents) against a formal schema
defined in a JSON Schema file named vote.yaml.
The contents of that file are copied below.
To understand those contents
(i.e. JSON Schema), check out
`"Understanding JSON Schema"
<https://spacetelescope.github.io/understanding-json-schema/index.html>`_
by Michael Droettboom or
`json-schema.org <http://json-schema.org/>`_.
.. literalinclude:: ../../../../bigchaindb/common/schema/vote.yaml
:language: yaml

View File

@ -1,36 +1,90 @@
The Block Model
===============
A block has the following structure:
A block is a JSON object with a particular schema,
as outlined in this page.
A block must contain the following JSON keys
(also called names or fields):
.. code-block:: json
{
"id": "<hash of block>",
"id": "<ID of the block>",
"block": {
"timestamp": "<block-creation timestamp>",
"transactions": ["<list of transactions>"],
"node_pubkey": "<public key of the node creating the block>",
"voters": ["<list of public keys of all nodes in the cluster>"]
"timestamp": "<Block-creation timestamp>",
"transactions": ["<List of transactions>"],
"node_pubkey": "<Public key of the node which created the block>",
"voters": ["<List of public keys of all nodes in the cluster>"]
},
"signature": "<signature of block>"
"signature": "<Signature of inner block object>"
}
- ``id``: The :ref:`hash <Hashes>` of the serialized inner ``block`` (i.e. the ``timestamp``, ``transactions``, ``node_pubkey``, and ``voters``). It's used as a unique index in the database backend (e.g. RethinkDB or MongoDB).
The JSON Keys in a Block
------------------------
- ``block``:
- ``timestamp``: The Unix time when the block was created. It's provided by the node that created the block.
- ``transactions``: A list of the transactions included in the block.
- ``node_pubkey``: The public key of the node that created the block.
- ``voters``: A list of the public keys of all cluster nodes at the time the block was created.
It's the list of nodes which can cast a vote on this block.
This list can change from block to block, as nodes join and leave the cluster.
**id**
- ``signature``: :ref:`Cryptographic signature <Signature Algorithm and Keys>` of the block by the node that created the block (i.e. the node with public key ``node_pubkey``). To generate the signature, the node signs the serialized inner ``block`` (the same thing that was hashed to determine the ``id``) using the private key corresponding to ``node_pubkey``.
The transaction ID and also the SHA3-256 hash
of the inner ``block`` object, loosely speaking.
It's a string.
To compute it, 1) construct an :term:`associative array` ``d`` containing
``block.timestamp``, ``block.transactions``, ``block.node_pubkey``,
``block.voters``, and their values. 2) compute ``id = hash_of_aa(d)``.
There's pseudocode for the ``hash_of_aa()`` function
in the `IPDB Protocol documentation page about cryptographic hashes
<https://the-ipdb-protocol.readthedocs.io/en/latest/crypto-hashes.html#computing-the-hash-of-an-associative-array>`_.
The result (``id``) is a string: the block ID.
An example is ``"b60adf655932bf47ef58c0bfb2dd276d4795b94346b36cbb477e10d7eb02cea8"``
Working with Blocks
-------------------
**block.timestamp**
There's a **Block** class for creating and working with Block objects; look in `/bigchaindb/models.py <https://github.com/bigchaindb/bigchaindb/blob/master/bigchaindb/models.py>`_. (The link is to the latest version on the master branch on GitHub.)
The `Unix time <https://en.wikipedia.org/wiki/Unix_time>`_
when the block was created, according to the node which created it.
It's a string representation of an integer.
An example is ``"1507294217"``.
**block.transactions**
A list of the :ref:`transactions <The Transaction Model>` included in the block.
(Each transaction is a JSON object.)
**block.node_pubkey**
The public key of the node that created the block.
It's a string.
See the `IPDB Protocol documentation page about cryptographic keys & signatures
<https://the-ipdb-protocol.readthedocs.io/en/latest/crypto-keys-and-sigs.html>`_.
**block.voters**
A list of the public keys of all cluster nodes at the time the block was created.
It's a list of strings.
This list can change from block to block, as nodes join and leave the cluster.
**signature**
The cryptographic signature of the inner ``block``
by the node that created the block
(i.e. the node with public key ``node_pubkey``).
To compute that:
#. Construct an :term:`associative array` ``d`` containing the contents
of the inner ``block``
(i.e. ``block.timestamp``, ``block.transactions``, ``block.node_pubkey``,
``block.voters``, and their values).
#. Compute ``signature = sig_of_aa(d, private_key)``,
where ``private_key`` is the node's private key
(i.e. ``node_pubkey`` and ``private_key`` are a key pair). There's pseudocode
for the ``sig_of_aa()`` function
on `the IPDB Protocol documentation page about cryptographic keys and signatures
<https://the-ipdb-protocol.readthedocs.io/en/latest/crypto-keys-and-sigs.html#computing-the-signature-of-an-associative-array>`_.
.. note::
The ``d_bytes`` computed when computing the block ID will be the *same* as the ``d_bytes`` computed when computing the block signature. This can be used to avoid redundant calculations.

View File

@ -1,27 +0,0 @@
# The Vote Model
A vote has the following structure:
```json
{
"node_pubkey": "<The public key of the voting node>",
"vote": {
"voting_for_block": "<ID of the block the node is voting on>",
"previous_block": "<ID of the block previous to the block being voted on>",
"is_block_valid": "<true OR false>",
"invalid_reason": null,
"timestamp": "<Unix time when the vote was generated, provided by the voting node>"
},
"signature": "<Cryptographic signature of vote>"
}
```
**Notes**
* Votes have no ID (or `"id"`), as far as users are concerned. (The backend database uses one internally, but it's of no concern to users and it's never reported to them via BigchainDB APIs.)
* At the time of writing, the value of `"invalid_reason"` was always `null`. In other words, it wasn't being used. It may be used or dropped in a future version of BigchainDB. See [Issue #217](https://github.com/bigchaindb/bigchaindb/issues/217) on GitHub.
* For more information about the vote `"timestamp"`, see [the page about timestamps in BigchainDB](https://docs.bigchaindb.com/en/latest/timestamps.html).
* For more information about how the `"signature"` is calculated, see [the page about cryptography in BigchainDB](../appendices/cryptography.html).

View File

@ -0,0 +1,121 @@
The Vote Model
==============
A vote is a JSON object with a particular schema,
as outlined in this page.
A vote must contain the following JSON keys
(also called names or fields):
.. code-block:: json
{
"node_pubkey": "<The public key of the voting node>",
"vote": {
"voting_for_block": "<ID of the block the node is voting on>",
"previous_block": "<ID of the block previous to the block being voted on>",
"is_block_valid": "<true OR false>",
"invalid_reason": null,
"timestamp": "<Vote-creation timestamp>"
},
"signature": "<Signature of inner vote object>"
}
.. note::
Votes have no ID (or ``"id"``), as far as users are concerned.
The backend database may use one internally,
but it's of no concern to users and it's never reported to them via APIs.
The JSON Keys in a Vote
-----------------------
**node_pubkey**
The public key of the node which cast this vote.
It's a string.
For more information about public keys,
see the `IPDB Protocol documentation page about cryptographic keys and signatures
<https://the-ipdb-protocol.readthedocs.io/en/latest/crypto-keys-and-sigs.html>`_.
**vote.voting_for_block**
The block ID that this vote is for.
It's a string.
For more information about block IDs,
see the page about :ref:`blocks <The Block Model>`.
**vote.previous_block**
The block ID of the block "before" the block that this vote is for,
according to the node which cast this vote.
It's a string.
(It's possible for different nodes to see different block orders.)
For more information about block IDs,
see the page about :ref:`blocks <The Block Model>`.
**vote.is_block_valid**
``true`` if the node which cast this vote considered the block in question to be valid,
and ``false`` otherwise.
Note that it's a *boolean* (i.e. ``true`` or ``false``), not a string.
**vote.invalid_reason**
Always ``null``, that is, it's not being used.
It may be used or dropped in a future version.
See `bigchaindb/bigchaindb issue #217
<https://github.com/bigchaindb/bigchaindb/issues/217>`_ on GitHub.
**vote.timestamp**
The `Unix time <https://en.wikipedia.org/wiki/Unix_time>`_
when the vote was created, according to the node which created it.
It's a string representation of an integer.
**signature**
The cryptographic signature of the inner ``vote``
by the node that created the vote
(i.e. the node with public key ``node_pubkey``).
To compute that:
#. Construct an :term:`associative array` ``d`` containing the contents of the inner ``vote``
(i.e. ``vote.voting_for_block``, ``vote.previous_block``, ``vote.is_block_valid``,
``vote.invalid_reason``, ``vote.timestamp``, and their values).
#. Compute ``signature = sig_of_aa(d, private_key)``, where ``private_key``
is the node's private key (i.e. ``node_pubkey`` and ``private_key`` are a key pair).
There's pseudocode for the ``sig_of_aa()`` function
on `the IPDB Protocol documentation page about cryptographic keys and signatures
<https://the-ipdb-protocol.readthedocs.io/en/latest/crypto-keys-and-sigs.html#computing-the-signature-of-an-associative-array>`_.
The Vote Schema
---------------
BigchainDB checks all votes (JSON documents) against a formal schema
defined in a JSON Schema file named :ref:`vote.yaml <The vote.yaml File>`.
An Example Vote
---------------
.. code-block:: json
{
"node_pubkey": "3ZCsVWPAhPTqHx9wZVxp9Se54pcNeeM5mQvnozDWyDR9",
"vote": {
"voting_for_block": "11c3a3fcc9efa4fc4332a0849fc39b58e403ff37794a7d1fdfb9e7703a94a274",
"previous_block": "3dd1441018b782a50607dc4c7f83a0f0a23eb257f4b6a8d99330dfff41271e0d",
"is_block_valid": true,
"invalid_reason": null,
"timestamp": "1509977988"
},
"signature": "3tW2EBVgxaZTE6nixVd9QEQf1vUxqPmQaNAMdCHc7zHik5KEosdkwScGYt4VhiHDTB6BCxTUzmqu3P7oP93tRWfj"
}

View File

@ -0,0 +1,19 @@
Glossary
========
.. glossary::
:sorted:
associative array
A collection of key/value (or name/value) pairs
such that each possible key appears at most once
in the collection.
In JavaScript (and JSON), all objects behave as associative arrays
with string-valued keys.
In Python and .NET, associative arrays are called *dictionaries*.
In Java and Go, they are called *maps*.
In Ruby, they are called *hashes*.
See also: Wikipedia's articles for
`Associative array <https://en.wikipedia.org/wiki/Associative_array>`_
and
`Comparison of programming languages (associative array) <https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(associative_array)>`_

View File

@ -17,4 +17,5 @@ BigchainDB Server Documentation
drivers-clients/index
data-models/index
release-notes
glossary
appendices/index