mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Merge remote-tracking branch 'origin/master' into kyber-master
This commit is contained in:
commit
f2d72e7deb
23
CHANGELOG.md
23
CHANGELOG.md
@ -15,6 +15,22 @@ For reference, the possible headings are:
|
||||
* **External Contributors** to list contributors outside of BigchainDB GmbH.
|
||||
* **Notes**
|
||||
|
||||
## [1.0.0] - 2017-07-05
|
||||
Tag name: v1.0.0
|
||||
|
||||
**This just reports the changes since the release of 1.0.0rc1. If you want the full picture of all changes since 0.10, then read the 1.0.0rc1 change log below as well as the upgrade guide.**
|
||||
|
||||
### Changed
|
||||
* The file name of the upgrade guide changed from `docs/upgrade-guides/v0.10-->v1.0.md` to `docs/upgrade-guides/v0.10-v1.0.md`.
|
||||
* In `transaction.inputs[n].fulfills`, `output` was renamed to `output_index`. [Pull Request #1596](https://github.com/bigchaindb/bigchaindb/pull/1596)
|
||||
* In `transaction.outputs[n].condition.details`, 1) `signature` was removed (from signature conditions) and 2) `subfulfillments` was renamed to `subconditions` (in threshold conditions). [Pull Request #1589](https://github.com/bigchaindb/bigchaindb/pull/1589)
|
||||
* Refined transaction schema validation to check that the `transaction.outputs[n].condition.uri` corresponds to a condition that BigchainDB Server 1.0.0 actually supports. [Pull Request #1597](https://github.com/bigchaindb/bigchaindb/pull/1597)
|
||||
* Before, GET requests (to the HTTP API) with header `Content-Type: 'application/json'` would get a response with the message, "The browser (or proxy) sent a request that this server could not understand." Now, if a GET request includes a `Content-Type` header, that header gets deleted (i.e. ignored). [Pull Request #1630](https://github.com/bigchaindb/bigchaindb/pull/1630)
|
||||
|
||||
### Fixed
|
||||
* If an end user sends a transaction with `operation` equal to `GENESIS`, it will be rejected as invalid. [Pull Request #1612](https://github.com/bigchaindb/bigchaindb/pull/1612)
|
||||
|
||||
|
||||
## [1.0.0rc1] - 2017-06-23
|
||||
Tag name: v1.0.0rc1
|
||||
|
||||
@ -70,6 +86,13 @@ Tag name: v1.0.0rc1
|
||||
* The [BigchainDB JavaScript driver](https://github.com/bigchaindb/js-bigchaindb-driver) was moved to a different GitHub repo and is now officially maintained by the BigchainDB team.
|
||||
* We continue to recommend using MongoDB.
|
||||
|
||||
## [0.10.3] - 2017-06-29
|
||||
Tag name: v0.10.3
|
||||
|
||||
## Fixed
|
||||
* Pin minor+ version of `cryptoconditions` to avoid upgrading to a non
|
||||
compatible version.
|
||||
[commit 97268a5](https://github.com/bigchaindb/bigchaindb/commit/97268a577bf27942a87d8eb838f4816165c84fd5)
|
||||
|
||||
## [0.10.2] - 2017-05-16
|
||||
Tag name: v0.10.2
|
||||
|
@ -23,7 +23,6 @@ BigchainDB is a scalable blockchain database. [The whitepaper](https://www.bigch
|
||||
* [Roadmap](https://github.com/bigchaindb/org/blob/master/ROADMAP.md)
|
||||
* [Blog](https://medium.com/the-bigchaindb-blog)
|
||||
* [Twitter](https://twitter.com/BigchainDB)
|
||||
* [Google Group](https://groups.google.com/forum/#!forum/bigchaindb)
|
||||
|
||||
## Links for Developers
|
||||
|
||||
|
@ -22,7 +22,7 @@ A minor release is preceeded by a feature freeze and created from the 'master' b
|
||||
1. Commit that change, and push the new branch to GitHub
|
||||
1. On GitHub, use the new branch to create a new pull request and wait for all the tests to pass
|
||||
1. Follow steps outlined in [Common Steps](#common-steps)
|
||||
1. In 'master' branch, Edit `bigchaindb/version.py`, increment the minor version to the next planned release, e.g. `0.10.0.dev`. This is so people reading the latest docs will know that they're for the latest (master branch) version of BigchainDB Server, not the docs at the time of the most recent release (which are also available).
|
||||
1. In 'master' branch, Edit `bigchaindb/version.py`, increment the minor version to the next planned release, e.g. `0.10.0.dev`. (Exception: If you just released `X.Y.Zrc1` then increment the minor version to `X.Y.Zrc2`.) This step is so people reading the latest docs will know that they're for the latest (master branch) version of BigchainDB Server, not the docs at the time of the most recent release (which are also available).
|
||||
1. Go to [Docker Hub](https://hub.docker.com/), sign in, go to Settings - Build Settings, and under the build with Docker Tag Name equal to `latest`, change the Name to the number of the new release, e.g. `0.9`
|
||||
|
||||
Congratulations, you have released BigchainDB!
|
||||
|
@ -19,10 +19,6 @@ class StartupError(BigchainDBError):
|
||||
"""Raised when there is an error starting up the system"""
|
||||
|
||||
|
||||
class GenesisBlockAlreadyExistsError(BigchainDBError):
|
||||
"""Raised when trying to create the already existing genesis block"""
|
||||
|
||||
|
||||
class CyclicBlockchainError(BigchainDBError):
|
||||
"""Raised when there is a cycle in the blockchain"""
|
||||
|
||||
@ -110,3 +106,7 @@ class DuplicateTransaction(ValidationError):
|
||||
|
||||
class ThresholdTooDeep(ValidationError):
|
||||
"""Raised if threshold condition is too deep"""
|
||||
|
||||
|
||||
class GenesisBlockAlreadyExistsError(ValidationError):
|
||||
"""Raised when trying to create the already existing genesis block"""
|
||||
|
@ -153,7 +153,9 @@ definitions:
|
||||
"$ref": "#/definitions/condition_details"
|
||||
uri:
|
||||
type: string
|
||||
pattern: "^ni:///sha-256;([a-zA-Z0-9_-]{0,86})?(.+)$"
|
||||
pattern: "^ni:///sha-256;([a-zA-Z0-9_-]{0,86})[?]\
|
||||
(fpt=(ed25519|threshold)-sha-256(&)?|cost=[0-9]+(&)?|\
|
||||
subtypes=ed25519-sha-256(&)?){2,3}$"
|
||||
public_keys:
|
||||
"$ref": "#/definitions/public_keys"
|
||||
description: |
|
||||
|
@ -1,3 +1,7 @@
|
||||
"""Transaction related models to parse and construct transaction
|
||||
payloads.
|
||||
|
||||
"""
|
||||
from copy import deepcopy
|
||||
from functools import reduce
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
from bigchaindb.utils import output_has_owner
|
||||
from bigchaindb.utils import condition_details_has_owner
|
||||
from bigchaindb.backend import query
|
||||
from bigchaindb.common.transaction import TransactionLink
|
||||
|
||||
@ -52,7 +52,8 @@ class FastQuery:
|
||||
return [TransactionLink(tx['id'], index)
|
||||
for tx in txs
|
||||
for index, output in enumerate(tx['outputs'])
|
||||
if output_has_owner(output, public_key)]
|
||||
if condition_details_has_owner(output['condition']['details'],
|
||||
public_key)]
|
||||
|
||||
def filter_spent_outputs(self, outputs):
|
||||
"""
|
||||
|
@ -13,7 +13,8 @@ import bigchaindb
|
||||
from bigchaindb import backend
|
||||
from bigchaindb.backend.changefeed import ChangeFeed
|
||||
from bigchaindb.models import Transaction
|
||||
from bigchaindb.common.exceptions import ValidationError
|
||||
from bigchaindb.common.exceptions import (ValidationError,
|
||||
GenesisBlockAlreadyExistsError)
|
||||
from bigchaindb import Bigchain
|
||||
|
||||
|
||||
@ -73,6 +74,14 @@ class BlockPipeline:
|
||||
|
||||
# If transaction is not valid it should not be included
|
||||
try:
|
||||
# Do not allow an externally submitted GENESIS transaction.
|
||||
# A simple check is enough as a pipeline is started only after the
|
||||
# creation of GENESIS block, or after the verification of a GENESIS
|
||||
# block. Voting will fail at a later stage if the GENESIS block is
|
||||
# absent.
|
||||
if tx.operation == Transaction.GENESIS:
|
||||
raise GenesisBlockAlreadyExistsError('Duplicate GENESIS transaction')
|
||||
|
||||
tx.validate(self.bigchain)
|
||||
return tx
|
||||
except ValidationError as e:
|
||||
|
@ -113,19 +113,6 @@ def condition_details_has_owner(condition_details, owner):
|
||||
return False
|
||||
|
||||
|
||||
def output_has_owner(output, owner):
|
||||
# TODO
|
||||
# Check whether it is really necessary to treat the single key case
|
||||
# differently from the multiple keys case, and why not just use the same
|
||||
# function for both cases.
|
||||
if len(output['public_keys']) > 1:
|
||||
return condition_details_has_owner(
|
||||
output['condition']['details'], owner)
|
||||
elif len(output['public_keys']) == 1:
|
||||
return output['condition']['details']['public_key'] == owner
|
||||
# TODO raise proper exception, e.g. invalid tx payload?
|
||||
|
||||
|
||||
def is_genesis_block(block):
|
||||
"""Check if the block is the genesis block.
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
__version__ = '1.0.0.dev'
|
||||
__short_version__ = '1.0.dev'
|
||||
__version__ = '1.0.0'
|
||||
__short_version__ = '1.0'
|
||||
|
@ -13,6 +13,7 @@ import gunicorn.app.base
|
||||
from bigchaindb import utils
|
||||
from bigchaindb import Bigchain
|
||||
from bigchaindb.web.routes import add_routes
|
||||
from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware
|
||||
|
||||
|
||||
# TODO: Figure out if we do we need all this boilerplate.
|
||||
@ -60,6 +61,7 @@ def create_app(*, debug=False, threads=1):
|
||||
"""
|
||||
|
||||
app = Flask(__name__)
|
||||
app.wsgi_app = StripContentTypeMiddleware(app.wsgi_app)
|
||||
|
||||
CORS(app)
|
||||
|
||||
|
27
bigchaindb/web/strip_content_type_middleware.py
Normal file
27
bigchaindb/web/strip_content_type_middleware.py
Normal file
@ -0,0 +1,27 @@
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StripContentTypeMiddleware:
|
||||
"""WSGI middleware to strip Content-Type header for GETs."""
|
||||
|
||||
def __init__(self, app):
|
||||
"""Create the new middleware.
|
||||
|
||||
Args:
|
||||
app: a flask application
|
||||
"""
|
||||
self.app = app
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
"""Run the middleware and then call the original WSGI application."""
|
||||
|
||||
if environ['REQUEST_METHOD'] == 'GET':
|
||||
try:
|
||||
del environ['CONTENT_TYPE']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
logger.debug('Remove header "Content-Type" from GET request')
|
||||
return self.app(environ, start_response)
|
@ -28,6 +28,7 @@ services:
|
||||
BIGCHAINDB_DATABASE_HOST: mdb
|
||||
BIGCHAINDB_DATABASE_PORT: 27017
|
||||
BIGCHAINDB_SERVER_BIND: 0.0.0.0:9984
|
||||
BIGCHAINDB_WSSERVER_HOST: 0.0.0.0
|
||||
ports:
|
||||
- "9984"
|
||||
command: bigchaindb start
|
||||
|
@ -1,4 +1,5 @@
|
||||
[Documentation on ReadTheDocs](http://bigchaindb.readthedocs.org/)
|
||||
- [Documentation on ReadTheDocs](http://bigchaindb.readthedocs.org/)
|
||||
- [BigchainDB Upgrade Guides](upgrade-guides/)
|
||||
|
||||
# The BigchainDB Documentation Strategy
|
||||
|
||||
|
@ -21,4 +21,4 @@ We’re actively exploring ways that BigchainDB can be used with other blockchai
|
||||
|
||||
.. note::
|
||||
|
||||
We used the word "owners" somewhat loosely above. A more accurate word might be fulfillers, signers, controllers, or tranfer-enablers. See BigchainDB Server `issue #626 <https://github.com/bigchaindb/bigchaindb/issues/626>`_.
|
||||
We used the word "owners" somewhat loosely above. A more accurate word might be fulfillers, signers, controllers, or transfer-enablers. See BigchainDB Server `issue #626 <https://github.com/bigchaindb/bigchaindb/issues/626>`_.
|
||||
|
@ -7,16 +7,13 @@ BigchainDB will run the subset of smart contracts expressible using "crypto-cond
|
||||
|
||||
The owners of an asset can impose conditions on it that must be met for the asset to be transferred to new owners. Examples of possible conditions (crypto-conditions) include:
|
||||
|
||||
- The current owner must sign the transfer transaction (one which transfers ownership to new owners)
|
||||
- Three out of five current owners must sign the transfer transaction
|
||||
- (Shannon and Kelly) or Morgan must sign the transfer transaction
|
||||
- Anyone who provides the secret password (technically, the preimage of a known hash) can create a valid transfer transaction
|
||||
- The current owner must sign the transfer transaction (one which transfers ownership to new owners).
|
||||
- Three out of five current owners must sign the transfer transaction.
|
||||
- (Shannon and Kelly) or Morgan must sign the transfer transaction.
|
||||
|
||||
Crypto-conditions can be quite complex if-this-then-that type conditions, where the "this" can be a long boolean expression. Crypto-conditions can't include loops or recursion and are therefore will always run/check in finite time.
|
||||
|
||||
BigchainDB also supports a timeout condition which enables it to support a form of escrow.
|
||||
|
||||
.. note::
|
||||
|
||||
We used the word "owners" somewhat loosely above. A more accurate word might be fulfillers, signers, controllers, or tranfer-enablers. See BigchainDB Server `issue #626 <https://github.com/bigchaindb/bigchaindb/issues/626>`_.
|
||||
We used the word "owners" somewhat loosely above. A more accurate word might be fulfillers, signers, controllers, or transfer-enablers. See BigchainDB Server `issue #626 <https://github.com/bigchaindb/bigchaindb/issues/626>`_.
|
||||
|
@ -15,30 +15,57 @@ one might register an identity or a creative work. The things are often called
|
||||
"assets" but they might not be literal assets.
|
||||
|
||||
BigchainDB supports divisible assets as of BigchainDB Server v0.8.0.
|
||||
That means you can create/register an asset with an initial quantity,
|
||||
e.g. 700 oak trees. Divisible assets can be split apart or recombined
|
||||
by transfer transactions (described more below).
|
||||
That means you can create/register an asset with an initial number of "shares."
|
||||
For example, A CREATE transaction could register a truckload of 50 oak trees.
|
||||
Each share of a divisible asset must be interchangeable with each other share;
|
||||
the shares must be fungible.
|
||||
|
||||
A CREATE transaction also establishes, in its outputs, the conditions that must
|
||||
be met to transfer the asset(s). The conditions may also be associated with a
|
||||
list of public keys that, depending on the condition, may have full or partial
|
||||
control over the asset(s). For example, there may be a condition that any
|
||||
transfer must be signed (cryptographically) by the private key associated with a
|
||||
given public key. More sophisticated conditions are possible. BigchainDB's
|
||||
conditions are based on the crypto-conditions of the [Interledger Protocol
|
||||
(ILP)](https://interledger.org/).
|
||||
A CREATE transaction can have one or more outputs.
|
||||
Each output has an associated amount: the number of shares tied to that output.
|
||||
For example, if the asset consists of 50 oak trees,
|
||||
one output might have 35 oak trees for one set of owners,
|
||||
and the other output might have 15 oak trees for another set of owners.
|
||||
|
||||
Each output also has an associated condition: the condition that must be met
|
||||
(by a TRANSFER transaction) to transfer/spend the output.
|
||||
BigchainDB supports a variety of conditions,
|
||||
a subset of the [Interledger Protocol (ILP)](https://interledger.org/)
|
||||
crypto-conditions. For details, see
|
||||
[the documentation about Inputs and Outputs](https://docs.bigchaindb.com/projects/server/en/latest/data-models/inputs-outputs.html).
|
||||
|
||||
Each output also has a list of all the public keys associated
|
||||
with the conditions on that output.
|
||||
Loosely speaking, that list might be interpreted as the list of "owners."
|
||||
A more accurate word might be fulfillers, signers, controllers,
|
||||
or transfer-enablers.
|
||||
See BigchainDB Server [issue #626](https://github.com/bigchaindb/bigchaindb/issues/626).
|
||||
|
||||
A CREATE transaction must be signed by all the owners.
|
||||
(If you're looking for that signature,
|
||||
it's in the one "fulfillment" of the one input, albeit encoded.)
|
||||
|
||||
|
||||
## TRANSFER Transactions
|
||||
|
||||
A TRANSFER transaction can transfer an asset
|
||||
by providing inputs which fulfill the current output conditions on the asset.
|
||||
It must also specify new transfer conditions.
|
||||
A TRANSFER transaction can transfer/spend one or more outputs
|
||||
on other transactions (CREATE transactions or other TRANSFER transactions).
|
||||
Those outputs must all be associated with the same asset;
|
||||
a TRANSFER transaction can only transfer shares of one asset at a time.
|
||||
|
||||
Each input on a TRANSFER transaction connects to one output
|
||||
on another transaction.
|
||||
Each input must satisfy the condition on the output it's trying
|
||||
to transfer/spend.
|
||||
|
||||
A TRANSFER transaction can have one or more outputs,
|
||||
just like a CREATE transaction (described above).
|
||||
The total number of shares coming in on the inputs must equal
|
||||
the total number of shares going out on the outputs.
|
||||
|
||||
**Example 1:** Suppose a red car is owned and controlled by Joe.
|
||||
Suppose the current transfer condition on the car says
|
||||
that any valid transfer must be signed by Joe.
|
||||
Joe and a buyer named Rae could build a TRANSFER transaction containing
|
||||
Joe could build a TRANSFER transaction containing
|
||||
an input with Joe's signature (to fulfill the current output condition)
|
||||
plus a new output condition saying that any valid transfer
|
||||
must be signed by Rae.
|
||||
@ -62,3 +89,11 @@ When a node is asked to check if a transaction is valid, it checks several
|
||||
things. We documented those things in a post on *The BigchainDB Blog*:
|
||||
["What is a Valid Transaction in BigchainDB?"](https://blog.bigchaindb.com/what-is-a-valid-transaction-in-bigchaindb-9a1a075a9598)
|
||||
(Note: That post was about BigchainDB Server v1.0.0.)
|
||||
|
||||
|
||||
## Example Transactions
|
||||
|
||||
There are example BigchainDB transactions in
|
||||
[the HTTP API documentation](https://docs.bigchaindb.com/projects/server/en/latest/http-client-server-api.html)
|
||||
and
|
||||
[the Python Driver documentation](https://docs.bigchaindb.com/projects/py-driver/en/latest/usage.html).
|
||||
|
BIN
docs/server/source/_static/mongodb_cloud_manager_1.png
Normal file
BIN
docs/server/source/_static/mongodb_cloud_manager_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@ -1,153 +1,103 @@
|
||||
Inputs and Outputs
|
||||
==================
|
||||
|
||||
BigchainDB is modelled around *assets*, and *inputs* and *outputs* are the mechanism by which control of an asset is transferred.
|
||||
There's a high-level overview of inputs and outputs
|
||||
in `the root docs page about transaction concepts <https://docs.bigchaindb.com/en/latest/transaction-concepts.html>`_.
|
||||
|
||||
Amounts of an asset are encoded in the outputs of a transaction, and each output may be spent separately. In order to spend an output, the output's ``conditions`` must be met by an ``input`` that provides corresponding ``fulfillments``. Each output may be spent at most once, by a single input. Note that any asset associated with an output holding an amount greater than one is considered a divisible asset that may be split up in future transactions.
|
||||
BigchainDB is modelled around *assets*, and *inputs* and *outputs* are the mechanism by which control of an asset (or shares of an asset) is transferred.
|
||||
Amounts of an asset are encoded in the outputs of a transaction, and each output may be spent separately. To spend an output, the output's ``condition`` must be met by an ``input`` that provides a corresponding ``fulfillment``. Each output may be spent at most once, by a single input. Note that any asset associated with an output holding an amount greater than one is considered a divisible asset that may be split up in future transactions.
|
||||
|
||||
.. note::
|
||||
|
||||
This document (and various places in the BigchainDB documentation and code) talks about control of an asset in terms of *owners* and *ownership*. The language is chosen to represent the most common use cases, but in some more complex scenarios, it may not be accurate to say that the output is owned by the controllers of those public keys–it would only be correct to say that those public keys are associated with the ability to fulfill the output. Also, depending on the use case, the entity controlling an output via a private key may not be the legal owner of the asset in the corresponding legal domain. However, since we aim to use language that is simple to understand and covers the majority of use cases, we talk in terms of *owners* of an output that have the ability to *spend* that output.
|
||||
Inputs
|
||||
------
|
||||
|
||||
In the most basic case, an output may define a **simple signature condition**, which gives control of the output to the entity controlling a corresponding private key.
|
||||
An input has the following structure:
|
||||
|
||||
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 if and only if m or more inputs are TRUE). If there are n inputs to a threshold condition:
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"owners_before": ["<The public_keys list in the output being spent>"],
|
||||
"fulfillment": "<Fulfillment URI fulfilling the condition of the output being spent>",
|
||||
"fulfills": {
|
||||
"output_index": "<Index of the output being spent (an integer)>",
|
||||
"transaction_id": "<ID of the transaction containing the output being spent>"
|
||||
}
|
||||
}
|
||||
|
||||
You can think of the ``fulfills`` object as a pointer to an output on another transaction: the output that this input is spending/transferring.
|
||||
A CREATE transaction should have exactly one input. That input can contain one or more ``owners_before``, a ``fulfillment`` (with one signature from each of the owners-before), and the value of ``fulfills`` should be ``null``). A TRANSFER transaction should have at least one input, and the value of ``fulfills`` should not be ``null``.
|
||||
See the reference on :ref:`inputs <Input>` for more description about the meaning of each field.
|
||||
|
||||
To calculate a fulfillment URI, you can use one of the
|
||||
:ref:`BigchainDB drivers or transaction-builders <Drivers & Tools>`,
|
||||
or use a low-level crypto-conditions library as illustrated
|
||||
in the page about `Handcrafting Transactions <https://docs.bigchaindb.com/projects/py-driver/en/latest/handcraft.html>`_.
|
||||
|
||||
|
||||
Outputs
|
||||
-------
|
||||
|
||||
An output has the following structure:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"condition": {"<Condition object>"},
|
||||
"public_keys": ["<List of all public keys associated with the condition object>"],
|
||||
"amount": "<Number of shares of the asset (an integer in a string)>"
|
||||
}
|
||||
|
||||
The list of ``public_keys`` is always the "owners" of the asset at the time the transaction completed, but before the next transaction started.
|
||||
See the reference on :ref:`outputs <Output>` for more description about the meaning of each field.
|
||||
|
||||
Below is a high-level description of what goes into building a ``condition`` object.
|
||||
To construct an actual ``condition`` object, you can use one of the
|
||||
:ref:`BigchainDB drivers or transaction-builders <Drivers & Tools>`,
|
||||
or use a low-level crypto-conditions library as illustrated
|
||||
in the page about `Handcrafting Transactions <https://docs.bigchaindb.com/projects/py-driver/en/latest/handcraft.html>`_.
|
||||
|
||||
|
||||
Conditions
|
||||
----------
|
||||
|
||||
At a high level, a condition is like a lock on an output.
|
||||
If can you satisfy the condition, you can unlock the output and transfer/spend it.
|
||||
BigchainDB Server v1.0 supports a subset of the ILP Crypto-Conditions
|
||||
(`version 02 of Crypto-Conditions <https://tools.ietf.org/html/draft-thomas-crypto-conditions-02>`_).
|
||||
|
||||
The simplest supported condition is a simple signature condition.
|
||||
Such a condition could be stated as,
|
||||
"You can satisfy this condition
|
||||
if you send me a message and a cryptographic signature of that message,
|
||||
produced using the private key corresponding to this public key."
|
||||
The public key is put in the output.
|
||||
BigchainDB currently only supports ED25519 signatures.
|
||||
|
||||
A more complex condition can be composed by using n simple signature conditions as inputs to an m-of-n threshold condition (a logic gate which outputs TRUE if and only if 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 m (of n) signatures before their asset can be transferred.
|
||||
|
||||
One can also put different weights on the inputs to a threshold condition, along with a threshold that the weighted-sum-of-inputs must pass for the output to be TRUE.
|
||||
|
||||
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).
|
||||
|
||||
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 complexity of the
|
||||
conditions, either directly by setting a maximum allowed fulfillment length,
|
||||
When one creates a condition, one can calculate its
|
||||
`cost <https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-7.2.2>`_,
|
||||
an estimate of the resources that would be required to validate the fulfillment.
|
||||
A BigchainDB federation can put an upper limit on the complexity of each
|
||||
condition, either directly by setting a maximum allowed cost,
|
||||
or
|
||||
`indirectly <https://github.com/bigchaindb/bigchaindb/issues/356#issuecomment-288085251>`_
|
||||
by :ref:`setting a maximum allowed transaction size <Enforcing a Max Transaction Size>`
|
||||
which would limit
|
||||
the overall complexity accross all inputs and outputs of a transaction.
|
||||
Note: At the time of writing, there was no configuration setting
|
||||
to set a maximum allowed fulfillment length,
|
||||
to set a maximum allowed cost,
|
||||
so the only real option was to
|
||||
:ref:`set a maximum allowed transaction size <Enforcing a Max Transaction Size>`.
|
||||
|
||||
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.
|
||||
|
||||
Outputs
|
||||
-------
|
||||
|
||||
.. note::
|
||||
|
||||
In what follows, the list of ``public_keys`` (in a condition) is always the controllers of the asset at the time the transaction completed, but before the next transaction started. The list of ``owners_before`` (in an input) is always equal to the list of ``public_keys`` in that asset's previous transaction.
|
||||
|
||||
One New Owner
|
||||
`````````````
|
||||
|
||||
If there is only one *new owner*, the output will contain a simple signature condition (i.e. only one signature is required).
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"condition": {
|
||||
"details": {
|
||||
"bitmask": "<base16 int>",
|
||||
"public_key": "<new owner public key>",
|
||||
"signature": null,
|
||||
"type": "fulfillment",
|
||||
"type_id": "<base16 int>"
|
||||
},
|
||||
"uri": "<string>"
|
||||
},
|
||||
"public_keys": ["<new owner public key>"],
|
||||
"amount": "<int>"
|
||||
}
|
||||
|
||||
|
||||
See the reference on :ref:`outputs <Output>` for descriptions of the meaning of each field.
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"condition": {
|
||||
"details": {
|
||||
"type": "threshold-sha-256",
|
||||
"threshold": 2,
|
||||
"subconditions": [
|
||||
{
|
||||
"public_key": "<new owner 1 public key>",
|
||||
"type": "ed25519-sha-256",
|
||||
},
|
||||
{
|
||||
"public_key": "<new owner 2 public key>",
|
||||
"type": "ed25519-sha-256",
|
||||
}
|
||||
],
|
||||
},
|
||||
"uri": "ni:///sha-256;PNYwdxaRaNw60N6LDFzOWO97b8tJeragczakL8PrAPc?fpt=ed25519-sha-256&cost=131072"},
|
||||
"public_keys": [
|
||||
"<owner 1 public key>",
|
||||
"<owner 2 public key>"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
- ``subconditions``: a list of condition specs
|
||||
- ``threshold``: threshold to reach for the subconditions to reach a valid fulfillment
|
||||
|
||||
The ``threshold`` can 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. If it is desired to give a different weight to a subcondition, it should be specified multiple times.
|
||||
|
||||
Inputs
|
||||
------
|
||||
|
||||
One Current Owner
|
||||
`````````````````
|
||||
|
||||
If there is only one *current owner*, the fulfillment will be a simple signature fulfillment (i.e. containing just one signature).
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"owners_before": ["<public key of the owner before the transaction happened>"],
|
||||
"fulfillment": "cf:4:RxFzIE679tFBk8zwEgizhmTuciAylvTUwy6EL6ehddHFJOhK5F4IjwQ1xLu2oQK9iyRCZJdfWAefZVjTt3DeG5j2exqxpGliOPYseNkRAWEakqJ_UrCwgnj92dnFRAEE",
|
||||
"fulfills": {
|
||||
"output_index": 0,
|
||||
"transaction_id": "11b3e7d893cc5fdfcf1a1706809c7def290a3b10b0bef6525d10b024649c42d3"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
See the reference on :ref:`inputs <Input>` for descriptions of the meaning of each field.
|
||||
|
||||
Multiple Current Owners
|
||||
```````````````````````
|
||||
|
||||
If there are multiple *current owners*, the fulfillment will be a little different from `One Current Owner`_. Suppose it has two current owners.
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"owners_before": ["<public key of the first owner before the transaction happened>","<public key of the second owner before the transaction happened>"],
|
||||
"fulfillment": "cf:2:AQIBAgEBYwAEYEv6O5HjHGl7OWo2Tu5mWcWQcL_OGrFuUjyej-dK3LM99TbZsRd8c9luQhU30xCH5AdNaupxg-pLHuk8DoSaDA1MHQGXUZ80a_cV-4UaaaCpdey8K0CEcJxre0X96hTHCwABAWMABGBnsuHExhuSj5Mdm-q0KoPgX4nAt0s00k1WTMCzuUpQIp6aStLoTSMlsvS4fmDtOSv9gubekKLuHTMAk-LQFSKF1JdzwaVWAA2UOv0v_OS2gY3A-r0kRq8HtzjYdcmVswUA",
|
||||
"fulfills": {
|
||||
"output_index": 0,
|
||||
"transaction_id": "e4805f1bfc999d6409b38e3a4c3b2fafad7c1280eb0d441da7083e945dd89eb8"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- ``owners_before``: A list of public keys of the owners before the transaction; in this case it has two owners, hence two public keys.
|
||||
- ``fulfillment``: A crypto-conditions URI that encodes the cryptographic fulfillments like signatures and others;'cf' indicates this is a fulfillment, '2' indicates the condition type is THRESHOLD-SHA-256 (while '4' in `One Current Owner`_ indicates its condition type is ED25519).
|
||||
- ``fulfills``: Pointer to an output from a previous transaction that is being spent
|
||||
- ``output_index``: The index of the output in a previous transaction
|
||||
- ``transaction_id``: ID of the transaction
|
||||
The BigchainDB documentation and code talks about control of an asset in terms of "owners" and "ownership." The language is chosen to represent the most common use cases, but in some more complex scenarios, it may not be accurate to say that the output is owned by the controllers of those public keys—it would only be correct to say that those public keys are associated with the ability to fulfill the conditions on the output. Also, depending on the use case, the entity controlling an output via a private key may not be the legal owner of the asset in the corresponding legal domain. However, since we aim to use language that is simple to understand and covers the majority of use cases, we talk in terms of "owners" of an output that have the ability to "spend" that output.
|
||||
|
@ -1,17 +1,3 @@
|
||||
.. raw:: html
|
||||
|
||||
<style>
|
||||
.rst-content a.internal[href*='/schema/'] {
|
||||
border: solid 1px #e1e4e5;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
color: blue;
|
||||
padding: 2px 4px;
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
=====================
|
||||
The Transaction Model
|
||||
=====================
|
||||
|
||||
@ -20,35 +6,57 @@ A transaction has the following structure:
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"id": "<hash of transaction, excluding signatures (see explanation)>",
|
||||
"version": "<version number of the transaction model>",
|
||||
"inputs": ["<list of inputs>"],
|
||||
"outputs": ["<list of outputs>"],
|
||||
"operation": "<string>",
|
||||
"asset": "<asset model; see below>",
|
||||
"metadata": "<any JSON document>"
|
||||
"id": "<ID of the transaction>",
|
||||
"version": "<Transaction schema version number>",
|
||||
"inputs": ["<List of inputs>"],
|
||||
"outputs": ["<List of outputs>"],
|
||||
"operation": "<String>",
|
||||
"asset": {"<Asset model; see below>"},
|
||||
"metadata": {"<Arbitrary transaction metadata>"}
|
||||
}
|
||||
|
||||
Here's some explanation of the contents of a :ref:`transaction <transaction>`:
|
||||
Here's some explanation of the contents:
|
||||
|
||||
- **id**: The :ref:`id <transaction.id>` of the transaction, and also the database primary key.
|
||||
- **id**: The ID of the transaction and also the hash of the transaction (loosely speaking). See below for an explanation of how it's computed. It's also the database primary key.
|
||||
|
||||
- **version**: :ref:`Version <transaction.version>` number of the transaction model, so that software can support different transaction models.
|
||||
- **version**: The version-number of :ref:`the transaction schema <Transaction Schema>`. As of BigchainDB Server 1.0.0, the only allowed value is ``"1.0"``.
|
||||
|
||||
- **inputs**: List of inputs. Each :ref:`input <Input>` contains a pointer to an unspent output
|
||||
and a *crypto fulfillment* that satisfies the conditions of that output. A *fulfillment*
|
||||
is usually a signature proving the ownership of the asset.
|
||||
See :doc:`./inputs-outputs`.
|
||||
- **inputs**: List of inputs.
|
||||
Each input spends/transfers a previous output by satisfying/fulfilling
|
||||
the crypto-conditions on that output.
|
||||
A CREATE transaction should have exactly one input.
|
||||
A TRANSFER transaction should have at least one input (i.e. ≥1).
|
||||
For more details, see the subsection about :ref:`inputs <Inputs>`.
|
||||
|
||||
- **outputs**: List of outputs. Each :ref:`output <Output>` contains *crypto-conditions* that need to be fulfilled by a transfer transaction in order to transfer ownership to new owners.
|
||||
See :doc:`./inputs-outputs`.
|
||||
- **outputs**: List of outputs.
|
||||
Each output indicates the crypto-conditions which must be satisfied
|
||||
by anyone wishing to spend/transfer that output.
|
||||
It also indicates the number of shares of the asset tied to that output.
|
||||
For more details, see the subsection about :ref:`outputs <Outputs>`.
|
||||
|
||||
- **operation**: String representation of the :ref:`operation <transaction.operation>` being performed (currently either "CREATE", "TRANSFER" or "GENESIS"). It determines how the transaction should be validated.
|
||||
- **operation**: A string indicating what kind of transaction this is,
|
||||
and how it should be validated.
|
||||
It can only be ``"CREATE"``, ``"TRANSFER"`` or ``"GENESIS"``
|
||||
(but there should only be one transaction whose operation is ``"GENESIS"``:
|
||||
the one in the GENESIS block).
|
||||
|
||||
- **asset**: Definition of the :ref:`asset <Asset>`. See :ref:`the page about the asset model <The Asset Model>`.
|
||||
- **asset**: A JSON document for the asset associated with the transaction.
|
||||
(A transaction can only be associated with one asset.)
|
||||
See :ref:`the page about the asset model <The Asset Model>`.
|
||||
|
||||
- **metadata**: User-provided transaction :ref:`metadata <metadata>`: Can be any JSON document, or `NULL`.
|
||||
- **metadata**: User-provided transaction metadata.
|
||||
It can be any valid JSON document, or ``null``.
|
||||
|
||||
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 input. A creation transaction is signed by whoever created it. A transfer transaction is signed by whoever currently controls or owns it.
|
||||
**How the transaction ID is computed.**
|
||||
1) Build a Python dictionary containing ``version``, ``inputs``, ``outputs``, ``operation``, ``asset``, ``metadata`` and their values,
|
||||
2) In each of the inputs, replace the value of each ``fulfillment`` with ``null``,
|
||||
3) :ref:`Serialize <JSON Serialization>` that dictionary,
|
||||
4) The transaction ID is just :ref:`the SHA3-256 hash <Hashes>` of the serialized dictionary.
|
||||
|
||||
What gets signed? For each input in the transaction, the "fullfillment message" that gets signed includes the JSON serialized body of the transaction, minus any fulfillment strings. The computed signature goes into creating the ``fulfillment`` string of the input.
|
||||
**About signing the 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 input. What gets signed (as of version 1.0.0) is everything inside the transaction, including the ``id``, but the value of each ``fulfillment`` is replaced with ``null``.
|
||||
|
||||
There are example BigchainDB transactions in
|
||||
:ref:`the HTTP API documentation <The HTTP Client-Server API>`
|
||||
and
|
||||
`the Python Driver documentation <https://docs.bigchaindb.com/projects/py-driver/en/latest/usage.html>`_.
|
||||
|
@ -1,5 +1,5 @@
|
||||
Drivers & Clients
|
||||
=================
|
||||
Drivers & Tools
|
||||
===============
|
||||
|
||||
Libraries and Tools Maintained by the BigchainDB Team
|
||||
-----------------------------------------------------
|
||||
|
@ -46,11 +46,15 @@ Configure MongoDB Cloud Manager for Monitoring
|
||||
connections, and click ``Continue``. This should already be selected for
|
||||
you in case you selected ``X.509 Client Certificate`` above.
|
||||
|
||||
* Once the deployment is found, click the ``Continue`` button again.
|
||||
This may take about a minute or two.
|
||||
* Wait a minute or two for the deployment to be found and then
|
||||
click the ``Continue`` button again.
|
||||
|
||||
* Verify that you see your process on the Cloud Manager UI, and click
|
||||
``Continue`` for the third time.
|
||||
* Verify that you see your process on the Cloud Manager UI.
|
||||
It should look something like this:
|
||||
|
||||
.. image:: /_static/mongodb_cloud_manager_1.png
|
||||
|
||||
* Click ``Continue``.
|
||||
|
||||
* Verify on the UI that data is being sent by the monitoring agent to the
|
||||
Cloud Manager. It may take upto 5 minutes for data to appear on the UI.
|
||||
|
@ -49,7 +49,7 @@ There are some things worth noting about the ``mdb-instance-name``:
|
||||
* We use ``mdb-instance-0``, ``mdb-instance-1`` and so on in our
|
||||
documentation. Your BigchainDB cluster may use a different naming convention.
|
||||
|
||||
bdb-keyring.bdb-keyring
|
||||
bdb-config.bdb-keyring
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This lists the BigchainDB public keys
|
||||
@ -70,29 +70,8 @@ of all *other* nodes in your BigchainDB cluster
|
||||
For example,
|
||||
``"DPjpKbmbPYPKVAuf6VSkqGCf5jzrEh69Ldef6TrLwsEQ:EPQk5i5yYpoUwGVM8VKZRjM8CYxB6j8Lu8i8SG7kGGce"``
|
||||
|
||||
|
||||
Edit secret.yaml
|
||||
----------------
|
||||
|
||||
Make a copy of the file ``k8s/configuration/secret.yaml``
|
||||
and edit the data values in the various Secrets.
|
||||
That file includes many comments to explain the required values.
|
||||
**In particular, note that all values must be base64-encoded.**
|
||||
There are tips at the top of the file
|
||||
explaining how to convert values into base64-encoded values.
|
||||
|
||||
Your BigchainDB node might not need all the Secrets.
|
||||
For example, if you plan to access the BigchainDB API over HTTP, you
|
||||
don't need the ``https-certs`` Secret.
|
||||
You can delete the Secrets you don't need,
|
||||
or set their data values to ``""``.
|
||||
|
||||
Note that ``ca.pem`` is just another name for ``ca.crt``
|
||||
(the certificate of your BigchainDB cluster's self-signed CA).
|
||||
|
||||
|
||||
bdb-certs.bdb-user
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
bdb-config.bdb-user
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is the user name that BigchainDB uses to authenticate itself to the
|
||||
backend MongoDB database.
|
||||
@ -114,13 +93,33 @@ You should see an output line that resembles:
|
||||
subject= emailAddress=dev@bigchaindb.com,CN=test-bdb-ssl,OU=BigchainDB-Instance,O=BigchainDB GmbH,L=Berlin,ST=Berlin,C=DE
|
||||
|
||||
The ``subject`` line states the complete user name we need to use for this
|
||||
field (``bdb-certs.bdb-user``), i.e.
|
||||
field (``bdb-config.bdb-user``), i.e.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
emailAddress=dev@bigchaindb.com,CN=test-bdb-ssl,OU=BigchainDB-Instance,O=BigchainDB GmbH,L=Berlin,ST=Berlin,C=DE
|
||||
|
||||
|
||||
Edit secret.yaml
|
||||
----------------
|
||||
|
||||
Make a copy of the file ``k8s/configuration/secret.yaml``
|
||||
and edit the data values in the various Secrets.
|
||||
That file includes many comments to explain the required values.
|
||||
**In particular, note that all values must be base64-encoded.**
|
||||
There are tips at the top of the file
|
||||
explaining how to convert values into base64-encoded values.
|
||||
|
||||
Your BigchainDB node might not need all the Secrets.
|
||||
For example, if you plan to access the BigchainDB API over HTTP, you
|
||||
don't need the ``https-certs`` Secret.
|
||||
You can delete the Secrets you don't need,
|
||||
or set their data values to ``""``.
|
||||
|
||||
Note that ``ca.pem`` is just another name for ``ca.crt``
|
||||
(the certificate of your BigchainDB cluster's self-signed CA).
|
||||
|
||||
|
||||
threescale-credentials.*
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -128,7 +128,22 @@ Step 4.1: Vanilla NGINX
|
||||
the ConfigMap followed by ``-dep``. For example, if the value set in the
|
||||
``ngx-instance-name`` is ``ngx-instance-0``, set the
|
||||
``spec.selector.app`` to ``ngx-instance-0-dep``.
|
||||
|
||||
|
||||
* Set ``ngx-public-mdb-port.port`` to 27017, or the port number on which you
|
||||
want to expose MongoDB service.
|
||||
Set the ``ngx-public-mdb-port.targetPort`` to the port number on which the
|
||||
Kubernetes MongoDB service will be present.
|
||||
|
||||
* Set ``ngx-public-api-port.port`` to 80, or the port number on which you want to
|
||||
expose BigchainDB API service.
|
||||
Set the ``ngx-public-api-port.targetPort`` to the port number on which the
|
||||
Kubernetes BigchainDB API service will present.
|
||||
|
||||
* Set ``ngx-public-ws-port.port`` to 81, or the port number on which you want to
|
||||
expose BigchainDB Websocket service.
|
||||
Set the ``ngx-public-ws-port.targetPort`` to the port number on which the
|
||||
BigchainDB Websocket service will be present.
|
||||
|
||||
* Start the Kubernetes Service:
|
||||
|
||||
.. code:: bash
|
||||
@ -155,6 +170,27 @@ Step 4.2: OpenResty NGINX + 3scale
|
||||
``ngx-instance-name`` is ``ngx-instance-0``, set the
|
||||
``spec.selector.app`` to ``ngx-instance-0-dep``.
|
||||
|
||||
* Set ``ngx-public-mdb-port.port`` to 27017, or the port number on which you
|
||||
want to expose MongoDB service.
|
||||
Set the ``ngx-public-mdb-port.targetPort`` to the port number on which the
|
||||
Kubernetes MongoDB service will be present.
|
||||
|
||||
* Set ``ngx-public-3scale-port.port`` to 8080, or the port number on which
|
||||
you want to let 3scale communicate with Openresty NGINX for authenctication.
|
||||
Set the ``ngx-public-3scale-port.targetPort`` to the port number on which
|
||||
this Openresty NGINX service will be listening to for communication with
|
||||
3scale.
|
||||
|
||||
* Set ``ngx-public-bdb-port.port`` to 443, or the port number on which you want
|
||||
to expose BigchainDB API service.
|
||||
Set the ``ngx-public-api-port.targetPort`` to the port number on which the
|
||||
Kubernetes BigchainDB API service will present.
|
||||
|
||||
* Set ``ngx-public-bdb-port-http.port`` to 80, or the port number on which you
|
||||
want to expose BigchainDB Websocket service.
|
||||
Set the ``ngx-public-bdb-port-http.targetPort`` to the port number on which the
|
||||
BigchainDB Websocket service will be present.
|
||||
|
||||
* Start the Kubernetes Service:
|
||||
|
||||
.. code:: bash
|
||||
@ -277,12 +313,6 @@ Step 8.1: Vanilla NGINX
|
||||
``BIGCHAINDB_BACKEND_HOST`` env var to
|
||||
``bdb-instance-0.default.svc.cluster.local``.
|
||||
|
||||
* Set ``MONGODB_FRONTEND_PORT`` to 27017, or the port number on which you
|
||||
want to expose MongoDB service.
|
||||
|
||||
* Set ``BIGCHAINDB_FRONTEND_PORT`` to 80, or the port number on which you
|
||||
want to expose BigchainDB service.
|
||||
|
||||
* Start the Kubernetes Deployment:
|
||||
|
||||
.. code:: bash
|
||||
@ -315,12 +345,6 @@ Step 8.2: OpenResty NGINX + 3scale
|
||||
``BIGCHAINDB_BACKEND_HOST`` env var to
|
||||
``bdb-instance-0.default.svc.cluster.local``.
|
||||
|
||||
* Set ``MONGODB_FRONTEND_PORT`` to 27017, or the port number on which you
|
||||
want to expose the MongoDB service.
|
||||
|
||||
* Set ``BIGCHAINDB_FRONTEND_PORT`` to 443, or the port number on which you
|
||||
want to expose the BigchainDB service over HTTPS.
|
||||
|
||||
* Start the Kubernetes Deployment:
|
||||
|
||||
.. code:: bash
|
||||
@ -658,7 +682,7 @@ Step 14: Start a Kubernetes Deployment for MongoDB Backup Agent
|
||||
$ kubectl --context k8s-bdb-test-cluster-0 apply -f mongodb-backup-agent/mongo-backup-dep.yaml
|
||||
|
||||
|
||||
Step 15: Start a Kubernetes Deployment for Bigchaindb
|
||||
Step 15: Start a Kubernetes Deployment for BigchainDB
|
||||
-----------------------------------------------------
|
||||
|
||||
* This configuration is located in the file
|
||||
@ -670,18 +694,13 @@ Step 15: Start a Kubernetes Deployment for Bigchaindb
|
||||
For example, if the value set in the
|
||||
``bdb-instance-name`` is ``bdb-instance-0``, set the fields to the
|
||||
value ``bdb-insance-0-dep``.
|
||||
|
||||
* Set ``BIGCHAINDB_DATABASE_HOST`` to the value set in ``mdb-instance-name``
|
||||
in the ConfigMap.
|
||||
For example, if the value set in the ``mdb-instance-name`` is
|
||||
``mdb-instance-0``, set the field to the value ``mdb-instance-0``.
|
||||
|
||||
* Set the appropriate ``BIGCHAINDB_KEYPAIR_PUBLIC``,
|
||||
``BIGCHAINDB_KEYPAIR_PRIVATE`` values.
|
||||
|
||||
* One way to generate BigchainDB keypair is to run a Python shell with
|
||||
the command
|
||||
``from bigchaindb_driver import crypto; crypto.generate_keypair()``.
|
||||
* Set the value of ``BIGCHAINDB_KEYPAIR_PRIVATE`` (not base64-encoded).
|
||||
(In the future, we'd like to pull the BigchainDB private key from
|
||||
the Secret named ``bdb-private-key``,
|
||||
but a Secret can only be mounted as a file,
|
||||
so BigchainDB Server would have to be modified to look for it
|
||||
in a file.)
|
||||
|
||||
* As we gain more experience running BigchainDB in testing and production,
|
||||
we will tweak the ``resources.limits`` values for CPU and memory, and as
|
||||
@ -695,16 +714,16 @@ Step 15: Start a Kubernetes Deployment for Bigchaindb
|
||||
$ kubectl --context k8s-bdb-test-cluster-0 apply -f bigchaindb/bigchaindb-dep.yaml
|
||||
|
||||
|
||||
* You can check its status using the command ``kubectl get deploy -w``
|
||||
* You can check its status using the command ``kubectl get deployments -w``
|
||||
|
||||
|
||||
Step 16: Configure the MongoDB Cloud Manager
|
||||
--------------------------------------------
|
||||
|
||||
* Refer to the
|
||||
:ref:`documentation <Configure MongoDB Cloud Manager for Monitoring and Backup>`
|
||||
for details on how to configure the MongoDB Cloud Manager to enable
|
||||
monitoring and backup.
|
||||
Refer to the
|
||||
:ref:`documentation <Configure MongoDB Cloud Manager for Monitoring and Backup>`
|
||||
for details on how to configure the MongoDB Cloud Manager to enable
|
||||
monitoring and backup.
|
||||
|
||||
|
||||
Step 17: Verify the BigchainDB Node Setup
|
||||
@ -713,20 +732,13 @@ Step 17: Verify the BigchainDB Node Setup
|
||||
Step 17.1: Testing Internally
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Run a container that provides utilities like ``nslookup``, ``curl`` and ``dig``
|
||||
on the cluster and query the internal DNS and IP endpoints.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ kubectl run -it toolbox -- image <docker image to run> --restart=Never --rm
|
||||
|
||||
There is a generic image based on alpine:3.5 with the required utilities
|
||||
hosted at Docker Hub under
|
||||
`bigchaindb/toolbox <https://hub.docker.com/r/bigchaindb/toolbox/>`_.
|
||||
The corresponding
|
||||
To test the setup of your BigchainDB node, you could use a Docker container
|
||||
that provides utilities like ``nslookup``, ``curl`` and ``dig``.
|
||||
For example, you could use a container based on our
|
||||
`bigchaindb/toolbox <https://hub.docker.com/r/bigchaindb/toolbox/>`_ image.
|
||||
(The corresponding
|
||||
`Dockerfile <https://github.com/bigchaindb/bigchaindb/blob/master/k8s/toolbox/Dockerfile>`_
|
||||
is in the ``bigchaindb/bigchaindb`` repository on GitHub.
|
||||
|
||||
is in the ``bigchaindb/bigchaindb`` repository on GitHub.)
|
||||
You can use it as below to get started immediately:
|
||||
|
||||
.. code:: bash
|
||||
@ -738,74 +750,69 @@ You can use it as below to get started immediately:
|
||||
--restart=Never --rm
|
||||
|
||||
It will drop you to the shell prompt.
|
||||
Now you can query for the ``mdb`` and ``bdb`` service details.
|
||||
|
||||
The ``nslookup`` commands should output the configured IP addresses of the
|
||||
services in the cluster
|
||||
|
||||
The ``dig`` commands should return the port numbers configured for the
|
||||
various services in the cluster.
|
||||
|
||||
Finally, the ``curl`` commands test the availability of the services
|
||||
themselves.
|
||||
|
||||
* Verify MongoDB instance
|
||||
To test the MongoDB instance:
|
||||
|
||||
.. code:: bash
|
||||
.. code:: bash
|
||||
|
||||
$ nslookup mdb-instance-0
|
||||
$ nslookup mdb-instance-0
|
||||
|
||||
$ dig +noall +answer _mdb-port._tcp.mdb-instance-0.default.svc.cluster.local SRV
|
||||
$ dig +noall +answer _mdb-port._tcp.mdb-instance-0.default.svc.cluster.local SRV
|
||||
|
||||
$ curl -X GET http://mdb-instance-0:27017
|
||||
$ curl -X GET http://mdb-instance-0:27017
|
||||
|
||||
The ``nslookup`` command should output the configured IP address of the service
|
||||
(in the cluster).
|
||||
The ``dig`` command should return the configured port numbers.
|
||||
The ``curl`` command tests the availability of the service.
|
||||
|
||||
To test the BigchainDB instance:
|
||||
|
||||
* Verify BigchainDB instance
|
||||
.. code:: bash
|
||||
|
||||
$ nslookup bdb-instance-0
|
||||
|
||||
$ dig +noall +answer _bdb-port._tcp.bdb-instance-0.default.svc.cluster.local SRV
|
||||
|
||||
$ curl -X GET http://bdb-instance-0:9984
|
||||
|
||||
To test the NGINX instance:
|
||||
|
||||
.. code:: bash
|
||||
.. code:: bash
|
||||
|
||||
$ nslookup bdb-instance-0
|
||||
$ nslookup ngx-instance-0
|
||||
|
||||
$ dig +noall +answer _bdb-port._tcp.bdb-instance-0.default.svc.cluster.local SRV
|
||||
|
||||
$ curl -X GET http://bdb-instance-0:9984
|
||||
|
||||
* Verify NGINX instance
|
||||
|
||||
.. code:: bash
|
||||
$ dig +noall +answer _ngx-public-mdb-port._tcp.ngx-instance-0.default.svc.cluster.local SRV
|
||||
|
||||
$ nslookup ngx-instance-0
|
||||
|
||||
$ dig +noall +answer _ngx-public-mdb-port._tcp.ngx-instance-0.default.svc.cluster.local SRV
|
||||
|
||||
$ curl -X GET http://ngx-instance-0:27017 # results in curl: (56) Recv failure: Connection reset by peer
|
||||
|
||||
$ dig +noall +answer _ngx-public-bdb-port._tcp.ngx-instance-0.default.svc.cluster.local SRV
|
||||
|
||||
* If you have run the vanilla NGINX instance, run
|
||||
$ dig +noall +answer _ngx-public-bdb-port._tcp.ngx-instance-0.default.svc.cluster.local SRV
|
||||
|
||||
.. code:: bash
|
||||
$ curl -X GET http://ngx-instance-0:27017
|
||||
|
||||
$ curl -X GET http://ngx-instance-0:80
|
||||
|
||||
* If you have the OpenResty NGINX + 3scale instance, run
|
||||
The curl command should result get the response
|
||||
``curl: (7) Failed to connect to ngx-instance-0 port 27017: Connection refused``.
|
||||
|
||||
.. code:: bash
|
||||
If you ran the vanilla NGINX instance, run:
|
||||
|
||||
$ curl -X GET https://ngx-instance-0
|
||||
.. code:: bash
|
||||
|
||||
$ curl -X GET http://ngx-instance-0:80
|
||||
|
||||
* Check the MongoDB monitoring and backup agent on the MongoDB Cloud Manager
|
||||
portal to verify they are working fine.
|
||||
|
||||
* Send some transactions to BigchainDB and verify it's up and running!
|
||||
If you ran the OpenResty NGINX + 3scale instance, run:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ curl -X GET https://ngx-instance-0
|
||||
|
||||
|
||||
Step 17.2: Testing Externally
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Try to access the ``<dns/ip of your exposed bigchaindb service endpoint>:80``
|
||||
on your browser. You must receive a json output that shows the BigchainDB
|
||||
server version among other things.
|
||||
Check the MongoDB monitoring and backup agent on the MongoDB Cloud Manager
|
||||
portal to verify they are working fine.
|
||||
|
||||
Try to access the ``<DNS/IP of your exposed BigchainDB service endpoint>:80``
|
||||
on your browser. You should receive a JSON response that shows the BigchainDB
|
||||
server version, among other things.
|
||||
|
||||
Use the Python Driver to send some transactions to the BigchainDB node and
|
||||
verify that your node or cluster works as expected.
|
||||
|
||||
|
@ -37,7 +37,7 @@ For convenience, here's a list of all the relevant environment variables (docume
|
||||
`BIGCHAINDB_LOG_FMT_LOGFILE`<br>
|
||||
`BIGCHAINDB_LOG_GRANULAR_LEVELS`<br>
|
||||
`BIGCHAINDB_DATABASE_SSL`<br>
|
||||
`BIGCHIANDB_DATABASE_LOGIN`<br>
|
||||
`BIGCHAINDB_DATABASE_LOGIN`<br>
|
||||
`BIGCHAINDB_DATABASE_PASSWORD`<br>
|
||||
`BIGCHAINDB_DATABASE_CA_CERT`<br>
|
||||
`BIGCHAINDB_DATABASE_CERTFILE`<br>
|
||||
|
433
docs/upgrade-guides/v0.10-v1.0.md
Normal file
433
docs/upgrade-guides/v0.10-v1.0.md
Normal file
@ -0,0 +1,433 @@
|
||||
# Updating from BigchainDB v0.10 to v1.0
|
||||
|
||||
BigchainDB v1.0 stands for backwards compatibility. This means that all
|
||||
following [minor](http://semver.org/) releases after version 1.0 will always be
|
||||
backwards-compatible to previous versions.
|
||||
|
||||
For all future releases, we commit to not introduce breaking changes to the
|
||||
public interfaces of BigchainDB's:
|
||||
|
||||
- [Data
|
||||
model](https://docs.bigchaindb.com/projects/server/en/latest/data-models/index.html)
|
||||
- [HTTP
|
||||
API](https://docs.bigchaindb.com/projects/server/en/latest/http-client-server-api.html)
|
||||
- [WebSocket Event Stream
|
||||
API](https://docs.bigchaindb.com/projects/server/en/latest/websocket-event-stream-api.html)
|
||||
|
||||
|
||||
As we saw the version bump to v1.0 as our last chance in a while to fix minor
|
||||
annoyances, we intentionally did clean up on the above interfaces. In this
|
||||
document, we'd like to give a comprehensive summary of those changes to allow
|
||||
you to upgrade efficiently.
|
||||
|
||||
The next sections will go over each of the above mentioned interfaces and
|
||||
detail the exact changes.
|
||||
|
||||
## A note upfront
|
||||
|
||||
We tried to test this upgrade guide as best as we could by using it to adjust
|
||||
our official drivers. If you still find breaking changes that causes your
|
||||
software to crash, please let us and others reading this guide know by sending
|
||||
over a Pull-Request or notifying us on Gitter.
|
||||
|
||||
Thank you very much :)
|
||||
|
||||
|
||||
## Syntactical changes
|
||||
|
||||
#### `tx`, `txid` and `tx_id` becomes `transaction_id`
|
||||
|
||||
To establish better consistency between external interfaces, all usages of
|
||||
`txid`, `tx` and `tx_id` in data models and HTTP API were renamed to
|
||||
`transaction_id` or `transaction`.
|
||||
|
||||
|
||||
## Breaking Changes to the Data Model
|
||||
|
||||
#### Output amount is now a string
|
||||
|
||||
BigchainDB transactions may have multiple inputs and outputs, and each output
|
||||
has an amount, which is the integral number of the asset being transferred. In
|
||||
prior versions of BigchainDB, the amount was encoded as a number, which on the
|
||||
face of it is the obvious way to encode an integer. However, as usual the devil
|
||||
is in the details; JSON, the encoding of choice for BigchainDB transactions,
|
||||
encodes all numbers including integers as floating point. This isn't a problem
|
||||
for the majority of circumstances where numbers are small, however in some
|
||||
environments and for some use cases\*, the number may lose precision.
|
||||
|
||||
In order to safeguard against this, amounts are now encoded as strings, and it
|
||||
is recommended to use a decimal math library (such as
|
||||
[big.js](https://github.com/MikeMcl/big.js)) when dealing with large numbers in
|
||||
Javascript. Additionally, numbers are capped at 9e18 to stay comfortably within
|
||||
the boundary of a 64 bit signed integer.
|
||||
|
||||
\* Try this in the Chrome developer console: `2**60 == 2**60+1`.
|
||||
|
||||
|
||||
#### Input `fulfills.txid` is now `transaction_id`
|
||||
|
||||
We renamed a TRANSFER transaction's `inputs.fulfills.txid` to
|
||||
`inputs.fulfills.transaction_id`.
|
||||
|
||||
#### Input `fulfills.output` is now `output_index`
|
||||
|
||||
We renamed a TRANSFER transaction's `inputs.fulfills.output` to
|
||||
`inputs.fulfills.output_index`.
|
||||
|
||||
#### Signing payload is now the transaction body
|
||||
|
||||
The signature payload of a BigchainDB transaction is now "just" the JSON
|
||||
serialized body of the transaction. This change is invisible to applications
|
||||
that do not produce transactions with more than one input. However, prior to
|
||||
the 1.0 release, transactions with multiple inputs had a special signing
|
||||
protocol, which included reassembly of the transaction. This was identified as
|
||||
being unneeded, so now the payload that is signed is always just the serialized
|
||||
transaction, minus signatures. More details, take a look at the
|
||||
[Pull-Request](https://github.com/bigchaindb/bigchaindb/pull/1225) introducing
|
||||
the change or at our updated [Handcrafting
|
||||
Transactions](https://docs.bigchaindb.com/projects/py-driver/en/latest/handcraft.html)
|
||||
document.
|
||||
|
||||
|
||||
#### Update to Crypto-Conditions version 2
|
||||
|
||||
Earlier this year the IETF Interledger working group released an [updated
|
||||
draft](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02) of their
|
||||
Crypto-Conditions specification. To send transactions to BigchainDB v1.0, all
|
||||
transaction's inputs and outputs need to comply to this new version.
|
||||
|
||||
Several of the language specific implementations have already been updated,
|
||||
including:
|
||||
|
||||
- [py-crypto-conditions](https://github.com/bigchaindb/cryptoconditions)
|
||||
- [js-crypto-conditions](https://github.com/interledgerjs/five-bells-condition)
|
||||
- [java-crypto-conditions](https://github.com/interledger/java-crypto-conditions)
|
||||
|
||||
|
||||
If you don't find your preferred language in this list, do not despair but
|
||||
reach out to us for help on Github/Gitter or product@bigchaindb.com.
|
||||
|
||||
|
||||
#### Revamp of Crypto-Conditions signing details
|
||||
|
||||
In order to create a correct fulfillment for an output condition in BigchainDB,
|
||||
we include the conditon URI ("ni:///sha-256;..."), to verify the fulfillment
|
||||
against. However, the condition URI does not tell you who may sign in order to
|
||||
create a correct fulfillment.
|
||||
|
||||
For this, we have the `condition.details` object. This is a recursive data structure
|
||||
which mirrors the n-of-m threshold / ed25519 condition types that we support.
|
||||
|
||||
An example of the new structure is:
|
||||
|
||||
```json
|
||||
{
|
||||
"details": {
|
||||
"type": "threshold-sha-256",
|
||||
"threshold": 2,
|
||||
"subconditions": [
|
||||
{
|
||||
"public_key": "<new owner 1 public key>",
|
||||
"type": "ed25519-sha-256",
|
||||
},
|
||||
{
|
||||
"public_key": "<new owner 2 public key>",
|
||||
"type": "ed25519-sha-256",
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### Transaction version is now 1.0
|
||||
|
||||
The `version` key in the transaction is now set to `'1.0'`.
|
||||
|
||||
|
||||
## Breaking Changes to the HTTP API
|
||||
|
||||
In this section, we'll go over each of the endpoints separately and list the
|
||||
changes done to them:
|
||||
|
||||
|
||||
### `GET /`
|
||||
|
||||
Documentation:
|
||||
|
||||
- [Old](https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html#bigchaindb-root-url)
|
||||
- [New](https://docs.bigchaindb.com/projects/server/en/v1.0.0/http-client-server-api.html#bigchaindb-root-url)
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
- All notion of `_links` was removed
|
||||
- `api_v1` is now an object including currently only one further object called
|
||||
`v1`
|
||||
- `api.v1` includes links that were originally only available through
|
||||
`/api/v1/`
|
||||
- `api.v1` now also includes links to `assets` (a new endpoint) and `outputs`
|
||||
- `streams_v1`'s link was changed from `streams/valid_tx` to
|
||||
`streams/valid_transactions`
|
||||
- `streams_v1` was renamed to `streams`
|
||||
- Usages of scheme, host and port to API V1's endpoints were removed to allow
|
||||
for configurations of BigchainDB behind reverse proxies
|
||||
- e.g. `http://example.com:9984/api/v1/transactions` ==>
|
||||
`/api/v1/transactions`
|
||||
|
||||
|
||||
```json
|
||||
// Old
|
||||
{
|
||||
"_links": {
|
||||
"api_v1": "http://example.com:9984/api/v1/",
|
||||
"docs": "https://docs.bigchaindb.com/projects/server/en/v0.10.2/"
|
||||
},
|
||||
"keyring": [
|
||||
"6qHyZew94NMmUTYyHnkZsB8cxJYuRNEiEpXHe1ih9QX3",
|
||||
"AdDuyrTyjrDt935YnFu4VBCVDhHtY2Y6rcy7x2TFeiRi"
|
||||
],
|
||||
"public_key": "NC8c8rYcAhyKVpx1PCV65CBmyq4YUbLysy3Rqrg8L8mz",
|
||||
"software": "BigchainDB",
|
||||
"version": "0.10.2"
|
||||
}
|
||||
|
||||
// New
|
||||
{
|
||||
"api": {
|
||||
"v1": {
|
||||
"docs": "https://docs.bigchaindb.com/projects/server/en/v0.11.0.dev/http-client-server-api.html",
|
||||
"statuses": "/api/v1/statuses/",
|
||||
"streams": "ws://example.com:9985/api/v1/streams/valid_transactions",
|
||||
"transactions": "/api/v1/transactions/",
|
||||
"assets": "/api/v1/assets/",
|
||||
"outputs": "/api/v1/outputs/"
|
||||
}
|
||||
},
|
||||
"docs": "https://docs.bigchaindb.com/projects/server/en/v0.11.0.dev/",
|
||||
"keyring": [
|
||||
"6qHyZew94NMmUTYyHnkZsB8cxJYuRNEiEpXHe1ih9QX3",
|
||||
"AdDuyrTyjrDt935YnFu4VBCVDhHtY2Y6rcy7x2TFeiRi"
|
||||
],
|
||||
"public_key": "NC8c8rYcAhyKVpx1PCV65CBmyq4YUbLysy3Rqrg8L8mz",
|
||||
"software": "BigchainDB",
|
||||
"version": "0.11.0.dev"
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/v1`
|
||||
|
||||
Documentation:
|
||||
|
||||
- [Old](https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html#api-root-endpoint)
|
||||
- [New](https://docs.bigchaindb.com/projects/server/en/v1.0.0/http-client-server-api.html#api-root-endpoint)
|
||||
|
||||
Changes:
|
||||
|
||||
- All notion of `_links` was removed
|
||||
- The response object of `/api/v1` now includes links to `assets` (a new
|
||||
endpoint) and `outputs`
|
||||
- `streams_v1`'s link was changed from `streams/valid_tx` to
|
||||
`streams/valid_transactions`
|
||||
- `streams_v1` was renamed to `streams`
|
||||
- Usages of scheme, host and port to API V1's endpoints were removed to allow
|
||||
for configurations of BigchainDB behind reverse proxies
|
||||
- e.g. `http://example.com:9984/api/v1/transactions` ==>
|
||||
`/api/v1/transactions`
|
||||
|
||||
|
||||
```json
|
||||
// Old
|
||||
{
|
||||
"_links": {
|
||||
"docs": "https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html",
|
||||
"self": "http://example.com:9984/api/v1/",
|
||||
"statuses": "http://example.com:9984/api/v1/statuses/",
|
||||
"streams_v1": "ws://example.com:9985/api/v1/streams/valid_tx",
|
||||
"transactions": "http://example.com:9984/api/v1/transactions/"
|
||||
}
|
||||
}
|
||||
|
||||
// New
|
||||
{
|
||||
"docs": "https://docs.bigchaindb.com/projects/server/en/v0.11.0.dev/http-client-server-api.html",
|
||||
"statuses": "/api/v1/statuses/",
|
||||
"streams": "ws://example.com:9985/api/v1/streams/valid_transactions",
|
||||
"transactions": "/api/v1/transactions/",
|
||||
"assets": "/api/v1/assets/",
|
||||
"outputs": "/api/v1/outputs/"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### `GET /api/v1/transactions/{tx_id}`
|
||||
|
||||
Documentation:
|
||||
|
||||
- [Old](https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html#get--api-v1-transactions-tx_id)
|
||||
- [New](https://docs.bigchaindb.com/projects/server/en/v1.0.0/http-client-server-api.html#get--api-v1-transactions-transaction_id)
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
- Previously this endpoint returned transactions from BigchainDB's `BACKLOG`
|
||||
and from blocks marked as `UNDECIDED`. With version 1.0, this endpoint will
|
||||
only return transactions included in blocks marked as `VALID`.
|
||||
|
||||
|
||||
### `POST /api/v1/transactions`
|
||||
|
||||
Documentation:
|
||||
|
||||
- [Old](https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html#post--api-v1-transactions)
|
||||
- [New](https://docs.bigchaindb.com/projects/server/en/v1.0.0/http-client-server-api.html#post--api-v1-transactions)
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
- A `Location` HTTP header was included in the endpoint's response to allow
|
||||
users to check the transaction's status more easily via the
|
||||
`/statuses?transaction_id` endpoint
|
||||
|
||||
|
||||
### `GET /api/v1/outputs`
|
||||
|
||||
Documentation:
|
||||
|
||||
- [Old](https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html#get--api-v1-outputs?public_key=public_key)
|
||||
- [New](https://docs.bigchaindb.com/projects/server/en/v1.0.0/http-client-server-api.html#get--api-v1-outputs?public_key=public_key)
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
- Reversed the behavior of the `unspent` query parameter to `spent`, implying
|
||||
the following behavior:
|
||||
- If `?spent=true`, the response is an array of all spent outputs
|
||||
associated with a given public key
|
||||
- If `?spent=false`, response is an array of all NOT YET spent (or
|
||||
"unspent" outputs associated with a given public key
|
||||
- If no ``spent=` filter is present in the request, the response is an
|
||||
array of all outputs associated with a given public key (spent and
|
||||
unspent)
|
||||
|
||||
Previously the response included a list of relative URLs pointed to
|
||||
transations' outputs:
|
||||
|
||||
```json
|
||||
// Old
|
||||
[
|
||||
"../transactions/2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e/outputs/0"
|
||||
]
|
||||
|
||||
// New
|
||||
[
|
||||
{
|
||||
"output_index": 0,
|
||||
"transaction_id": "2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
In the future, we're planning to [upgrade this endpoint
|
||||
further](https://github.com/bigchaindb/bigchaindb/blob/99499b1f8783719a082813912ac9a0d363ae278f/bdb-ip.md#6-a-new-outputs-endpoint)
|
||||
to meet the requirements of [our
|
||||
users](https://github.com/bigchaindb/bigchaindb/issues/1227#issuecomment-307297473).
|
||||
|
||||
|
||||
### `GET /api/v1/statuses?tx_id`
|
||||
|
||||
Documentation:
|
||||
|
||||
- [Old](https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html#get--api-v1-statuses?tx_id=tx_id)
|
||||
- [New](https://docs.bigchaindb.com/projects/server/en/v1.0.0/http-client-server-api.html#get--api-v1-statuses?transaction_id=transaction_id)
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
- All notion of `_links` was removed. In case of querying the status of a
|
||||
transaction already included in a block marked `VALID`, no `_links` object is
|
||||
provided anymore. The response object now only contains a single key value
|
||||
pair named `status`
|
||||
- The query parameter `tx_id` was renamed to `transaction_id`, e.g. `GET
|
||||
/api/v1/statuses?transaction_id=`
|
||||
|
||||
|
||||
```json
|
||||
// Old
|
||||
{
|
||||
"status": "valid",
|
||||
"_links": {
|
||||
"tx": "/transactions/04c00267af82c161b4bf2ad4a47d1ddbfeb47eef1a14b8d51f37d6ee00ea5cdd"
|
||||
}
|
||||
}
|
||||
|
||||
// New
|
||||
{
|
||||
"status": "valid",
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### `GET /api/v1/statuses?block_id`
|
||||
|
||||
Documentation:
|
||||
|
||||
- [Old](https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html#get--api-v1-statuses?block_id=block_id)
|
||||
- [New](https://docs.bigchaindb.com/projects/server/en/v1.0.0/http-client-server-api.html#get--api-v1-statuses?block_id=block_id)
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
- All notion of `_links` was removed. The response object now only contains a
|
||||
single key value pair named `status`
|
||||
|
||||
|
||||
```json
|
||||
// Old
|
||||
{
|
||||
"status": "valid",
|
||||
"_links": {
|
||||
"tx": "/transactions/04c00267af82c161b4bf2ad4a47d1ddbfeb47eef1a14b8d51f37d6ee00ea5cdd"
|
||||
}
|
||||
}
|
||||
|
||||
// New
|
||||
{
|
||||
"status": "valid",
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### `GET /api/v1/blocks?tx_id`
|
||||
|
||||
Documentation:
|
||||
|
||||
- [Old](https://docs.bigchaindb.com/projects/server/en/v0.10.2/http-client-server-api.html#get--api-v1-blocks?tx_id=tx_id&status=UNDECIDED|VALID|INVALID)
|
||||
- [New](https://docs.bigchaindb.com/projects/server/en/v1.0.0/http-client-server-api.html#get--api-v1-blocks?transaction_id=transaction_id&status=UNDECIDED|VALID|INVALID)
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
- The query parameter `tx_id` was renamed to `transaction_id`, e.g. `GET
|
||||
/api/v1/blocks?transaction_id`
|
||||
|
||||
|
||||
## Breaking Changes to the WebSocket Event Stream API
|
||||
|
||||
In the event object sent to a listener, `tx_id` was renamed to
|
||||
`transaction_id`.
|
||||
|
||||
```json
|
||||
// Old
|
||||
{
|
||||
"tx_id": "<sha3-256 hash>",
|
||||
"asset_id": "<sha3-256 hash>",
|
||||
"block_id": "<sha3-256 hash>"
|
||||
}
|
||||
|
||||
// New
|
||||
{
|
||||
"transaction_id": "<sha3-256 hash>",
|
||||
"asset_id": "<sha3-256 hash>",
|
||||
"block_id": "<sha3-256 hash>"
|
||||
}
|
||||
```
|
@ -1,9 +1,3 @@
|
||||
###############################################################
|
||||
# This config file runs bigchaindb:0.10.1 as a k8s Deployment #
|
||||
# and it connects to the mongodb backend running as a #
|
||||
# separate pod #
|
||||
###############################################################
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
@ -18,13 +12,16 @@ spec:
|
||||
terminationGracePeriodSeconds: 10
|
||||
containers:
|
||||
- name: bigchaindb
|
||||
image: bigchaindb/bigchaindb:1.0.0rc1
|
||||
image: bigchaindb/bigchaindb:1.0.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- start
|
||||
env:
|
||||
- name: BIGCHAINDB_DATABASE_HOST
|
||||
value: mdb-instance-0
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: vars
|
||||
key: mdb-instance-name
|
||||
- name: BIGCHAINDB_DATABASE_PORT
|
||||
value: "27017"
|
||||
- name: BIGCHAINDB_DATABASE_REPLICASET
|
||||
@ -40,7 +37,10 @@ spec:
|
||||
- name: BIGCHAINDB_WSSERVER_PORT
|
||||
value: "9985"
|
||||
- name: BIGCHAINDB_KEYPAIR_PUBLIC
|
||||
value: "<public key here>"
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: bdb-config
|
||||
key: bdb-public-key
|
||||
- name: BIGCHAINDB_KEYPAIR_PRIVATE
|
||||
value: "<private key here>"
|
||||
- name: BIGCHAINDB_BACKLOG_REASSIGN_DELAY
|
||||
@ -51,6 +51,8 @@ spec:
|
||||
value: "120"
|
||||
- name: BIGCHAINDB_LOG_LEVEL_CONSOLE
|
||||
value: debug
|
||||
- name: BIGCHAINDB_DATABASE_SSL
|
||||
value: "true"
|
||||
- name: BIGCHAINDB_DATABASE_CA_CERT
|
||||
value: /etc/bigchaindb/ssl/ca.pem
|
||||
- name: BIGCHAINDB_DATABASE_CRLFILE
|
||||
@ -60,10 +62,16 @@ spec:
|
||||
- name: BIGCHAINDB_DATABASE_KEYFILE
|
||||
value: /etc/bigchaindb/ssl/bdb-instance.key
|
||||
- name: BIGCHAINDB_DATABASE_LOGIN
|
||||
value: /etc/bigchaindb/ssl/bdb-user
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: bdb-config
|
||||
key: bdb-user
|
||||
# The following env var is not required for the bootstrap/first node
|
||||
#- name: BIGCHAINDB_KEYRING
|
||||
# value: ""
|
||||
# valueFrom:
|
||||
# configMapKeyRef:
|
||||
# name: bdb-config
|
||||
# key: bdb-keyring
|
||||
ports:
|
||||
- containerPort: 9984
|
||||
hostPort: 9984
|
||||
|
@ -30,18 +30,13 @@ data:
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: bdb-keyring
|
||||
name: bdb-config
|
||||
namespace: default
|
||||
data:
|
||||
# Colon-separated list of all *other* nodes' BigchainDB public keys.
|
||||
bdb-keyring: "<':' separated list of public keys>"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: bdb-public-key
|
||||
namespace: default
|
||||
data:
|
||||
# BigchainDB instance authentication user name
|
||||
bdb-user: "<user name>"
|
||||
# BigchainDB public key of *this* node.
|
||||
# Example: "EPQk5i5yYpoUwGVM8VKZRjM8CYxB6j8Lu8i8SG7kGGce"
|
||||
bdb-public-key: "<public key>"
|
||||
|
@ -82,8 +82,6 @@ data:
|
||||
bdb-instance.pem: "<b64 encoded certificate>"
|
||||
# Base64-encoded private key
|
||||
bdb-instance.key: "<b64 encoded private key>"
|
||||
# Base64-encoded instance authentication credentials
|
||||
bdb-user: "<b64 encoded user name>"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
|
@ -24,7 +24,7 @@ spec:
|
||||
terminationGracePeriodSeconds: 10
|
||||
containers:
|
||||
- name: mdb-backup
|
||||
image: bigchaindb/mongodb-backup-agent:2.0
|
||||
image: bigchaindb/mongodb-backup-agent:3.0
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: MMS_API_KEYFILE_PATH
|
||||
|
@ -24,7 +24,7 @@ spec:
|
||||
terminationGracePeriodSeconds: 10
|
||||
containers:
|
||||
- name: mdb-mon
|
||||
image: bigchaindb/mongodb-monitoring-agent:2.0
|
||||
image: bigchaindb/mongodb-monitoring-agent:3.0
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: MMS_API_KEYFILE_PATH
|
||||
|
@ -21,7 +21,7 @@ spec:
|
||||
terminationGracePeriodSeconds: 10
|
||||
containers:
|
||||
- name: mongodb
|
||||
image: bigchaindb/mongodb:3.4.4
|
||||
image: bigchaindb/mongodb:3.0
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: MONGODB_FQDN
|
||||
|
6
setup.py
6
setup.py
@ -47,6 +47,8 @@ tests_require = [
|
||||
'pep8',
|
||||
'flake8',
|
||||
'flake8-quotes==0.8.1',
|
||||
'hypothesis',
|
||||
'hypothesis-regex',
|
||||
'pylint',
|
||||
'pytest>=3.0.0',
|
||||
'pytest-catchlog>=1.2.2',
|
||||
@ -67,9 +69,9 @@ install_requires = [
|
||||
'rethinkdb~=2.3', # i.e. a version between 2.3 and 3.0
|
||||
'pymongo~=3.4',
|
||||
'pysha3~=1.0.2',
|
||||
'cryptoconditions>=0.6.0.dev',
|
||||
'cryptoconditions~=0.6.0.dev',
|
||||
'python-rapidjson==0.0.11',
|
||||
'logstats>=0.2.1',
|
||||
'logstats~=0.2.1',
|
||||
'flask>=0.10.1',
|
||||
'flask-cors~=3.0.0',
|
||||
'flask-restful~=0.3.0',
|
||||
|
@ -175,3 +175,30 @@ def transfer_utx(user_output, user2_output, utx):
|
||||
@pytest.fixture
|
||||
def transfer_tx(transfer_utx, user_priv):
|
||||
return transfer_utx.sign([user_priv])
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_transaction():
|
||||
return {
|
||||
'asset': {'data': None},
|
||||
'id': 64 * 'a',
|
||||
'inputs': [{
|
||||
'fulfillment': 'dummy',
|
||||
'fulfills': None,
|
||||
'owners_before': [58 * 'a'],
|
||||
}],
|
||||
'metadata': None,
|
||||
'operation': 'CREATE',
|
||||
'outputs': [{
|
||||
'amount': '1',
|
||||
'condition': {
|
||||
'details': {
|
||||
'public_key': 58 * 'b',
|
||||
'type': 'ed25519-sha-256'
|
||||
},
|
||||
'uri': 'dummy',
|
||||
},
|
||||
'public_keys': [58 * 'b']
|
||||
}],
|
||||
'version': '1.0'
|
||||
}
|
||||
|
@ -3,14 +3,21 @@ This module is tests related to schema checking, but _not_ of granular schematic
|
||||
properties related to validation.
|
||||
"""
|
||||
|
||||
from pytest import raises
|
||||
from unittest.mock import patch
|
||||
|
||||
from hypothesis import given
|
||||
from hypothesis_regex import regex
|
||||
from pytest import raises
|
||||
|
||||
from bigchaindb.common.exceptions import SchemaValidationError
|
||||
from bigchaindb.common.schema import (
|
||||
TX_SCHEMA_COMMON, VOTE_SCHEMA, drop_schema_descriptions,
|
||||
validate_transaction_schema, validate_vote_schema)
|
||||
|
||||
SUPPORTED_CRYPTOCONDITION_TYPES = ('threshold-sha-256', 'ed25519-sha-256')
|
||||
UNSUPPORTED_CRYPTOCONDITION_TYPES = (
|
||||
'preimage-sha-256', 'prefix-sha-256', 'rsa-sha-256')
|
||||
|
||||
|
||||
################################################################################
|
||||
# Test of schema utils
|
||||
@ -109,6 +116,63 @@ def test_validate_failure_inconsistent():
|
||||
validate_transaction_schema({})
|
||||
|
||||
|
||||
@given(condition_uri=regex(
|
||||
r'^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{{0,86}})\?fpt=({})'
|
||||
r'&cost=[0-9]+(?![\n])$'.format('|'.join(
|
||||
t for t in SUPPORTED_CRYPTOCONDITION_TYPES))))
|
||||
def test_condition_uri_with_supported_fpt(dummy_transaction, condition_uri):
|
||||
dummy_transaction['outputs'][0]['condition']['uri'] = condition_uri
|
||||
validate_transaction_schema(dummy_transaction)
|
||||
|
||||
|
||||
@given(condition_uri=regex(r'^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{{0,86}})\?fpt='
|
||||
r'({})&cost=[0-9]+(?![\n])$'.format(
|
||||
'|'.join(UNSUPPORTED_CRYPTOCONDITION_TYPES))))
|
||||
def test_condition_uri_with_unsupported_fpt(dummy_transaction, condition_uri):
|
||||
dummy_transaction['outputs'][0]['condition']['uri'] = condition_uri
|
||||
with raises(SchemaValidationError):
|
||||
validate_transaction_schema(dummy_transaction)
|
||||
|
||||
|
||||
@given(condition_uri=regex(
|
||||
r'^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{{0,86}})\?fpt=(?!{})'
|
||||
r'&cost=[0-9]+(?![\n])$'.format('$|'.join(
|
||||
t for t in SUPPORTED_CRYPTOCONDITION_TYPES))))
|
||||
def test_condition_uri_with_unknown_fpt(dummy_transaction, condition_uri):
|
||||
dummy_transaction['outputs'][0]['condition']['uri'] = condition_uri
|
||||
with raises(SchemaValidationError):
|
||||
validate_transaction_schema(dummy_transaction)
|
||||
|
||||
|
||||
@given(condition_uri=regex(
|
||||
r'^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{0,86})\?fpt=threshold-sha-256'
|
||||
r'&cost=[0-9]+&subtypes=ed25519-sha-256(?![\n])$'))
|
||||
def test_condition_uri_with_supported_subtype(dummy_transaction,
|
||||
condition_uri):
|
||||
dummy_transaction['outputs'][0]['condition']['uri'] = condition_uri
|
||||
validate_transaction_schema(dummy_transaction)
|
||||
|
||||
|
||||
@given(condition_uri=regex(
|
||||
r'^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{0,86})\?fpt=threshold-sha-256&cost='
|
||||
r'[0-9]+&subtypes=(preimage-sha-256|prefix-sha-256|rsa-sha-256)(?![\n])$'))
|
||||
def test_condition_uri_with_unsupported_subtype(dummy_transaction,
|
||||
condition_uri):
|
||||
dummy_transaction['outputs'][0]['condition']['uri'] = condition_uri
|
||||
with raises(SchemaValidationError):
|
||||
validate_transaction_schema(dummy_transaction)
|
||||
|
||||
|
||||
@given(condition_uri=regex(
|
||||
r'^ni:\/\/\/sha-256;([a-zA-Z0-9_-]{{0,86}})\?fpt=threshold-sha-256'
|
||||
r'&cost=[0-9]+&subtypes=(?!{})(?![\n])$'.format('$|'.join(
|
||||
t for t in SUPPORTED_CRYPTOCONDITION_TYPES))))
|
||||
def test_condition_uri_with_unknown_subtype(dummy_transaction, condition_uri):
|
||||
dummy_transaction['outputs'][0]['condition']['uri'] = condition_uri
|
||||
with raises(SchemaValidationError):
|
||||
validate_transaction_schema(dummy_transaction)
|
||||
|
||||
|
||||
################################################################################
|
||||
# Test call vote schema
|
||||
|
||||
|
@ -489,3 +489,38 @@ def mocked_setup_sub_logger(mocker):
|
||||
def certs_dir():
|
||||
cwd = os.environ.get('TRAVIS_BUILD_DIR', os.getcwd())
|
||||
return cwd + '/tests/backend/mongodb-ssl/certs'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wsserver_config():
|
||||
from bigchaindb import config
|
||||
return config['wsserver']
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wsserver_scheme(wsserver_config):
|
||||
return wsserver_config['scheme']
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wsserver_host(wsserver_config):
|
||||
return wsserver_config['host']
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wsserver_port(wsserver_config):
|
||||
return wsserver_config['port']
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wsserver_base_url(wsserver_scheme, wsserver_host, wsserver_port):
|
||||
return '{}://{}:{}'.format(wsserver_scheme, wsserver_host, wsserver_port)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def genesis_tx(b, user_pk):
|
||||
from bigchaindb.models import Transaction
|
||||
tx = Transaction.create([b.me], [([user_pk], 1)])
|
||||
tx.operation = Transaction.GENESIS
|
||||
genesis_tx = tx.sign([b.me_private])
|
||||
return genesis_tx
|
||||
|
@ -226,3 +226,14 @@ def test_block_snowflake(create_tx, signed_transfer_tx):
|
||||
snowflake.send(signed_transfer_tx)
|
||||
snowflake.send(create_tx)
|
||||
assert snowflake.send(None) == [create_tx, signed_transfer_tx]
|
||||
|
||||
|
||||
@pytest.mark.bdb
|
||||
@pytest.mark.genesis
|
||||
def test_duplicate_genesis_transaction(b, genesis_block, genesis_tx):
|
||||
# Try to create a duplicate GENESIS transaction
|
||||
# Expect None as it will be rejected during validation
|
||||
|
||||
from bigchaindb.pipelines import block
|
||||
block_maker = block.BlockPipeline()
|
||||
assert block_maker.validate_tx(genesis_tx.to_dict()) is None
|
||||
|
40
tests/web/test_content_type_middleware.py
Normal file
40
tests/web/test_content_type_middleware.py
Normal file
@ -0,0 +1,40 @@
|
||||
from unittest.mock import Mock
|
||||
|
||||
OUTPUTS_ENDPOINT = '/api/v1/outputs/'
|
||||
|
||||
|
||||
def test_middleware_does_nothing_when_no_content_type_is_provided():
|
||||
from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware
|
||||
mock = Mock()
|
||||
middleware = StripContentTypeMiddleware(mock)
|
||||
middleware({'REQUEST_METHOD': 'GET'}, None)
|
||||
|
||||
assert 'CONTENT_TYPE' not in mock.call_args[0][0]
|
||||
|
||||
|
||||
def test_middleware_strips_content_type_from_gets():
|
||||
from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware
|
||||
mock = Mock()
|
||||
middleware = StripContentTypeMiddleware(mock)
|
||||
middleware({'REQUEST_METHOD': 'GET',
|
||||
'CONTENT_TYPE': 'application/json'},
|
||||
None)
|
||||
|
||||
assert 'CONTENT_TYPE' not in mock.call_args[0][0]
|
||||
|
||||
|
||||
def test_middleware_does_notstrip_content_type_from_other_methods():
|
||||
from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware
|
||||
mock = Mock()
|
||||
middleware = StripContentTypeMiddleware(mock)
|
||||
middleware({'REQUEST_METHOD': 'POST',
|
||||
'CONTENT_TYPE': 'application/json'},
|
||||
None)
|
||||
|
||||
assert 'CONTENT_TYPE' in mock.call_args[0][0]
|
||||
|
||||
|
||||
def test_get_outputs_endpoint_with_content_type(client, user_pk):
|
||||
res = client.get(OUTPUTS_ENDPOINT + '?public_key={}'.format(user_pk),
|
||||
headers=[('Content-Type', 'application/json')])
|
||||
assert res.status_code == 200
|
@ -4,7 +4,7 @@ from unittest import mock
|
||||
@mock.patch('bigchaindb.version.__short_version__', 'tst')
|
||||
@mock.patch('bigchaindb.version.__version__', 'tsttst')
|
||||
@mock.patch('bigchaindb.config', {'keyring': ['abc'], 'keypair': {'public': 'def'}})
|
||||
def test_api_root_endpoint(client):
|
||||
def test_api_root_endpoint(client, wsserver_base_url):
|
||||
res = client.get('/')
|
||||
docs_url = ['https://docs.bigchaindb.com/projects/server/en/vtsttst',
|
||||
'/http-client-server-api.html']
|
||||
@ -16,7 +16,8 @@ def test_api_root_endpoint(client):
|
||||
'statuses': '/api/v1/statuses/',
|
||||
'assets': '/api/v1/assets/',
|
||||
'outputs': '/api/v1/outputs/',
|
||||
'streams': 'ws://localhost:9985/api/v1/streams/valid_transactions',
|
||||
'streams': '{}/api/v1/streams/valid_transactions'.format(
|
||||
wsserver_base_url),
|
||||
}
|
||||
},
|
||||
'docs': 'https://docs.bigchaindb.com/projects/server/en/vtsttst/',
|
||||
@ -29,7 +30,7 @@ def test_api_root_endpoint(client):
|
||||
|
||||
@mock.patch('bigchaindb.version.__short_version__', 'tst')
|
||||
@mock.patch('bigchaindb.version.__version__', 'tsttst')
|
||||
def test_api_v1_endpoint(client):
|
||||
def test_api_v1_endpoint(client, wsserver_base_url):
|
||||
docs_url = ['https://docs.bigchaindb.com/projects/server/en/vtsttst',
|
||||
'/http-client-server-api.html']
|
||||
api_v1_info = {
|
||||
@ -38,7 +39,8 @@ def test_api_v1_endpoint(client):
|
||||
'statuses': '/statuses/',
|
||||
'assets': '/assets/',
|
||||
'outputs': '/outputs/',
|
||||
'streams': 'ws://localhost:9985/api/v1/streams/valid_transactions',
|
||||
'streams': '{}/api/v1/streams/valid_transactions'.format(
|
||||
wsserver_base_url),
|
||||
}
|
||||
res = client.get('/api/v1')
|
||||
assert res.json == api_v1_info
|
||||
|
Loading…
x
Reference in New Issue
Block a user