Merge remote-tracking branch 'origin/develop' into feat/17/provide-a-restful-api

This commit is contained in:
vrde 2016-02-24 12:02:54 +01:00
commit 3bfb6bc4c4
13 changed files with 219 additions and 147 deletions

View File

@ -7,7 +7,7 @@ contribute to the project.
We are committed to making participation in this project a harassment-free We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance, identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality. body size, race, ethnicity, age, religion, nationality, or species--no picking on Wrigley for being a buffalo!
Examples of unacceptable behavior by participants include: Examples of unacceptable behavior by participants include:

View File

@ -4,11 +4,11 @@ There are many ways you can contribute to the BigchainDB project, some very easy
## Easy Ways to Contribute ## Easy Ways to Contribute
The BigchainDB community has a Google Group and a Slack chat. Our [Community page](https://www.bigchaindb.com/community) has more information about those. The BigchainDB community has a Google Group and a Gitter chatroom. Our [Community page](https://www.bigchaindb.com/community) has more information about those.
You can also follow us on Twitter [@BigchainDB](https://twitter.com/BigchainDB). You can also follow us on Twitter [@BigchainDB](https://twitter.com/BigchainDB) or read [our blog on Medium](https://medium.com/the-bigchaindb-blog).
If you want to file a bug report, suggest a feature, or ask a code-related question, please go to the `BigchainDB/bigchaindb` repository on GitHub and [create a new Issue](https://github.com/bigchaindb/bigchaindb/issues/new). (You will need a [GitHub account](https://github.com/signup/free) (free).) Please describe the issue clearly, including steps to reproduce when it is a bug. If you want to file a bug report, suggest a feature, or ask a code-related question, please go to the `bigchaindb/bigchaindb` repository on GitHub and [create a new Issue](https://github.com/bigchaindb/bigchaindb/issues/new). (You will need a [GitHub account](https://github.com/signup/free) (free).) Please describe the issue clearly, including steps to reproduce when it is a bug.
## How to Contribute Code or Documentation ## How to Contribute Code or Documentation
@ -26,6 +26,8 @@ Familiarize yourself with how we do coding and documentation in the BigchainDB p
* Note that we call the main branch `develop` rather than `master` * Note that we call the main branch `develop` rather than `master`
* [semantic versioning](http://semver.org/) * [semantic versioning](http://semver.org/)
Note: We have a slight variation on the GitHub Flow: we call the default branch `develop` rather than `master`.
### Step 1 - Fork bigchaindb on GitHub ### Step 1 - Fork bigchaindb on GitHub
In your web browser, go to [the BigchainDB repository on GitHub](https://github.com/bigchaindb/bigchaindb) and click the `Fork` button in the top right corner. This creates a new Git repository named `bigchaindb` in _your_ GitHub account. In your web browser, go to [the BigchainDB repository on GitHub](https://github.com/bigchaindb/bigchaindb) and click the `Fork` button in the top right corner. This creates a new Git repository named `bigchaindb` in _your_ GitHub account.
@ -36,7 +38,7 @@ In your web browser, go to [the BigchainDB repository on GitHub](https://github.
```text ```text
git clone git@github.com:your-github-username/bigchaindb.git git clone git@github.com:your-github-username/bigchaindb.git
cd bigchaindb cd bigchaindb
git add upstream git@github.com:BigchainDB/bigchaindb.git git add upstream git@github.com:bigchaindb/bigchaindb.git
``` ```
### Step 3 - Fetch and Merge the Latest from `upstream/develop` ### Step 3 - Fetch and Merge the Latest from `upstream/develop`
@ -93,7 +95,7 @@ git push origin new-branch-name
Go to the GitHub website and to _your_ remote bigchaindb repository (i.e. something like https://github.com/your-user-name/bigchaindb). Go to the GitHub website and to _your_ remote bigchaindb repository (i.e. something like https://github.com/your-user-name/bigchaindb).
See [GitHub's documentation on how to initiate and send a pull request](https://help.github.com/articles/using-pull-requests/). Note that the destination repository should be `BigchainDB/bigchaindb` and the destination branch will be `develop` (usually, and if it's not, then we can change that if necessary). See [GitHub's documentation on how to initiate and send a pull request](https://help.github.com/articles/using-pull-requests/). Note that the destination repository should be `bigchaindb/bigchaindb` and the destination branch will be `develop` (usually, and if it's not, then we can change that if necessary).
If this is the first time you've submitted a pull request to BigchainDB, then you must read and accept the Contributor License Agreement (CLA) before we can merge your contributions. That can be found at [https://www.bigchaindb.com/cla](https://www.bigchaindb.com/cla). If this is the first time you've submitted a pull request to BigchainDB, then you must read and accept the Contributor License Agreement (CLA) before we can merge your contributions. That can be found at [https://www.bigchaindb.com/cla](https://www.bigchaindb.com/cla).
@ -103,7 +105,7 @@ Someone will then merge your branch or suggest changes. If we suggsest changes,
## Quick Links ## Quick Links
* [BigchainDB Community links](https://www.bigchaindb.com/community) (e.g. mailing list, Slack) * [BigchainDB Community links](https://www.bigchaindb.com/community)
* [General GitHub Documentation](https://help.github.com/) * [General GitHub Documentation](https://help.github.com/)
* [Code of Conduct](./CODE_OF_CONDUCT.md) * [Code of Conduct](./CODE_OF_CONDUCT.md)
* [BigchainDB Licenses](./LICENSES.md) * [BigchainDB Licenses](./LICENSES.md)

View File

@ -1,81 +1,36 @@
# BigchainDB # BigchainDB
A scalable blockchain database. [The whitepaper](https://www.bigchaindb.com/whitepaper/) explains what that means.
[![Join the chat at https://gitter.im/bigchaindb/bigchaindb](https://badges.gitter.im/bigchaindb/bigchaindb.svg)](https://gitter.im/bigchaindb/bigchaindb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/bigchaindb/bigchaindb](https://badges.gitter.im/bigchaindb/bigchaindb.svg)](https://gitter.im/bigchaindb/bigchaindb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![PyPI](https://img.shields.io/pypi/v/bigchaindb.svg)](https://pypi.python.org/pypi/BigchainDB) [![PyPI](https://img.shields.io/pypi/v/bigchaindb.svg)](https://pypi.python.org/pypi/BigchainDB)
[![Travis branch](https://img.shields.io/travis/bigchaindb/bigchaindb/develop.svg)](https://travis-ci.org/bigchaindb/bigchaindb) [![Travis branch](https://img.shields.io/travis/bigchaindb/bigchaindb/develop.svg)](https://travis-ci.org/bigchaindb/bigchaindb)
[![Codecov branch](https://img.shields.io/codecov/c/github/bigchaindb/bigchaindb/develop.svg)](https://codecov.io/github/bigchaindb/bigchaindb?branch=develop) [![Codecov branch](https://img.shields.io/codecov/c/github/bigchaindb/bigchaindb/develop.svg)](https://codecov.io/github/bigchaindb/bigchaindb?branch=develop)
[![Documentation Status](https://readthedocs.org/projects/bigchaindb/badge/?version=develop)](http://bigchaindb.readthedocs.org/en/develop/?badge=develop) [![Documentation Status](https://readthedocs.org/projects/bigchaindb/badge/?version=develop)](http://bigchaindb.readthedocs.org/en/develop/?badge=develop)
## Documentation ## Quick Start
Documentation is available at https://bigchaindb.readthedocs.org/ ### [Install & Run BigchainDB](http://bigchaindb.readthedocs.org/en/develop/installing.html)
### [Run BigchainDB with Docker](http://bigchaindb.readthedocs.org/en/develop/installing.html#run-bigchaindb-with-docker)
### [Getting Started (Tutorial)](http://bigchaindb.readthedocs.org/en/develop/getting-started.html)
## Getting started ## Links for Everyone
* [BigchainDB.com](https://www.bigchaindb.com/) - the main BigchainDB website, including newsletter signup
* [Whitepaper](https://www.bigchaindb.com/whitepaper/) - outlines the motivations, goals and core algorithms of BigchainDB
* [Roadmap](ROADMAP.md)
* [Blog](https://medium.com/the-bigchaindb-blog)
* [Twitter](https://twitter.com/BigchainDB)
* [Google Group](https://groups.google.com/forum/#!forum/bigchaindb)
### Install RethinkDB ## Links for Developers
* [Documentation](http://bigchaindb.readthedocs.org/en/develop/#) - for developers
* [CONTRIBUTING.md](CONTRIBUTING.md) - how to contribute
* [Community guidelines](CODE_OF_CONDUCT.md)
* [Open issues](https://github.com/bigchaindb/bigchaindb/issues)
* [Open pull requests](https://github.com/bigchaindb/bigchaindb/pulls)
* [Gitter chatroom](https://gitter.im/bigchaindb/bigchaindb)
#### On Ubuntu ## Legal
```sh * [Licenses](LICENSES.md) - open source & open content
# install rethinkdb https://rethinkdb.com/docs/install/ubuntu/ * [Imprint](https://www.bigchaindb.com/imprint/)
$ source /etc/lsb-release && echo "deb http://download.rethinkdb.com/apt $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list * [Contact Us](https://www.bigchaindb.com/contact/)
$ wget -qO- http://download.rethinkdb.com/apt/pubkey.gpg | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install rethinkdb
# start rethinkdb
$ rethinkdb
```
#### On other platforms
To install RethinkDB on other platform, please refer to [the official documentation](https://rethinkdb.com/docs/install/).
### Install BigchainDB
```sh
$ pip install bigchaindb
```
### Running BigchainDB
Currently BigchainDB only supports Python 3.4+
Start the main process. If it's the first time `bigchaindb` will generate a default
configuration file for you.
```sh
$ bigchaindb start
```
Generate some tests transactions:
```sh
$ bigchaindb-benchmark load # add '-m' if you want to use all your cores
```
To know more about the bigchain command run
```sh
$ bigchaindb -h
```
#### Importing `BigchainDB` from the interpreter (python/ipython)
Make sure your `rethinkdb` process is running.
```python
>>> from bigchaindb import Bigchain
>>> b = Bigchain()
>>> b.me
'2B8C8PJxhycFzn4wncRhBNmMWwE5Frr9nLBUa1dGGxj5W'
```
#### Configuration
BigchainDB creates a default configuration file on `$HOME/.bigchaindb` on the
first run.
```sh
$ bigchaindb show-config
```
#### Testing
```
$ py.test -v
```

View File

@ -190,7 +190,6 @@ class Bigchain(object):
Returns: Returns:
The transaction that used the `txid` as an input if it exists else it returns `None` The transaction that used the `txid` as an input if it exists else it returns `None`
""" """
# checks if an input was already spent # checks if an input was already spent
# checks if the bigchain has any transaction with input `transaction_id` # checks if the bigchain has any transaction with input `transaction_id`
response = r.table('bigchain').concat_map(lambda doc: doc['block']['transactions'])\ response = r.table('bigchain').concat_map(lambda doc: doc['block']['transactions'])\
@ -272,11 +271,12 @@ class Bigchain(object):
raise exceptions.TransactionOwnerError('current_owner `{}` does not own the input `{}`'.format( raise exceptions.TransactionOwnerError('current_owner `{}` does not own the input `{}`'.format(
transaction['transaction']['current_owner'], transaction['transaction']['input'])) transaction['transaction']['current_owner'], transaction['transaction']['input']))
# check if the input was already spent # check if the input was already spent by a transaction other then this one.
spent = self.get_spent(tx_input['id']) spent = self.get_spent(tx_input['id'])
if spent: if spent:
raise exceptions.DoubleSpend('input `{}` was already spent'.format( if spent['id'] != transaction['id']:
transaction['transaction']['input'])) raise exceptions.DoubleSpend('input `{}` was already spent'.format(
transaction['transaction']['input']))
util.check_hash_and_signature(transaction) util.check_hash_and_signature(transaction)
return transaction return transaction
@ -406,14 +406,12 @@ class Bigchain(object):
# 2. create the block with one transaction # 2. create the block with one transaction
# 3. write the block to the bigchain # 3. write the block to the bigchain
blocks_count = r.table('bigchain').count().run(self.conn) blocks_count = r.table('bigchain').count().run(self.conn)
if blocks_count: if blocks_count:
raise GenesisBlockAlreadyExistsError('Cannot create the Genesis block') raise GenesisBlockAlreadyExistsError('Cannot create the Genesis block')
payload = {'message': 'Hello World from the BigchainDB'}
payload = {'message': 'Hello World from the Bigchain'}
transaction = self.create_transaction(self.me, self.me, None, 'GENESIS', payload=payload) transaction = self.create_transaction(self.me, self.me, None, 'GENESIS', payload=payload)
transaction_signed = self.sign_transaction(transaction, self.me_private) transaction_signed = self.sign_transaction(transaction, self.me_private)

View File

@ -19,7 +19,7 @@ def create_transaction():
val = {} val = {}
tx = request.get_json(force=True) tx = request.get_json(force=True)
if tx['operation'] == 'CREATE': if tx['transaction']['operation'] == 'CREATE':
tx = util.transform_create(tx) tx = util.transform_create(tx)
tx = util.sign_tx(tx, b.me_private) tx = util.sign_tx(tx, b.me_private)

View File

@ -0,0 +1,4 @@
<h3>License</h3>
<p>
This documentation is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.
</p>

View File

@ -168,7 +168,8 @@ html_sidebars = {
'**': ['sidebar-title-template.html', '**': ['sidebar-title-template.html',
'globaltoc.html', 'globaltoc.html',
'sidebar-links-template.html', 'sidebar-links-template.html',
'searchbox.html'], 'searchbox.html',
'license-template.html'],
} }
# Additional templates that should be rendered to pages, maps page names to # Additional templates that should be rendered to pages, maps page names to

View File

@ -47,6 +47,8 @@ sudo pip install bigchaindb
``` ```
(or maybe `sudo pip3 install bigchaindb` or `sudo pip3.4 install bigchaindb`. The `sudo` may not be necessary.) (or maybe `sudo pip3 install bigchaindb` or `sudo pip3.4 install bigchaindb`. The `sudo` may not be necessary.)
Note: You can use `pip` to upgrade bigchaindb to the latest version using `sudo pip install --upgrade bigchaindb`
### How to Install BigchainDB from Source ### How to Install BigchainDB from Source
BigchainDB is in its early stages and being actively developed on its [GitHub repository](https://github.com/bigchaindb/bigchaindb). Contributions are highly appreciated. BigchainDB is in its early stages and being actively developed on its [GitHub repository](https://github.com/bigchaindb/bigchaindb). Contributions are highly appreciated.
@ -86,58 +88,51 @@ During its first run, BigchainDB takes care of configuring a single node environ
**NOT for Production Use** **NOT for Production Use**
For those who like using Docker and wish to experiment with BigchainDB in For those who like using Docker and wish to experiment with BigchainDB in
non-production environments, we currently maintain a `Dockerfile` that can be non-production environments, we currently maintain a `dockerfile` that can be
used to build an image for `bigchaindb`, along with a `docker-compose.yml` file used to build an image for `bigchaindb`, along with a `docker-compose.yml` file
to manage a "standalone node", consisting mainly of two containers: one for to manage a "standalone node", consisting mainly of two containers: one for
rethinkdb, and another for `bigchaindb`. RethinkDB, and another for `bigchaindb`.
Assuming you have `docker` and `docker-compose` installed, you would proceed as Assuming you have `docker` and `docker-compose` installed, you would proceed as
follows. follows.
In a terminal shell: In a terminal shell:
```text
```bash
$ git clone git@github.com:bigchaindb/bigchaindb.git $ git clone git@github.com:bigchaindb/bigchaindb.git
``` ```
Build the docker image Build the Docker image:
```text
```bash
$ docker-compose build $ docker-compose build
``` ```
then, a one-time configuration step, to create the config file, which will be then do a one-time configuration step to create the config file; it will be
stored on your host machine under ` ~/.bigchaindb_docker/config` stored on your host machine under ` ~/.bigchaindb_docker/config`:
```text
```bash
$ docker-compose run --rm bigchaindb bigchaindb configure $ docker-compose run --rm bigchaindb bigchaindb configure
``` ```
you can load test transactions via You can load test transactions via:
```text
```bash
$ docker-compose run --rm bigchaindb bigchaindb-benchmark load $ docker-compose run --rm bigchaindb bigchaindb-benchmark load
``` ```
you should then be able to start `bigchaindb`, via You should then be able to start `bigchaindb`, via:
```text
```bash
$ docker-compose run --rm bigchaindb bigchaindb start $ docker-compose run --rm bigchaindb bigchaindb start
``` ```
or or
```text
```bash
$ docker-compose up $ docker-compose up
``` ```
You should be able to view the rethinkdb dashboard at You should be able to view the RethinkDB dashboard at:
```text
```
http://docker_host:58080/ http://docker_host:58080/
``` ```
where `docker_host` is the ip or hostname of the machine running the docker where `docker_host` is the IP or hostname of the machine running the Docker
engine. If you are developing on linux this most likely will be `localhost`, engine. If you are developing on Linux, this most likely will be `localhost`,
whereas if you are running docker-machine (e.g.: on Mac OS X) this will be the whereas if you are running docker-machine (e.g.: on Mac OS X) this will be the
ip of the docher machine (`docker-machine ip machine_name`). IP of the Docker machine (`docker-machine ip machine_name`).

View File

@ -8,4 +8,6 @@ BigchainDB is a scalable blockchain database. You can read about its motivations
Right now, BigchainDB is fairly new, so there are no live, operational BigchainDB clusters. There are no BigchainDB drivers. Those things are coming. Right now, BigchainDB is fairly new, so there are no live, operational BigchainDB clusters. There are no BigchainDB drivers. Those things are coming.
What does exist is our in-development BigchainDB server software. Therefore all the documentation is about that, for now. What does exist is our in-development BigchainDB server software. Therefore all the documentation is about that, for now.
If you're curious about what's coming in our roadmap, see [the ROADMAP.md file](https://github.com/bigchaindb/bigchaindb/blob/develop/ROADMAP.md) and [the list of open issues](https://github.com/bigchaindb/bigchaindb/issues). If you want to request a feature or file a bug report, see [the CONTRIBUTING.md file](https://github.com/bigchaindb/bigchaindb/blob/develop/CONTRIBUTING.md).

View File

@ -1,6 +1,6 @@
# The Transaction, Block and Vote Models # The Transaction, Block and Vote Models
Transactions, blocks and votes are represented using JSON documents with the following models (schemas). Transactions, blocks and votes are represented using JSON documents with the following models (schemas). See [the section on cryptography](cryptography.html) for more information about how we calculate hashes and signatures.
## The Transaction Model ## The Transaction Model
@ -22,64 +22,59 @@ Transactions, blocks and votes are represented using JSON documents with the fol
} }
} }
}, },
"signature": "<ECDSA signature of the transaction>" "signature": "<signature of the transaction>"
} }
``` ```
A transaction is an operation between the `current_owner` and the `new_owner` over the digital content described by `hash`. For example if could be a transfer of ownership of the digital content `hash` A transaction is an operation between the `current_owner` and the `new_owner` over the digital content described by `hash`. For example if could be a transfer of ownership of the digital content `hash`
- `id`: sha3 hash of the transaction and rethinkdb primary key. By using the hash of the transaction of the - `id`: sha3 hash of the transaction. Also the RethinkDB primary key. By using the hash of the transaction as the primary key, we eliminate the problem of duplicated transactions, if for some reason two nodes decide to create the same transaction
primary key we eliminate the problem of duplicated transactions, if for some reason two nodes decide to create the
same transaction
- `current_owner`: Public key of the current owner of the digital content with hash `hash` - `current_owner`: Public key of the current owner of the digital content with hash `hash`
- `new_owner`: Public key of the new owner of the digital content with hash `hash` - `new_owner`: Public key of the new owner of the digital content with hash `hash`
- `input`: sha3 hash of the transaction in which the content was transfered to the user (similar to input in - `input`: id (sha3 hash) of the transaction in which the content was transfered to the user (similar to input in the blockchain). Right now we will assume that there is only one input per transaction to simplify the prototype. This can be changed in the future to allow multiple inputs per transaction.
the blockchain). Right now we will assume that there is only one input per transaction to simplify the prototype.
This can be changed in the future to allow multiple inputs per transaction.
- `operation`: String representation of the operation being performed (REGISTER, TRANSFER, ...) this will define how - `operation`: String representation of the operation being performed (REGISTER, TRANSFER, ...) this will define how
the transactions should be validated the transactions should be validated
- `timestamp`: Time of creation of the transaction in UTC - `timestamp`: Time of creation of the transaction in UTC
- `data`: JSON object describing the asset (digital content). It contains at least the field `hash` which is a - `data`: JSON object describing the asset (digital content). It contains at least the field `hash` which is a
sha3 hash of the digital content. sha3 hash of the digital content.
- `signature`: ECDSA signature of the transaction with the `current_owner` private key - `signature`: Signature of the transaction with the `current_owner` private key
## The Block Model ## The Block Model
```json ```json
{ {
"id": "<sha3 hash of the list of transactions + timestamp + nodes_pubkeys>", "id": "<sha3 hash of the serialized block contents>",
"block": { "block": {
"timestamp": "<RethinkDB timestamp>", "timestamp": "<RethinkDB timestamp>",
"transactions": ["<list of transactions>"], "transactions": ["<list of transactions>"],
"node_pubkey": "<public key of the node creating the block>", "node_pubkey": "<public key of the node creating the block>",
"voters": ["<list of federation nodes pulic keys>"] "voters": ["<list of federation nodes public keys>"]
}, },
"signature": "<signature of the block>", "signature": "<signature of the block>",
"votes": [] "votes": ["<list of votes>"]
} }
``` ```
Still to be defined when new blocks are created (after x number of transactions, or after x amount of seconds, Still to be defined when new blocks are created (after x number of transactions, or after x amount of seconds,
or both). or both).
A block contains a group of transactions and includes the hash of the hash of the previous block to build the chain. A block contains a group of transactions and includes the hash of the hash of the previous block to build the chain.
- `id`: sha3 hash of the current block. This is also a RethinkDB primary key, this way we make sure that all blocks are unique. - `id`: sha3 hash of the contents of `block` (i.e. the timestamp, list of transactions, node_pubkey, and voters). This is also a RethinkDB primary key; that's how we ensure that all blocks are unique.
- `block`: The actual block - `block`: The actual block
- `timestamp`: timestamp when the block was created - `timestamp`: timestamp when the block was created
- `transactions`: the list of transactions included in the block - `transactions`: the list of transactions included in the block
- `node_pubkey`: the public key of the node that create the block - `node_pubkey`: the public key of the node that create the block
- `voters`: list public keys of the federation nodes. Since the size of the - `voters`: list public keys of the federation nodes. Since the size of the
federation may change over time this will tell us how many nodes existed federation may change over time this will tell us how many nodes existed
in the federation when the block was created so that in a later point in in the federation when the block was created so that in a later point in
time we can check that the block received the correct number of votes. 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 - `signature`: Signature of the block by the node that created the block (i.e. To create it, the node serialized the block contents and signed that with its private key)
- `votes`: Initially an empty list. Nodes in the voters list will append to it - `votes`: Initially an empty list. New votes are appended as they come in from the nodes.
has they vote on the block
## The Vote Model ## The Vote Model
This is the structure that each node will append to the block `votes` list. Each node must generate a vote for each block, to be appended to that block's `votes` list. A vote has the following structure:
```json ```json
{ {
@ -91,6 +86,8 @@ This is the structure that each node will append to the block `votes` list.
"invalid_reason": "<None|DOUBLE_SPEND|TRANSACTIONS_HASH_MISMATCH|NODES_PUBKEYS_MISMATCH", "invalid_reason": "<None|DOUBLE_SPEND|TRANSACTIONS_HASH_MISMATCH|NODES_PUBKEYS_MISMATCH",
"timestamp": "<timestamp of the voting action>" "timestamp": "<timestamp of the voting action>"
}, },
"signature": "<ECDSA signature of vote block>" "signature": "<signature of vote block>"
} }
``` ```
Note: The `invalid_reason` was not being used as of v0.1.3.

View File

@ -21,6 +21,7 @@ from bigchaindb.block import Block
def test_remove_unclosed_sockets(): def test_remove_unclosed_sockets():
pass pass
class TestBigchainApi(object): class TestBigchainApi(object):
def test_create_transaction(self, b): def test_create_transaction(self, b):
@ -34,7 +35,6 @@ class TestBigchainApi(object):
with pytest.raises(TypeError): with pytest.raises(TypeError):
b.create_transaction('a', 'b', 'c', 'd', payload=[]) b.create_transaction('a', 'b', 'c', 'd', payload=[])
def test_transaction_hash(self, b): def test_transaction_hash(self, b):
payload = {'cats': 'are awesome'} payload = {'cats': 'are awesome'}
tx = b.create_transaction('a', 'b', 'c', 'd', payload) tx = b.create_transaction('a', 'b', 'c', 'd', payload)
@ -142,8 +142,8 @@ class TestBigchainApi(object):
b.create_genesis_block() b.create_genesis_block()
genesis_blocks = list(r.table('bigchain') genesis_blocks = list(r.table('bigchain')
.filter(r.row['block_number'] == 0) .filter(r.row['block_number'] == 0)
.run(b.conn)) .run(b.conn))
assert len(genesis_blocks) == 1 assert len(genesis_blocks) == 1
@ -325,6 +325,24 @@ class TestTransactionValidation(object):
assert tx_valid_signed == b.validate_transaction(tx_valid_signed) assert tx_valid_signed == b.validate_transaction(tx_valid_signed)
assert tx_valid_signed == b.is_valid_transaction(tx_valid_signed) assert tx_valid_signed == b.is_valid_transaction(tx_valid_signed)
@pytest.mark.usefixtures('inputs')
def test_valid_non_create_transaction_after_block_creation(self, b, user_public_key, user_private_key):
input_valid = b.get_owned_ids(user_public_key).pop()
tx_valid = b.create_transaction(user_public_key, 'b', input_valid, 'd')
tx_valid_signed = b.sign_transaction(tx_valid, user_private_key)
assert tx_valid_signed == b.validate_transaction(tx_valid_signed)
assert tx_valid_signed == b.is_valid_transaction(tx_valid_signed)
# create block
block = b.create_block([tx_valid_signed])
assert b.is_valid_block(block)
b.write_block(block, durability='hard')
# check that the transaction is still valid after being written to the bigchain
assert tx_valid_signed == b.validate_transaction(tx_valid_signed)
assert tx_valid_signed == b.is_valid_transaction(tx_valid_signed)
class TestBlockValidation(object): class TestBlockValidation(object):
@ -333,7 +351,7 @@ class TestBlockValidation(object):
# change block hash # change block hash
block.update({'id': 'abc'}) block.update({'id': 'abc'})
with pytest.raises(exceptions.InvalidHash) as excinfo: with pytest.raises(exceptions.InvalidHash):
b.validate_block(block) b.validate_block(block)
@pytest.mark.skipif(reason='Separated tx validation from block creation.') @pytest.mark.skipif(reason='Separated tx validation from block creation.')
@ -344,7 +362,6 @@ class TestBlockValidation(object):
tx_invalid = b.create_transaction('a', 'b', valid_input, 'c') tx_invalid = b.create_transaction('a', 'b', valid_input, 'c')
block = b.create_block([tx_invalid]) block = b.create_block([tx_invalid])
assert invalid_transactions == [tx_invalid]
# create a block with invalid transactions # create a block with invalid transactions
block = { block = {
@ -496,7 +513,6 @@ class TestBigchainVoter(object):
time.sleep(1) time.sleep(1)
voter.kill() voter.kill()
# retrive block from bigchain # retrive block from bigchain
bigchain_block = r.table('bigchain').get(block['id']).run(b.conn) bigchain_block = r.table('bigchain').get(block['id']).run(b.conn)
@ -741,4 +757,3 @@ class TestBigchainBlock(object):
def test_duplicated_transactions(self): def test_duplicated_transactions(self):
pytest.skip('We may have duplicates in the initial_results and changefeed') pytest.skip('We may have duplicates in the initial_results and changefeed')

View File

@ -5,6 +5,7 @@ import multiprocessing as mp
from bigchaindb import Bigchain from bigchaindb import Bigchain
from bigchaindb import util from bigchaindb import util
from bigchaindb.voter import Voter, BlockStream from bigchaindb.voter import Voter, BlockStream
from bigchaindb.crypto import PublicKey from bigchaindb.crypto import PublicKey
@ -36,6 +37,47 @@ class TestBigchainVoter(object):
.order_by(r.asc((r.row['block']['timestamp']))) .order_by(r.asc((r.row['block']['timestamp'])))
.run(b.conn)) .run(b.conn))
# validate vote
assert len(blocks[1]['votes']) == 1
vote = blocks[1]['votes'][0]
assert vote['vote']['voting_for_block'] == block['id']
assert vote['vote']['previous_block'] == genesis['id']
assert vote['vote']['is_block_valid'] is True
assert vote['vote']['invalid_reason'] is None
assert vote['node_pubkey'] == b.me
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_valid_block_voting_with_create_transaction(self, b):
q_new_block = mp.Queue()
genesis = b.create_genesis_block()
# create a `CREATE` transaction
test_user_priv, test_user_pub = b.generate_keys()
tx = b.create_transaction(b.me, test_user_pub, None, 'CREATE')
tx_signed = b.sign_transaction(tx, b.me_private)
assert b.is_valid_transaction(tx_signed)
# create valid block
block = b.create_block([tx_signed])
# assert block is valid
assert b.is_valid_block(block)
b.write_block(block, durability='hard')
# create queue and voter
voter = Voter(q_new_block)
# vote
voter.start()
# wait for vote to be written
time.sleep(1)
voter.kill()
# retrive block from bigchain
blocks = list(r.table('bigchain')
.order_by(r.asc((r.row['block']['timestamp'])))
.run(b.conn))
# validate vote # validate vote
assert len(blocks[1]['votes']) == 1 assert len(blocks[1]['votes']) == 1
@ -48,6 +90,76 @@ class TestBigchainVoter(object):
assert vote['node_pubkey'] == b.me assert vote['node_pubkey'] == b.me
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_valid_block_voting_with_transfer_transactions(self, b):
q_new_block = mp.Queue()
b.create_genesis_block()
# create a `CREATE` transaction
test_user_priv, test_user_pub = b.generate_keys()
tx = b.create_transaction(b.me, test_user_pub, None, 'CREATE')
tx_signed = b.sign_transaction(tx, b.me_private)
assert b.is_valid_transaction(tx_signed)
# create valid block
block = b.create_block([tx_signed])
# assert block is valid
assert b.is_valid_block(block)
b.write_block(block, durability='hard')
# create queue and voter
voter = Voter(q_new_block)
# vote
voter.start()
# wait for vote to be written
time.sleep(1)
voter.kill()
# retrive block from bigchain
blocks = list(r.table('bigchain')
.order_by(r.asc((r.row['block']['timestamp'])))
.run(b.conn))
# validate vote
assert len(blocks[1]['votes']) == 1
# create a `TRANSFER` transaction
test_user2_priv, test_user2_pub = b.generate_keys()
tx2 = b.create_transaction(test_user_pub, test_user2_pub, tx['id'], 'TRANSFER')
tx2_signed = b.sign_transaction(tx2, test_user_priv)
assert b.is_valid_transaction(tx2_signed)
# create valid block
block = b.create_block([tx2_signed])
# assert block is valid
assert b.is_valid_block(block)
b.write_block(block, durability='hard')
# create queue and voter
voter = Voter(q_new_block)
# vote
voter.start()
# wait for vote to be written
time.sleep(1)
voter.kill()
# retrive block from bigchain
blocks = list(r.table('bigchain')
.order_by(r.asc((r.row['block']['timestamp'])))
.run(b.conn))
# validate vote
assert len(blocks[2]['votes']) == 1
vote = blocks[2]['votes'][0]
assert vote['vote']['voting_for_block'] == block['id']
assert vote['vote']['is_block_valid'] is True
assert vote['vote']['invalid_reason'] is None
assert vote['node_pubkey'] == b.me
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_invalid_block_voting(self, b, user_public_key): def test_invalid_block_voting(self, b, user_public_key):
# create queue and voter # create queue and voter
@ -67,7 +179,6 @@ class TestBigchainVoter(object):
assert not b.is_valid_block(block) assert not b.is_valid_block(block)
b.write_block(block, durability='hard') b.write_block(block, durability='hard')
# vote # vote
voter.start() voter.start()
time.sleep(1) time.sleep(1)
@ -168,7 +279,6 @@ class TestBigchainVoter(object):
time.sleep(1) time.sleep(1)
voter.kill() voter.kill()
# retrive blocks from bigchain # retrive blocks from bigchain
blocks = list(r.table('bigchain') blocks = list(r.table('bigchain')
.order_by(r.asc((r.row['block']['timestamp']))) .order_by(r.asc((r.row['block']['timestamp'])))
@ -188,7 +298,6 @@ class TestBigchainVoter(object):
pass pass
class TestBlockStream(object): class TestBlockStream(object):
def test_if_federation_size_is_greater_than_one_ignore_past_blocks(self, b): def test_if_federation_size_is_greater_than_one_ignore_past_blocks(self, b):
@ -220,7 +329,6 @@ class TestBlockStream(object):
assert bs.get() == block_1 assert bs.get() == block_1
assert bs.get() == block_2 assert bs.get() == block_2
def test_if_old_blocks_get_should_return_old_block_first(self, b): def test_if_old_blocks_get_should_return_old_block_first(self, b):
# create two blocks # create two blocks
block_1 = b.create_block([]) block_1 = b.create_block([])

View File

@ -17,11 +17,6 @@ def cleanup_tables(request, node_config):
conftest.cleanup_tables(request, node_config) conftest.cleanup_tables(request, node_config)
@pytest.fixture
def b():
return conftest.b()
@pytest.fixture @pytest.fixture
def app(request, node_config): def app(request, node_config):
# XXX: For whatever reason this fixture runs before `restore_config`, # XXX: For whatever reason this fixture runs before `restore_config`,