Merge remote-tracking branch 'origin/master' into update-changelog-for-0.7.0
@ -19,14 +19,9 @@ def start_rethinkdb():
|
||||
"""Start RethinkDB as a child process and wait for it to be
|
||||
available.
|
||||
|
||||
Args:
|
||||
wait_for_db (bool): wait for the database to be ready
|
||||
extra_opts (list): a list of extra options to be used when
|
||||
starting the db
|
||||
|
||||
Raises:
|
||||
``bigchaindb.common.exceptions.StartupError`` if RethinkDB cannot
|
||||
be started.
|
||||
:class:`~bigchaindb.common.exceptions.StartupError` if
|
||||
RethinkDB cannot be started.
|
||||
"""
|
||||
|
||||
proc = subprocess.Popen(['rethinkdb', '--bind', 'all'],
|
||||
|
0
bigchaindb/common/__init__.py
Normal file
@ -198,10 +198,10 @@ class Bigchain(object):
|
||||
the return value is then a tuple: (tx, status)
|
||||
|
||||
Returns:
|
||||
A dict with the transaction details if the transaction was found.
|
||||
Will add the transaction status to payload ('valid', 'undecided',
|
||||
or 'backlog'). If no transaction with that `txid` was found it
|
||||
returns `None`
|
||||
A :class:`~.models.Transaction` instance if the transaction
|
||||
was found, otherwise ``None``.
|
||||
If :attr:`include_status` is ``True``, also returns the
|
||||
transaction's status if the transaction was found.
|
||||
"""
|
||||
|
||||
response, tx_status = None, None
|
||||
@ -412,14 +412,14 @@ class Bigchain(object):
|
||||
return None
|
||||
|
||||
def get_owned_ids(self, owner):
|
||||
"""Retrieve a list of `txids` that can we used has inputs.
|
||||
"""Retrieve a list of `txid`s that can be used as inputs.
|
||||
|
||||
Args:
|
||||
owner (str): base58 encoded public key.
|
||||
|
||||
Returns:
|
||||
list (TransactionLink): list of `txid`s and `cid`s pointing to
|
||||
another transaction's condition
|
||||
:obj:`list` of TransactionLink: list of `txid`s and `cid`s
|
||||
pointing to another transaction's condition
|
||||
"""
|
||||
|
||||
# get all transactions in which owner is in the `owners_after` list
|
||||
@ -587,11 +587,11 @@ class Bigchain(object):
|
||||
return block
|
||||
|
||||
def vote(self, block_id, previous_block_id, decision, invalid_reason=None):
|
||||
"""Cast your vote on the block given the previous_block_hash and the decision (valid/invalid)
|
||||
return the block to the updated in the database.
|
||||
"""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.
|
||||
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
|
||||
|
@ -26,8 +26,8 @@ class StaleTransactionMonitor:
|
||||
Args:
|
||||
timeout: how often to check for stale tx (in sec)
|
||||
backlog_reassign_delay: How stale a transaction should
|
||||
be before reassignment (in sec). If supplied, overrides the
|
||||
Bigchain default value.
|
||||
be before reassignment (in sec). If supplied, overrides
|
||||
the Bigchain default value.
|
||||
"""
|
||||
self.bigchain = Bigchain(backlog_reassign_delay=backlog_reassign_delay)
|
||||
self.timeout = timeout
|
||||
|
@ -13,16 +13,16 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ChangeFeed(Node):
|
||||
"""This class wraps a RethinkDB changefeed adding a `prefeed`.
|
||||
"""This class wraps a RethinkDB changefeed adding a ``prefeed``.
|
||||
|
||||
It extends the ``multipipes::Node`` class to make it pluggable in
|
||||
other Pipelines instances, and it makes usage of ``self.outqueue``
|
||||
to output the data.
|
||||
It extends :class:`multipipes.Node` to make it pluggable in other
|
||||
Pipelines instances, and makes usage of ``self.outqueue`` to output
|
||||
the data.
|
||||
|
||||
A changefeed is a real time feed on inserts, updates, and deletes, and
|
||||
it's volatile. This class is a helper to create changefeeds. Moreover
|
||||
it provides a way to specify a `prefeed`, that is a set of data (iterable)
|
||||
to output before the actual changefeed.
|
||||
is volatile. This class is a helper to create changefeeds. Moreover,
|
||||
it provides a way to specify a ``prefeed`` of iterable data to output
|
||||
before the actual changefeed.
|
||||
"""
|
||||
|
||||
INSERT = 1
|
||||
@ -35,8 +35,8 @@ class ChangeFeed(Node):
|
||||
Args:
|
||||
table (str): name of the table to listen to for changes.
|
||||
operation (int): can be ChangeFeed.INSERT, ChangeFeed.DELETE, or
|
||||
ChangeFeed.UPDATE. Combining multiple operation is possible using
|
||||
the bitwise ``|`` operator
|
||||
ChangeFeed.UPDATE. Combining multiple operation is possible
|
||||
with the bitwise ``|`` operator
|
||||
(e.g. ``ChangeFeed.INSERT | ChangeFeed.UPDATE``)
|
||||
prefeed (iterable): whatever set of data you want to be published
|
||||
first.
|
||||
|
@ -119,7 +119,7 @@ def condition_details_has_owner(condition_details, owner):
|
||||
def verify_vote_signature(voters, signed_vote):
|
||||
"""Verify the signature of a vote
|
||||
|
||||
A valid vote should have been signed `owner_before` corresponding private key.
|
||||
A valid vote should have been signed by a voter's private key.
|
||||
|
||||
Args:
|
||||
voters (list): voters of the block that is under election
|
||||
|
@ -1,2 +1,2 @@
|
||||
__version__ = '0.6.0'
|
||||
__short_version__ = '0.6'
|
||||
__version__ = '0.7.0.dev'
|
||||
__short_version__ = '0.7.dev'
|
||||
|
@ -10,12 +10,14 @@
|
||||
|
||||
# How to Generate the HTML Version of the Long-Form Documentation
|
||||
|
||||
If you want to generate the HTML version of the long-form documentation on your local machine, you need to have Sphinx and some Sphinx-contrib packages installed. To do that, go to the BigchainDB `docs` directory (i.e. this directory) and do:
|
||||
If you want to generate the HTML version of the long-form documentation on your local machine, you need to have Sphinx and some Sphinx-contrib packages installed. To do that, go to a subdirectory of `docs` (e.g. `docs/server`) and do:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
You can then generate the HTML documentation by doing:
|
||||
|
||||
You can then generate the HTML documentation _in that subdirectory_ by doing:
|
||||
```bash
|
||||
make html
|
||||
```
|
||||
The generated HTML documentation will be in the `docs/build/html` directory. You can view it by opening `docs/build/html/index.html` in your web browser.
|
||||
|
||||
It should tell you where the generated documentation (HTML files) can be found. You can view it in your web browser.
|
||||
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# BigchainDB documentation build configuration file, created by
|
||||
# BigchainDB Server documentation build configuration file, created by
|
||||
# sphinx-quickstart on Tue Jan 19 14:42:58 2016.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
@ -32,7 +32,7 @@ import sphinx_rtd_theme
|
||||
|
||||
# get version
|
||||
_version = {}
|
||||
with open('../../bigchaindb/version.py') as fp:
|
||||
with open('../../../bigchaindb/version.py') as fp:
|
||||
exec(fp.read(), _version)
|
||||
|
||||
|
263
docs/server/source/drivers-clients/http-client-server-api.rst
Normal file
@ -0,0 +1,263 @@
|
||||
The HTTP Client-Server API
|
||||
==========================
|
||||
|
||||
.. note::
|
||||
|
||||
The HTTP client-server API is currently quite rudimentary. For example, there is no ability to do complex queries using the HTTP API. We plan to add querying capabilities in the future.
|
||||
|
||||
When you start Bigchaindb using `bigchaindb start`, an HTTP API is exposed at the address stored in the BigchainDB node configuration settings. The default is:
|
||||
|
||||
`http://localhost:9984/api/v1/ <http://localhost:9984/api/v1/>`_
|
||||
|
||||
but that address can be changed by changing the "API endpoint" configuration setting (e.g. in a local config file). There's more information about setting the API endpoint in :doc:`the section about BigchainDB Configuration Settings <../server-reference/configuration>`.
|
||||
|
||||
There are other configuration settings related to the web server (serving the HTTP API). In particular, the default is for the web server socket to bind to ``localhost:9984`` but that can be changed (e.g. to ``0.0.0.0:9984``). For more details, see the "server" settings ("bind", "workers" and "threads") in :doc:`the section about BigchainDB Configuration Settings <../server-reference/configuration>`.
|
||||
|
||||
|
||||
API Root
|
||||
--------
|
||||
|
||||
If you send an HTTP GET request to e.g. ``http://localhost:9984`` (with no ``/api/v1/`` on the end), then you should get an HTTP response with something like the following in the body:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"api_endpoint": "http://localhost:9984/api/v1",
|
||||
"keyring": [
|
||||
"6qHyZew94NMmUTYyHnkZsB8cxJYuRNEiEpXHe1ih9QX3",
|
||||
"AdDuyrTyjrDt935YnFu4VBCVDhHtY2Y6rcy7x2TFeiRi"
|
||||
],
|
||||
"public_key": "AiygKSRhZWTxxYT4AfgKoTG4TZAoPsWoEt6C6bLq4jJR",
|
||||
"software": "BigchainDB",
|
||||
"version": "0.6.0"
|
||||
}
|
||||
|
||||
|
||||
POST /transactions/
|
||||
-------------------
|
||||
|
||||
.. http:post:: /transactions/
|
||||
|
||||
Push a new transaction.
|
||||
|
||||
Note: The posted transaction should be valid `transaction <https://bigchaindb.readthedocs.io/en/latest/data-models/transaction-model.html>`_. The steps to build a valid transaction are beyond the scope of this page. One would normally use a driver such as the `BigchainDB Python Driver <https://docs.bigchaindb.com/projects/py-driver/en/latest/index.html>`_ to build a valid transaction.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /transactions/ HTTP/1.1
|
||||
Host: example.com
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"transaction": {
|
||||
"conditions": [
|
||||
{
|
||||
"cid": 0,
|
||||
"condition": {
|
||||
"uri": "cc:4:20:GG-pi3CeIlySZhQoJVBh9O23PzrOuhnYI7OHqIbHjkk:96",
|
||||
"details": {
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4,
|
||||
"bitmask": 32,
|
||||
"public_key": "2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
}
|
||||
},
|
||||
"amount": 1,
|
||||
"owners_after": [
|
||||
"2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
]
|
||||
}
|
||||
],
|
||||
"operation": "CREATE",
|
||||
"asset": {
|
||||
"divisible": false,
|
||||
"updatable": false,
|
||||
"data": null,
|
||||
"id": "aebeab22-e672-4d3b-a187-bde5fda6533d",
|
||||
"refillable": false
|
||||
},
|
||||
"metadata": null,
|
||||
"timestamp": "1477578978",
|
||||
"fulfillments": [
|
||||
{
|
||||
"fid": 0,
|
||||
"input": null,
|
||||
"fulfillment": "cf:4:GG-pi3CeIlySZhQoJVBh9O23PzrOuhnYI7OHqIbHjkn2VnQaEWvecO1x82Qr2Va_JjFywLKIOEV1Ob9Ofkeln2K89ny2mB-s7RLNvYAVzWNiQnp18_nQEUsvwACEXTYJ",
|
||||
"owners_before": [
|
||||
"2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": "2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e",
|
||||
"version": 1
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": "2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e",
|
||||
"version": 1,
|
||||
"transaction": {
|
||||
"conditions": [
|
||||
{
|
||||
"amount": 1,
|
||||
"condition": {
|
||||
"uri": "cc:4:20:GG-pi3CeIlySZhQoJVBh9O23PzrOuhnYI7OHqIbHjkk:96",
|
||||
"details": {
|
||||
"signature": null,
|
||||
"type_id": 4,
|
||||
"type": "fulfillment",
|
||||
"bitmask": 32,
|
||||
"public_key": "2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
}
|
||||
},
|
||||
"owners_after": [
|
||||
"2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
],
|
||||
"cid": 0
|
||||
}
|
||||
],
|
||||
"fulfillments": [
|
||||
{
|
||||
"input": null,
|
||||
"fulfillment": "cf:4:GG-pi3CeIlySZhQoJVBh9O23PzrOuhnYI7OHqIbHjkn2VnQaEWvecO1x82Qr2Va_JjFywLKIOEV1Ob9Ofkeln2K89ny2mB-s7RLNvYAVzWNiQnp18_nQEUsvwACEXTYJ",
|
||||
"fid": 0,
|
||||
"owners_before": [
|
||||
"2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
]
|
||||
}
|
||||
],
|
||||
"operation": "CREATE",
|
||||
"timestamp": "1477578978",
|
||||
"asset": {
|
||||
"updatable": false,
|
||||
"refillable": false,
|
||||
"divisible": false,
|
||||
"data": null,
|
||||
"id": "aebeab22-e672-4d3b-a187-bde5fda6533d"
|
||||
},
|
||||
"metadata": null
|
||||
}
|
||||
}
|
||||
|
||||
:statuscode 201: A new transaction was created.
|
||||
:statuscode 400: The transaction was invalid and not created.
|
||||
|
||||
|
||||
GET /transactions/{tx_id}/status
|
||||
--------------------------------
|
||||
|
||||
.. http:get:: /transactions/{tx_id}/status
|
||||
|
||||
Get the status of the transaction with the ID ``tx_id``, if a transaction with that ``tx_id`` exists.
|
||||
|
||||
The possible status values are ``backlog``, ``undecided``, ``valid`` or ``invalid``.
|
||||
|
||||
:param tx_id: transaction ID
|
||||
:type tx_id: hex string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /transactions/7ad5a4b83bc8c70c4fd7420ff3c60693ab8e6d0e3124378ca69ed5acd2578792/status HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "valid"
|
||||
}
|
||||
|
||||
:statuscode 200: A transaction with that ID was found and the status is returned.
|
||||
:statuscode 404: A transaction with that ID was not found.
|
||||
|
||||
|
||||
GET /transactions/{tx_id}
|
||||
-------------------------
|
||||
|
||||
.. http:get:: /transactions/{tx_id}
|
||||
|
||||
Get the transaction with the ID ``tx_id``.
|
||||
|
||||
This endpoint returns only a transaction from a ``VALID`` or ``UNDECIDED`` block on ``bigchain``, if exists.
|
||||
|
||||
:param tx_id: transaction ID
|
||||
:type tx_id: hex string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /transactions/2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"transaction": {
|
||||
"conditions": [
|
||||
{
|
||||
"cid": 0,
|
||||
"condition": {
|
||||
"uri": "cc:4:20:GG-pi3CeIlySZhQoJVBh9O23PzrOuhnYI7OHqIbHjkk:96",
|
||||
"details": {
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4,
|
||||
"bitmask": 32,
|
||||
"public_key": "2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
}
|
||||
},
|
||||
"amount": 1,
|
||||
"owners_after": [
|
||||
"2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
]
|
||||
}
|
||||
],
|
||||
"operation": "CREATE",
|
||||
"asset": {
|
||||
"divisible": false,
|
||||
"updatable": false,
|
||||
"data": null,
|
||||
"id": "aebeab22-e672-4d3b-a187-bde5fda6533d",
|
||||
"refillable": false
|
||||
},
|
||||
"metadata": null,
|
||||
"timestamp": "1477578978",
|
||||
"fulfillments": [
|
||||
{
|
||||
"fid": 0,
|
||||
"input": null,
|
||||
"fulfillment": "cf:4:GG-pi3CeIlySZhQoJVBh9O23PzrOuhnYI7OHqIbHjkn2VnQaEWvecO1x82Qr2Va_JjFywLKIOEV1Ob9Ofkeln2K89ny2mB-s7RLNvYAVzWNiQnp18_nQEUsvwACEXTYJ",
|
||||
"owners_before": [
|
||||
"2ePYHfV3yS3xTxF9EE3Xjo8zPwq2RmLPFAJGQqQKc3j6"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": "2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e",
|
||||
"version": 1
|
||||
}
|
||||
|
||||
:statuscode 200: A transaction with that ID was found.
|
||||
:statuscode 404: A transaction with that ID was not found.
|
@ -4,7 +4,6 @@ Drivers & Clients
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
python-server-api-examples
|
||||
http-client-server-api
|
||||
python-driver
|
||||
example-apps
|
@ -34,4 +34,4 @@ bigchaindb start
|
||||
|
||||
That's it!
|
||||
|
||||
For now, you can get a good sense of how to work with BigchainDB Server by going through [the examples in the section on the Python Server API](drivers-clients/python-server-api-examples.html).
|
||||
Next Steps: You could build valid transactions and push them to your running BigchainDB Server using the [BigchaindB Python Driver](https://docs.bigchaindb.com/projects/py-driver/en/latest/index.html).
|
6
docs/server/source/topic-guides/models.md
Normal file
@ -0,0 +1,6 @@
|
||||
# The Transaction, Block and Vote Models
|
||||
|
||||
This page about transaction concepts and data models was getting too big, so it was split into smaller pages. It will be deleted eventually, so update your links. Here's where you can find the new pages:
|
||||
|
||||
* [Transaction Concepts](https://docs.bigchaindb.com/en/latest/transaction-concepts.html)
|
||||
* [Data Models (all of them)](https://docs.bigchaindb.com/en/latest/data-models/index.html)
|
@ -1,272 +0,0 @@
|
||||
The HTTP Client-Server API
|
||||
==========================
|
||||
|
||||
Note: The HTTP client-server API is currently quite rudimentary. For example, there is no ability to do complex queries using the HTTP API. We plan to add querying capabilities in the future.
|
||||
|
||||
When you start Bigchaindb using `bigchaindb start`, an HTTP API is exposed at the address stored in the BigchainDB node configuration settings. The default is:
|
||||
|
||||
`http://localhost:9984/api/v1/ <http://localhost:9984/api/v1/>`_
|
||||
|
||||
but that address can be changed by changing the "API endpoint" configuration setting (e.g. in a local config file). There's more information about setting the API endpoint in :doc:`the section about BigchainDB Configuration Settings <../server-reference/configuration>`.
|
||||
|
||||
There are other configuration settings related to the web server (serving the HTTP API). In particular, the default is for the web server socket to bind to ``localhost:9984`` but that can be changed (e.g. to ``0.0.0.0:9984``). For more details, see the "server" settings ("bind", "workers" and "threads") in :doc:`the section about BigchainDB Configuration Settings <../server-reference/configuration>`.
|
||||
|
||||
If you send an HTTP GET request to e.g. ``http://localhost:9984`` (with no ``/api/v1/`` on the end), then you should get an HTTP response with something like the following in the body:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"api_endpoint": "http://localhost:9984/api/v1",
|
||||
"keyring": [
|
||||
"6qHyZew94NMmUTYyHnkZsB8cxJYuRNEiEpXHe1ih9QX3",
|
||||
"AdDuyrTyjrDt935YnFu4VBCVDhHtY2Y6rcy7x2TFeiRi"
|
||||
],
|
||||
"public_key": "AiygKSRhZWTxxYT4AfgKoTG4TZAoPsWoEt6C6bLq4jJR",
|
||||
"software": "BigchainDB",
|
||||
"version": "0.6.0"
|
||||
}
|
||||
|
||||
|
||||
HTTP API Endpoints
|
||||
------------------
|
||||
|
||||
.. http:get:: /transactions/{tx_id}
|
||||
|
||||
Get the transaction with the ID ``tx_id``.
|
||||
|
||||
This endpoint returns only a transaction from a ``VALID`` or ``UNDECIDED`` block on ``bigchain``, if exists.
|
||||
|
||||
:param tx_id: transaction ID
|
||||
:type tx_id: hex string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /transactions/7ad5a4b83bc8c70c4fd7420ff3c60693ab8e6d0e3124378ca69ed5acd2578792 HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id":"7ad5a4b83bc8c70c4fd7420ff3c60693ab8e6d0e3124378ca69ed5acd2578792",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":32,
|
||||
"public_key":"CwA8s2QYQBfNz4WvjEwmJi83zYr7JhxRhidx6uZ5KBVd",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4
|
||||
},
|
||||
"uri":"cc:4:20:sVA_3p8gvl8yRFNTomqm6MaavKewka6dGYcFAuPrRXQ:96"
|
||||
},
|
||||
"owners_after":[
|
||||
"CwA8s2QYQBfNz4WvjEwmJi83zYr7JhxRhidx6uZ5KBVd"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data":{
|
||||
"payload":null,
|
||||
"uuid":"a9999d69-6cde-4b80-819d-ed57f6abe257"
|
||||
},
|
||||
"fulfillments":[
|
||||
{
|
||||
"owners_before":[
|
||||
"JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"
|
||||
],
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:__Y_Um6H73iwPe6ejWXEw930SQhqVGjtAHTXilPp0P01vE_Cx6zs3GJVoO1jhPL18C94PIVkLTGMUB2aKC9qsbIb3w8ejpOf0_I3OCuTbPdkd6r2lKMeVftMyMxkeWoM",
|
||||
"input":{
|
||||
"cid":0,
|
||||
"txid":"598ce4e9a29837a1c6fc337ee4a41b61c20ad25d01646754c825b1116abd8761"
|
||||
}
|
||||
}
|
||||
],
|
||||
"operation":"TRANSFER",
|
||||
"timestamp":"1471423869",
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
|
||||
:statuscode 200: A transaction with that ID was found.
|
||||
:statuscode 404: A transaction with that ID was not found.
|
||||
|
||||
|
||||
.. http:get:: /transactions/{tx_id}/status
|
||||
|
||||
Get the status of a transaction with the ID ``tx_id``.
|
||||
|
||||
This endpoint returns the status of a transaction if exists.
|
||||
|
||||
Possible values are ``valid``, ``invalid``, ``undecided`` or ``backlog``.
|
||||
|
||||
:param tx_id: transaction ID
|
||||
:type tx_id: hex string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /transactions/7ad5a4b83bc8c70c4fd7420ff3c60693ab8e6d0e3124378ca69ed5acd2578792/status HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "valid"
|
||||
}
|
||||
|
||||
:statuscode 200: A transaction with that ID was found and the status is returned.
|
||||
:statuscode 404: A transaction with that ID was not found.
|
||||
|
||||
.. http:post:: /transactions/
|
||||
|
||||
Push a new transaction.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /transactions/ HTTP/1.1
|
||||
Host: example.com
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id":"7ad5a4b83bc8c70c4fd7420ff3c60693ab8e6d0e3124378ca69ed5acd2578792",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":32,
|
||||
"public_key":"CwA8s2QYQBfNz4WvjEwmJi83zYr7JhxRhidx6uZ5KBVd",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4
|
||||
},
|
||||
"uri":"cc:4:20:sVA_3p8gvl8yRFNTomqm6MaavKewka6dGYcFAuPrRXQ:96"
|
||||
},
|
||||
"owners_after":[
|
||||
"CwA8s2QYQBfNz4WvjEwmJi83zYr7JhxRhidx6uZ5KBVd"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data":{
|
||||
"payload":null,
|
||||
"uuid":"a9999d69-6cde-4b80-819d-ed57f6abe257"
|
||||
},
|
||||
"fulfillments":[
|
||||
{
|
||||
"owners_before":[
|
||||
"JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"
|
||||
],
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:__Y_Um6H73iwPe6ejWXEw930SQhqVGjtAHTXilPp0P01vE_Cx6zs3GJVoO1jhPL18C94PIVkLTGMUB2aKC9qsbIb3w8ejpOf0_I3OCuTbPdkd6r2lKMeVftMyMxkeWoM",
|
||||
"input":{
|
||||
"cid":0,
|
||||
"txid":"598ce4e9a29837a1c6fc337ee4a41b61c20ad25d01646754c825b1116abd8761"
|
||||
}
|
||||
}
|
||||
],
|
||||
"operation":"TRANSFER",
|
||||
"timestamp":"1471423869",
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"assignee":"4XYfCbabAWVUCbjTmRTFEu2sc3dFEdkse4r6X498B1s8",
|
||||
"id":"7ad5a4b83bc8c70c4fd7420ff3c60693ab8e6d0e3124378ca69ed5acd2578792",
|
||||
"transaction":{
|
||||
"conditions":[
|
||||
{
|
||||
"cid":0,
|
||||
"condition":{
|
||||
"details":{
|
||||
"bitmask":32,
|
||||
"public_key":"CwA8s2QYQBfNz4WvjEwmJi83zYr7JhxRhidx6uZ5KBVd",
|
||||
"signature":null,
|
||||
"type":"fulfillment",
|
||||
"type_id":4
|
||||
},
|
||||
"uri":"cc:4:20:sVA_3p8gvl8yRFNTomqm6MaavKewka6dGYcFAuPrRXQ:96"
|
||||
},
|
||||
"owners_after":[
|
||||
"CwA8s2QYQBfNz4WvjEwmJi83zYr7JhxRhidx6uZ5KBVd"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data":{
|
||||
"payload":null,
|
||||
"uuid":"a9999d69-6cde-4b80-819d-ed57f6abe257"
|
||||
},
|
||||
"fulfillments":[
|
||||
{
|
||||
"owners_before":[
|
||||
"JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"
|
||||
],
|
||||
"fid":0,
|
||||
"fulfillment":"cf:4:__Y_Um6H73iwPe6ejWXEw930SQhqVGjtAHTXilPp0P01vE_Cx6zs3GJVoO1jhPL18C94PIVkLTGMUB2aKC9qsbIb3w8ejpOf0_I3OCuTbPdkd6r2lKMeVftMyMxkeWoM",
|
||||
"input":{
|
||||
"cid":0,
|
||||
"txid":"598ce4e9a29837a1c6fc337ee4a41b61c20ad25d01646754c825b1116abd8761"
|
||||
}
|
||||
}
|
||||
],
|
||||
"operation":"TRANSFER",
|
||||
"timestamp":"1471423869",
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
|
||||
:statuscode 201: A new transaction was created.
|
||||
:statuscode 400: The transaction was invalid and not created.
|
||||
|
||||
**Disclaimer**
|
||||
|
||||
``CREATE`` transactions are treated differently from ``TRANSFER`` assets.
|
||||
The reason is that a ``CREATE`` transaction needs to be signed by a federation node and not by the client.
|
||||
|
||||
The following python snippet in a client can be used to generate ``CREATE`` transactions before they can be pushed to the API server:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from bigchaindb import util
|
||||
tx = util.create_and_sign_tx(my_privkey, my_pubkey, my_pubkey, None, 'CREATE')
|
||||
|
||||
When POSTing ``tx`` to the API, the ``CREATE`` transaction will be signed by a federation node.
|
||||
|
||||
A ``TRANSFER`` transaction, that takes an existing input transaction to change ownership can be generated in multiple ways:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from bigchaindb import util, Bigchain
|
||||
tx = util.create_and_sign_tx(my_privkey, my_pubkey, other_pubkey, input_tx, 'TRANSFER')
|
||||
# or
|
||||
b = Bigchain()
|
||||
tx_unsigned = b.create_transaction(my_pubkey, other_pubkey, input_tx, 'TRANSFER')
|
||||
tx = b.sign_transaction(tx_unsigned, my_privkey)
|
||||
|
||||
More information on generating transactions can be found in the `Python server API examples <python-server-api-examples.html>`_
|
@ -1,313 +0,0 @@
|
||||
# The Transaction, Block and Vote Models
|
||||
|
||||
BigchainDB stores all its records in JSON documents.
|
||||
|
||||
The three main kinds of records are transactions, blocks and votes.
|
||||
_Transactions_ are used to register, issue, create or transfer things (e.g. assets). Multiple transactions are combined with some other metadata to form _blocks_. Nodes vote on blocks. This section is a reference on the details of transactions, blocks and votes.
|
||||
|
||||
Below we often refer to cryptographic hashes, keys and signatures. The details of those are covered in [the section on cryptography](../appendices/cryptography.html).
|
||||
|
||||
|
||||
## Some Words of Caution
|
||||
|
||||
BigchainDB is still in the early stages of development. The data models described below may change substantially before BigchainDB reaches a production-ready state (i.e. version 1.0 and higher).
|
||||
|
||||
|
||||
## Transaction Concepts
|
||||
|
||||
Transactions are the most basic kind of record stored by BigchainDB. There are two kinds: creation transactions and transfer transactions.
|
||||
|
||||
A _creation transaction_ can be used to register, issue, create or otherwise initiate the history of a single thing (or asset) in BigchainDB. For example, one might register an identity or a creative work. The things are often called "assets" but they might not be literal assets. A creation transaction also establishes the initial owner or owners of the asset. Only a federation node can create a valid creation transaction (but it's usually made based on a message from a client).
|
||||
|
||||
Currently, BigchainDB only supports indivisible assets. You can't split an asset apart into multiple assets, nor can you combine several assets together into one. [Issue #129](https://github.com/bigchaindb/bigchaindb/issues/129) is an enhancement proposal to support divisible assets.
|
||||
|
||||
A _transfer transaction_ can transfer one or more assets to new owners.
|
||||
|
||||
BigchainDB works with the [Interledger Protocol (ILP)](https://interledger.org/), a protocol for transferring assets between different ledgers, blockchains or payment systems.
|
||||
|
||||
The owner(s) of an asset can specifiy conditions (ILP crypto-conditions) which others must fulfill (satisfy) in order to become the new owner(s) of the asset. For example, a crypto-condition might require a signature from the owner, or from m-of-n owners (a threshold condition, e.g. 3-of-4).
|
||||
|
||||
When someone creates a transfer transaction with the goal of changing an asset's owners, they must fulfill the asset's current crypto-conditions (i.e. in a fulfillment), and they must provide new conditions (including the list of new owners).
|
||||
|
||||
Every create transaction contains exactly one fulfillment-condition pair. A transfer transaction can contain multiple fulfillment-condition pairs: one per asset transferred. Every fulfillment in a transfer transaction (input) must correspond to a condition (output) in a previous transaction. The diagram below illustrates some of these concepts: transactions are represented by light grey boxes, fulfillments have a label like `f:0`, and conditions have a label like `c:0`.
|
||||
|
||||

|
||||
|
||||
To determine the current owner(s) of an asset, find the most recent valid transaction involving it, and then look at the list of owners in the _conditions_ (not the fulfillments).
|
||||
|
||||
|
||||
### Transaction Validation
|
||||
|
||||
When a node is asked to check the validity of a transaction, it must do several things; the main things are:
|
||||
|
||||
* schema validation,
|
||||
* double-spending checks (for transfer transactions),
|
||||
* hash validation (i.e. is the calculated transaction hash equal to its id?), and
|
||||
* validation of all fulfillments, including validation of cryptographic signatures if they’re among the conditions.
|
||||
|
||||
The full details of transaction validation can be found in the code for `validate_transaction()` in the `BaseConsensusRules` class of [`consensus.py`](https://github.com/bigchaindb/bigchaindb/blob/master/bigchaindb/consensus.py) (unless other validation rules are being used by a federation, in which case those should be consulted instead).
|
||||
|
||||
|
||||
### Mutable and Immutable Assets
|
||||
|
||||
Assets can be mutable (changeable) or immutable. To change a mutable asset, you must create a valid transfer transaction with a payload specifying how it changed (or will change). The data structure (schema) of the change depends on the asset class. If you're inventing a new asset class, you can make up how to describe changes. For a mutable asset in an existing asset class, you should find out how changes are specified for that asset class. That's not something determined by BigchainDB.
|
||||
|
||||
|
||||
## The Transaction Model
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<hash of transaction, excluding signatures (see explanation)>",
|
||||
"transaction": {
|
||||
"version": "<version number of the transaction model>",
|
||||
"fulfillments": ["<list of fulfillments>"],
|
||||
"conditions": ["<list of conditions>"],
|
||||
"operation": "<string>",
|
||||
"timestamp": "<timestamp from client>",
|
||||
"asset": "<digital asset description (explained in the next section)>",
|
||||
"metadata": {
|
||||
"id": "<uuid>",
|
||||
"data": "<any JSON document>"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here's some explanation of the contents of a transaction:
|
||||
|
||||
- `id`: The hash of everything inside the serialized `transaction` body (i.e. `fulfillments`, `conditions`, `operation`, `timestamp` and `data`; see below), with one wrinkle: for each fulfillment in `fulfillments`, `fulfillment` is set to `null`. The `id` is also the database primary key.
|
||||
- `transaction`:
|
||||
- `version`: Version number of the transaction model, so that software can support different transaction models.
|
||||
- `fulfillments`: List of fulfillments. Each _fulfillment_ contains a pointer to an unspent asset
|
||||
and a _crypto fulfillment_ that satisfies a spending condition set on the unspent asset. A _fulfillment_
|
||||
is usually a signature proving the ownership of the asset.
|
||||
See [Conditions and Fulfillments](#conditions-and-fulfillments) below.
|
||||
- `conditions`: List of conditions. Each _condition_ is a _crypto-condition_ that needs to be fulfilled by a transfer transaction in order to transfer ownership to new owners.
|
||||
See [Conditions and Fulfillments](#conditions-and-fulfillments) below.
|
||||
- `operation`: String representation of the operation being performed (currently either "CREATE" or "TRANSFER"). It determines how the transaction should be validated.
|
||||
- `timestamp`: The Unix time when the transaction was created. It's provided by the client. See [the section on timestamps](timestamps.html).
|
||||
- `asset`: Definition of the digital asset. See next section.
|
||||
- `metadata`:
|
||||
- `id`: UUID version 4 (random) converted to a string of hex digits in standard form.
|
||||
- `data`: Can be any JSON document. It may be empty in the case of a transfer transaction.
|
||||
|
||||
Later, when we get to the models for the block and the vote, we'll see that both include a signature (from the node which created it). You may wonder why transactions don't have signatures... The answer is that they do! They're just hidden inside the `fulfillment` string of each fulfillment. A creation transaction is signed by the node that created it. A transfer transaction is signed by whoever currently controls or owns it.
|
||||
|
||||
What gets signed? For each fulfillment in the transaction, the "fullfillment message" that gets signed includes the `operation`, `timestamp`, `data`, `version`, `id`, corresponding `condition`, and the fulfillment itself, except with its fulfillment string set to `null`. The computed signature goes into creating the `fulfillment` string of the fulfillment.
|
||||
|
||||
One other note: Currently, transactions contain only the public keys of asset-owners (i.e. who own an asset or who owned an asset in the past), inside the conditions and fulfillments. A transaction does _not_ contain the public key of the client (computer) which generated and sent it to a BigchainDB node. In fact, there's no need for a client to _have_ a public/private keypair. In the future, each client may also have a keypair, and it may have to sign each sent transaction (using its private key); see [Issue #347 on GitHub](https://github.com/bigchaindb/bigchaindb/issues/347). In practice, a person might think of their keypair as being both their "ownership-keypair" and their "client-keypair," but there is a difference, just like there's a difference between Joe and Joe's computer.
|
||||
|
||||
|
||||
## The Digital Asset Model
|
||||
To avoid redundant data in transactions the digital asset model is different for `CREATE` and `TRANSFER` transactions.
|
||||
|
||||
The digital asset properties are defined at creation time in a `CREATE` transaction with the following model:
|
||||
```json
|
||||
{
|
||||
"id": "<uuid>",
|
||||
"divisible": "<true | false>",
|
||||
"updatable": "<true | false>",
|
||||
"refillable": "<true | false>",
|
||||
"data": "<json document>"
|
||||
}
|
||||
```
|
||||
|
||||
For `TRANSFER` transactions we only keep the asset id.
|
||||
```json
|
||||
{
|
||||
"id": "<uuid>",
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
- `id`: UUID version 4 (random) converted to a string of hex digits in standard form. Added server side.
|
||||
- `divisible`: Whether the asset is divisible or not. Defaults to false.
|
||||
- `updatable`: Whether the data in the asset can be updated in the future or not. Defaults to false.
|
||||
- `refillable`: Whether the amount of the asset can change after its creation. Defaults to false.
|
||||
- `data`: A user supplied JSON document with custom information about the asset. Defaults to null.
|
||||
- _amount_: The amount of "shares". Only relevant if the asset is marked as divisible. Defaults to 1. The amount is not specified in the asset, but in the conditions (see next section).
|
||||
|
||||
At the time of this writing divisible, updatable, and refillable assets are not yet implemented.
|
||||
See [Issue #487 on Github](https://github.com/bigchaindb/bigchaindb/issues/487)
|
||||
|
||||
|
||||
## Conditions and Fulfillments
|
||||
|
||||
To create a transaction that transfers an asset to new owners, one must fulfill the asset’s current conditions (crypto-conditions). The most basic kinds of conditions are:
|
||||
|
||||
* **A hashlock condition:** One can fulfill a hashlock condition by providing the correct “preimage” (similar to a password or secret phrase)
|
||||
* **A simple signature condition:** One can fulfill a simple signature condition by a providing a valid cryptographic signature (i.e. corresponding to the public key of an owner, usually)
|
||||
* **A timeout condition:** Anyone can fulfill a timeout condition before the condition’s expiry time. After the expiry time, nobody can fulfill the condition. Another way to say this is that a timeout condition’s fulfillment is valid (TRUE) before the expiry time and invalid (FALSE) after the expiry time. Note: at the time of writing, timeout conditions are BigchainDB-specific (i.e. not part of the Interledger specs).
|
||||
|
||||
A more complex condition can be composed by using n of the above conditions as inputs to an m-of-n threshold condition (a logic gate which outputs TRUE iff m or more inputs are TRUE). If there are n inputs to a threshold condition:
|
||||
* 1-of-n is the same as a logical OR of all the inputs
|
||||
* n-of-n is the same as a logical AND of all the inputs
|
||||
|
||||
For example, one could create a condition requiring that m (of n) owners provide signatures before their asset can be transferred to new owners.
|
||||
|
||||
One can also put different weights on the inputs to threshold condition, along with a threshold that the weighted-sum-of-inputs must pass for the output to be TRUE. Weights could be used, for example, to express the number of shares that someone owns in an asset.
|
||||
|
||||
The (single) output of a threshold condition can be used as one of the inputs of other threshold conditions. This means that one can combine threshold conditions to build complex logical expressions, e.g. (x OR y) AND (u OR v).
|
||||
|
||||
Aside: In BigchainDB, the output of an m-of-n threshold condition can be inverted on the way out, so an output that would have been TRUE would get changed to FALSE (and vice versa). This enables the creation of NOT, NOR and NAND gates. At the time of writing, this “inverted threshold condition” is BigchainDB-specific (i.e. not part of the Interledger specs). It should only be used in combination with a timeout condition.
|
||||
|
||||
When one creates a condition, one can calculate its fulfillment length (e.g. 96). The more complex the condition, the larger its fulfillment length will be. A BigchainDB federation can put an upper limit on the allowed fulfillment length, as a way of capping the complexity of conditions (and the computing time required to validate them).
|
||||
|
||||
If someone tries to make a condition where the output of a threshold condition feeds into the input of another “earlier” threshold condition (i.e. in a closed logical circuit), then their computer will take forever to calculate the (infinite) “condition URI”, at least in theory. In practice, their computer will run out of memory or their client software will timeout after a while.
|
||||
|
||||
Aside: In what follows, the list of `owners_after` (in a condition) is always who owned the asset at the time the transaction completed, but before the next transaction started. The list of `owners_before` (in a fulfillment) is always equal to the list of `owners_after` in that asset's previous transaction.
|
||||
|
||||
### Conditions
|
||||
|
||||
#### One New Owner
|
||||
|
||||
If there is only one _new owner_, the condition will be a simple signature condition (i.e. only one signature is required).
|
||||
|
||||
```json
|
||||
{
|
||||
"cid": "<condition index>",
|
||||
"condition": {
|
||||
"details": {
|
||||
"bitmask": "<base16 int>",
|
||||
"public_key": "<new owner public key>",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": "<base16 int>"
|
||||
},
|
||||
"uri": "<string>"
|
||||
},
|
||||
"owners_after": ["<new owner public key>"],
|
||||
"amount": "<int>"
|
||||
}
|
||||
```
|
||||
|
||||
- **Condition header**:
|
||||
- `cid`: Condition index so that we can reference this output as an input to another transaction. It also matches
|
||||
the input `fid`, making this the condition to fulfill in order to spend the asset used as input with `fid`.
|
||||
- `owners_after`: A list containing one item: the public key of the new owner.
|
||||
- `amount`: The amount of shares for a divisible asset to send to the new owners.
|
||||
- **Condition body**:
|
||||
- `bitmask`: A set of bits representing the features required by the condition type.
|
||||
- `public_key`: The new owner's public key.
|
||||
- `type_id`: The fulfillment type ID; see the [ILP spec](https://interledger.org/five-bells-condition/spec.html).
|
||||
- `uri`: Binary representation of the condition using only URL-safe characters.
|
||||
|
||||
#### Multiple New Owners
|
||||
|
||||
If there are multiple _new owners_, they can create a ThresholdCondition requiring a signature from each of them in order
|
||||
to spend the asset. For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"cid": "<condition index>",
|
||||
"condition": {
|
||||
"details": {
|
||||
"bitmask": 41,
|
||||
"subfulfillments": [
|
||||
{
|
||||
"bitmask": 32,
|
||||
"public_key": "<new owner 1 public key>",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4,
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"bitmask": 32,
|
||||
"public_key": "<new owner 2 public key>",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": 4,
|
||||
"weight": 1
|
||||
}
|
||||
],
|
||||
"threshold": 2,
|
||||
"type": "fulfillment",
|
||||
"type_id": 2
|
||||
},
|
||||
"uri": "cc:2:29:ytNK3X6-bZsbF-nCGDTuopUIMi1HCyCkyPewm6oLI3o:206"},
|
||||
"owners_after": [
|
||||
"owner 1 public key>",
|
||||
"owner 2 public key>"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `subfulfillments`: a list of fulfillments
|
||||
- `weight`: integer weight for each subfulfillment's contribution to the threshold
|
||||
- `threshold`: threshold to reach for the subfulfillments to reach a valid fulfillment
|
||||
|
||||
The `weight`s and `threshold` could be adjusted. For example, if the `threshold` was changed to 1 above, then only one of the new owners would have to provide a signature to spend the asset.
|
||||
|
||||
### Fulfillments
|
||||
|
||||
#### One Current Owner
|
||||
|
||||
If there is only one _current owner_, the fulfillment will be a simple signature fulfillment (i.e. containing just one signature).
|
||||
|
||||
```json
|
||||
{
|
||||
"owners_before": ["<public key of the owner before the transaction happened>"],
|
||||
"fid": 0,
|
||||
"fulfillment": "cf:4:RxFzIE679tFBk8zwEgizhmTuciAylvTUwy6EL6ehddHFJOhK5F4IjwQ1xLu2oQK9iyRCZJdfWAefZVjTt3DeG5j2exqxpGliOPYseNkRAWEakqJ_UrCwgnj92dnFRAEE",
|
||||
"input": {
|
||||
"cid": 0,
|
||||
"txid": "11b3e7d893cc5fdfcf1a1706809c7def290a3b10b0bef6525d10b024649c42d3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `fid`: Fulfillment index. It matches a `cid` in the conditions with a new _crypto-condition_ that the new owner
|
||||
needs to fulfill to spend this asset.
|
||||
- `owners_before`: A list of public keys of the owners before the transaction; in this case it has just one public key.
|
||||
- `fulfillment`: A crypto-conditions URI that encodes the cryptographic fulfillments like signatures and others, see [crypto-conditions](https://interledger.org/five-bells-condition/spec.html).
|
||||
- `input`: Pointer to the asset and condition of a previous transaction
|
||||
- `cid`: Condition index
|
||||
- `txid`: Transaction id
|
||||
|
||||
## The Block Model
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<hash of block>",
|
||||
"block": {
|
||||
"timestamp": "<block-creation timestamp>",
|
||||
"transactions": ["<list of transactions>"],
|
||||
"node_pubkey": "<public key of the node creating the block>",
|
||||
"voters": ["<list of federation nodes public keys>"]
|
||||
},
|
||||
"signature": "<signature of block>",
|
||||
}
|
||||
```
|
||||
|
||||
- `id`: The hash of the serialized `block` (i.e. the `timestamp`, `transactions`, `node_pubkey`, and `voters`). This is also a database primary key; that's how we ensure that all blocks are unique.
|
||||
- `block`:
|
||||
- `timestamp`: The Unix time when the block was created. It's provided by the node that created the block. See [the section on timestamps](timestamps.html).
|
||||
- `transactions`: A list of the transactions included in the block.
|
||||
- `node_pubkey`: The public key of the node that create the block.
|
||||
- `voters`: A list of public keys of federation nodes. Since the size of the
|
||||
federation may change over time, this will tell us how many nodes existed
|
||||
in the federation when the block was created, so that at a later point in
|
||||
time we can check that the block received the correct number of votes.
|
||||
- `signature`: Signature of the block by the node that created the block. (To create the signature, the node serializes the block contents and signs that with its private key.)
|
||||
|
||||
## The Vote Model
|
||||
|
||||
Each node must generate a vote for each block, to be appended the `votes` table. A vote has the following structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<RethinkDB-generated ID for the vote>",
|
||||
"node_pubkey": "<the public key of the voting node>",
|
||||
"vote": {
|
||||
"voting_for_block": "<id of the block the node is voting for>",
|
||||
"previous_block": "<id of the block previous to this one>",
|
||||
"is_block_valid": "<true|false>",
|
||||
"invalid_reason": "<None|DOUBLE_SPEND|TRANSACTIONS_HASH_MISMATCH|NODES_PUBKEYS_MISMATCH",
|
||||
"timestamp": "<Unix time when the vote was generated, provided by the voting node>"
|
||||
},
|
||||
"signature": "<signature of vote>",
|
||||
}
|
||||
```
|
||||
|
||||
Note: The `invalid_reason` was not being used as of v0.1.3 and may be dropped in a future version of BigchainDB.
|