mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
*Problem: Merge conflict from #2342
Solution: Merge changes into Master
This commit is contained in:
commit
c6b10114b1
@ -59,6 +59,10 @@ config = {
|
|||||||
'advertised_host': 'localhost',
|
'advertised_host': 'localhost',
|
||||||
'advertised_port': 9985,
|
'advertised_port': 9985,
|
||||||
},
|
},
|
||||||
|
'tendermint': {
|
||||||
|
'host': 'localhost',
|
||||||
|
'port': 46657,
|
||||||
|
},
|
||||||
# FIXME: hardcoding to localmongodb for now
|
# FIXME: hardcoding to localmongodb for now
|
||||||
'database': _database_map['localmongodb'],
|
'database': _database_map['localmongodb'],
|
||||||
'log': {
|
'log': {
|
||||||
|
|||||||
@ -21,7 +21,6 @@ from bigchaindb.commands import utils
|
|||||||
from bigchaindb.commands.utils import (configure_bigchaindb,
|
from bigchaindb.commands.utils import (configure_bigchaindb,
|
||||||
input_on_stderr)
|
input_on_stderr)
|
||||||
from bigchaindb.log import setup_logging
|
from bigchaindb.log import setup_logging
|
||||||
from bigchaindb.tendermint.lib import BigchainDB
|
|
||||||
from bigchaindb.tendermint.utils import public_key_from_base64
|
from bigchaindb.tendermint.utils import public_key_from_base64
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
@ -82,6 +81,10 @@ def run_configure(args):
|
|||||||
val = conf['database'][key]
|
val = conf['database'][key]
|
||||||
conf['database'][key] = input_on_stderr('Database {}? (default `{}`): '.format(key, val), val)
|
conf['database'][key] = input_on_stderr('Database {}? (default `{}`): '.format(key, val), val)
|
||||||
|
|
||||||
|
for key in ('host', 'port'):
|
||||||
|
val = conf['tendermint'][key]
|
||||||
|
conf['tendermint'][key] = input_on_stderr('Tendermint {}? (default `{}`)'.format(key, val), val)
|
||||||
|
|
||||||
if config_path != '-':
|
if config_path != '-':
|
||||||
bigchaindb.config_utils.write_config(conf, config_path)
|
bigchaindb.config_utils.write_config(conf, config_path)
|
||||||
else:
|
else:
|
||||||
@ -167,7 +170,7 @@ def run_start(args):
|
|||||||
setup_logging()
|
setup_logging()
|
||||||
|
|
||||||
logger.info('BigchainDB Version %s', bigchaindb.__version__)
|
logger.info('BigchainDB Version %s', bigchaindb.__version__)
|
||||||
run_recover(BigchainDB())
|
run_recover(bigchaindb.tendermint.lib.BigchainDB())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not args.skip_initialize_database:
|
if not args.skip_initialize_database:
|
||||||
|
|||||||
@ -248,10 +248,8 @@ def autoconfigure(filename=None, config=None, force=False):
|
|||||||
|
|
||||||
# override configuration with env variables
|
# override configuration with env variables
|
||||||
newconfig = env_config(newconfig)
|
newconfig = env_config(newconfig)
|
||||||
|
|
||||||
if config:
|
if config:
|
||||||
newconfig = update(newconfig, config)
|
newconfig = update(newconfig, config)
|
||||||
|
|
||||||
set_config(newconfig) # sets bigchaindb.config
|
set_config(newconfig) # sets bigchaindb.config
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
bigchaindb/core.py
Normal file
0
bigchaindb/core.py
Normal file
@ -1,60 +0,0 @@
|
|||||||
from bigchaindb.utils import condition_details_has_owner
|
|
||||||
from bigchaindb.backend import query
|
|
||||||
from bigchaindb.common.transaction import TransactionLink
|
|
||||||
|
|
||||||
|
|
||||||
class FastQuery:
|
|
||||||
"""Database queries that join on block results from a single node.
|
|
||||||
|
|
||||||
* Votes are not validated for security (security is a replication concern)
|
|
||||||
* Votes come from only one node, and as such, non-byzantine fault tolerance
|
|
||||||
is reduced.
|
|
||||||
|
|
||||||
Previously, to consider the status of a block, all votes for that block
|
|
||||||
were retrieved and the election results were counted. This meant that a
|
|
||||||
faulty node may still have been able to obtain a correct election result.
|
|
||||||
However, from the point of view of a client, it is still neccesary to
|
|
||||||
query multiple nodes to insure against getting an incorrect response from
|
|
||||||
a byzantine node.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, connection):
|
|
||||||
self.connection = connection
|
|
||||||
|
|
||||||
def get_outputs_by_public_key(self, public_key):
|
|
||||||
"""Get outputs for a public key"""
|
|
||||||
res = list(query.get_owned_ids(self.connection, public_key))
|
|
||||||
txs = [tx for _, tx in self.filter_valid_items(res)]
|
|
||||||
return [TransactionLink(tx['id'], index)
|
|
||||||
for tx in txs
|
|
||||||
for index, output in enumerate(tx['outputs'])
|
|
||||||
if condition_details_has_owner(output['condition']['details'],
|
|
||||||
public_key)]
|
|
||||||
|
|
||||||
def filter_spent_outputs(self, outputs):
|
|
||||||
"""Remove outputs that have been spent
|
|
||||||
|
|
||||||
Args:
|
|
||||||
outputs: list of TransactionLink
|
|
||||||
"""
|
|
||||||
links = [o.to_dict() for o in outputs]
|
|
||||||
res = query.get_spending_transactions(self.connection, links)
|
|
||||||
txs = [tx for _, tx in self.filter_valid_items(res)]
|
|
||||||
spends = {TransactionLink.from_dict(input_['fulfills'])
|
|
||||||
for tx in txs
|
|
||||||
for input_ in tx['inputs']}
|
|
||||||
return [ff for ff in outputs if ff not in spends]
|
|
||||||
|
|
||||||
def filter_unspent_outputs(self, outputs):
|
|
||||||
"""Remove outputs that have not been spent
|
|
||||||
|
|
||||||
Args:
|
|
||||||
outputs: list of TransactionLink
|
|
||||||
"""
|
|
||||||
links = [o.to_dict() for o in outputs]
|
|
||||||
res = query.get_spending_transactions(self.connection, links)
|
|
||||||
txs = [tx for _, tx in self.filter_valid_items(res)]
|
|
||||||
spends = {TransactionLink.from_dict(input_['fulfills'])
|
|
||||||
for tx in txs
|
|
||||||
for input_ in tx['inputs']}
|
|
||||||
return [ff for ff in outputs if ff in spends]
|
|
||||||
@ -2,17 +2,17 @@ import asyncio
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from os import getenv
|
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
|
from bigchaindb import config
|
||||||
from bigchaindb.common.utils import gen_timestamp
|
from bigchaindb.common.utils import gen_timestamp
|
||||||
from bigchaindb.events import EventTypes, Event
|
from bigchaindb.events import EventTypes, Event
|
||||||
from bigchaindb.tendermint.utils import decode_transaction_base64
|
from bigchaindb.tendermint.utils import decode_transaction_base64
|
||||||
|
|
||||||
|
|
||||||
HOST = getenv('BIGCHAINDB_TENDERMINT_HOST', 'localhost')
|
HOST = config['tendermint']['host']
|
||||||
PORT = int(getenv('BIGCHAINDB_TENDERMINT_PORT', 46657))
|
PORT = config['tendermint']['port']
|
||||||
URL = 'ws://{}:{}/websocket'.format(HOST, PORT)
|
URL = 'ws://{}:{}/websocket'.format(HOST, PORT)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@ -3,5 +3,3 @@ The BigchainDB Class
|
|||||||
####################
|
####################
|
||||||
|
|
||||||
.. autoclass:: bigchaindb.tendermint.BigchainDB
|
.. autoclass:: bigchaindb.tendermint.BigchainDB
|
||||||
|
|
||||||
.. automethod:: bigchaindb.tendermint.lib.BigchainDB.__init__
|
|
||||||
|
|||||||
@ -33,6 +33,8 @@ For convenience, here's a list of all the relevant environment variables (docume
|
|||||||
`BIGCHAINDB_LOG_DATEFMT_LOGFILE`<br>
|
`BIGCHAINDB_LOG_DATEFMT_LOGFILE`<br>
|
||||||
`BIGCHAINDB_LOG_FMT_CONSOLE`<br>
|
`BIGCHAINDB_LOG_FMT_CONSOLE`<br>
|
||||||
`BIGCHAINDB_LOG_FMT_LOGFILE`<br>
|
`BIGCHAINDB_LOG_FMT_LOGFILE`<br>
|
||||||
|
`BIGCHAINDB_TENDERMINT_HOST`<br>
|
||||||
|
`BIGCHAINDB_TENDERMINT_PORT`<br>
|
||||||
|
|
||||||
|
|
||||||
The local config file is `$HOME/.bigchaindb` by default (a file which might not even exist), but you can tell BigchainDB to use a different file by using the `-c` command-line option, e.g. `bigchaindb -c path/to/config_file.json start`
|
The local config file is `$HOME/.bigchaindb` by default (a file which might not even exist), but you can tell BigchainDB to use a different file by using the `-c` command-line option, e.g. `bigchaindb -c path/to/config_file.json start`
|
||||||
@ -426,3 +428,26 @@ logging of the `core.py` module to be more verbose, you would set the
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Defaults to**: `{}`
|
**Defaults to**: `{}`
|
||||||
|
|
||||||
|
## tendermint.host & tendermint.port
|
||||||
|
|
||||||
|
The settings with names of the form `tendermint.*` are for
|
||||||
|
consensus(Tendermint) backend that we are using:
|
||||||
|
|
||||||
|
* `tendermint.host` is the hostname (FQDN)/IP address of the tendermint backend.
|
||||||
|
* `tendermint.port` is self-explanatory.
|
||||||
|
|
||||||
|
**Example using environment variables**
|
||||||
|
```text
|
||||||
|
export BIGCHAINDB_TENDERMINT_HOST=tendermint
|
||||||
|
export BIGCHAINDB_TENDERMINT_PORT=46657
|
||||||
|
```
|
||||||
|
|
||||||
|
**Default values**
|
||||||
|
|
||||||
|
```js
|
||||||
|
"tendermint": {
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 46657,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@ -107,6 +107,10 @@ def _configure_bigchaindb(request):
|
|||||||
|
|
||||||
config = {
|
config = {
|
||||||
'database': bigchaindb._database_map[backend],
|
'database': bigchaindb._database_map[backend],
|
||||||
|
'tendermint': {
|
||||||
|
'host': 'localhost',
|
||||||
|
'port': 46657,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
config['database']['name'] = test_db_name
|
config['database']['name'] = test_db_name
|
||||||
config = config_utils.env_config(config)
|
config = config_utils.env_config(config)
|
||||||
|
|||||||
@ -978,38 +978,48 @@ def test_get_owned_ids_calls_get_outputs_filtered():
|
|||||||
assert res == gof()
|
assert res == gof()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.tendermint
|
||||||
def test_get_outputs_filtered_only_unspent():
|
def test_get_outputs_filtered_only_unspent():
|
||||||
from bigchaindb.common.transaction import TransactionLink
|
from bigchaindb.common.transaction import TransactionLink
|
||||||
from bigchaindb.tendermint import BigchainDB
|
from bigchaindb.tendermint.lib import BigchainDB
|
||||||
with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs:
|
|
||||||
|
go = 'bigchaindb.tendermint.fastquery.FastQuery.get_outputs_by_public_key'
|
||||||
|
with patch(go) as get_outputs:
|
||||||
get_outputs.return_value = [TransactionLink('a', 1),
|
get_outputs.return_value = [TransactionLink('a', 1),
|
||||||
TransactionLink('b', 2)]
|
TransactionLink('b', 2)]
|
||||||
with patch('bigchaindb.fastquery.FastQuery.filter_spent_outputs') as filter_spent:
|
fs = 'bigchaindb.tendermint.fastquery.FastQuery.filter_spent_outputs'
|
||||||
|
with patch(fs) as filter_spent:
|
||||||
filter_spent.return_value = [TransactionLink('b', 2)]
|
filter_spent.return_value = [TransactionLink('b', 2)]
|
||||||
out = BigchainDB().get_outputs_filtered('abc', spent=False)
|
out = BigchainDB().get_outputs_filtered('abc', spent=False)
|
||||||
get_outputs.assert_called_once_with('abc')
|
get_outputs.assert_called_once_with('abc')
|
||||||
assert out == [TransactionLink('b', 2)]
|
assert out == [TransactionLink('b', 2)]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.tendermint
|
||||||
def test_get_outputs_filtered_only_spent():
|
def test_get_outputs_filtered_only_spent():
|
||||||
from bigchaindb.common.transaction import TransactionLink
|
from bigchaindb.common.transaction import TransactionLink
|
||||||
from bigchaindb.tendermint import BigchainDB
|
from bigchaindb.tendermint.lib import BigchainDB
|
||||||
with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs:
|
go = 'bigchaindb.tendermint.fastquery.FastQuery.get_outputs_by_public_key'
|
||||||
|
with patch(go) as get_outputs:
|
||||||
get_outputs.return_value = [TransactionLink('a', 1),
|
get_outputs.return_value = [TransactionLink('a', 1),
|
||||||
TransactionLink('b', 2)]
|
TransactionLink('b', 2)]
|
||||||
with patch('bigchaindb.fastquery.FastQuery.filter_unspent_outputs') as filter_spent:
|
fs = 'bigchaindb.tendermint.fastquery.FastQuery.filter_unspent_outputs'
|
||||||
|
with patch(fs) as filter_spent:
|
||||||
filter_spent.return_value = [TransactionLink('b', 2)]
|
filter_spent.return_value = [TransactionLink('b', 2)]
|
||||||
out = BigchainDB().get_outputs_filtered('abc', spent=True)
|
out = BigchainDB().get_outputs_filtered('abc', spent=True)
|
||||||
get_outputs.assert_called_once_with('abc')
|
get_outputs.assert_called_once_with('abc')
|
||||||
assert out == [TransactionLink('b', 2)]
|
assert out == [TransactionLink('b', 2)]
|
||||||
|
|
||||||
|
|
||||||
@patch('bigchaindb.fastquery.FastQuery.filter_unspent_outputs')
|
@pytest.mark.tendermint
|
||||||
@patch('bigchaindb.fastquery.FastQuery.filter_spent_outputs')
|
@patch('bigchaindb.tendermint.fastquery.FastQuery.filter_unspent_outputs')
|
||||||
|
@patch('bigchaindb.tendermint.fastquery.FastQuery.filter_spent_outputs')
|
||||||
def test_get_outputs_filtered(filter_spent, filter_unspent):
|
def test_get_outputs_filtered(filter_spent, filter_unspent):
|
||||||
from bigchaindb.common.transaction import TransactionLink
|
from bigchaindb.common.transaction import TransactionLink
|
||||||
from bigchaindb.tendermint import BigchainDB
|
from bigchaindb.tendermint.lib import BigchainDB
|
||||||
with patch('bigchaindb.fastquery.FastQuery.get_outputs_by_public_key') as get_outputs:
|
|
||||||
|
go = 'bigchaindb.tendermint.fastquery.FastQuery.get_outputs_by_public_key'
|
||||||
|
with patch(go) as get_outputs:
|
||||||
get_outputs.return_value = [TransactionLink('a', 1),
|
get_outputs.return_value = [TransactionLink('a', 1),
|
||||||
TransactionLink('b', 2)]
|
TransactionLink('b', 2)]
|
||||||
out = BigchainDB().get_outputs_filtered('abc')
|
out = BigchainDB().get_outputs_filtered('abc')
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import pytest
|
|||||||
from bigchaindb.common.transaction import TransactionLink
|
from bigchaindb.common.transaction import TransactionLink
|
||||||
from bigchaindb.models import Transaction
|
from bigchaindb.models import Transaction
|
||||||
|
|
||||||
|
|
||||||
pytestmark = [pytest.mark.bdb, pytest.mark.tendermint]
|
pytestmark = [pytest.mark.bdb, pytest.mark.tendermint]
|
||||||
|
|
||||||
|
|
||||||
@ -25,3 +26,46 @@ def test_get_outputs_by_public_key(b, user_pk, user2_pk, txns):
|
|||||||
TransactionLink(txns[0].id, 0),
|
TransactionLink(txns[0].id, 0),
|
||||||
TransactionLink(txns[2].id, 1),
|
TransactionLink(txns[2].id, 1),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_filter_spent_outputs(b, user_pk, user_sk):
|
||||||
|
out = [([user_pk], 1)]
|
||||||
|
tx1 = Transaction.create([user_pk], out * 2)
|
||||||
|
tx1.sign([user_sk])
|
||||||
|
|
||||||
|
inputs = tx1.to_inputs()
|
||||||
|
|
||||||
|
tx2 = Transaction.transfer([inputs[0]], out, tx1.id)
|
||||||
|
tx2.sign([user_sk])
|
||||||
|
|
||||||
|
# tx2 produces a new unspent. inputs[1] remains unspent.
|
||||||
|
b.store_bulk_transactions([tx1, tx2])
|
||||||
|
|
||||||
|
outputs = b.fastquery.get_outputs_by_public_key(user_pk)
|
||||||
|
unspents = b.fastquery.filter_spent_outputs(outputs)
|
||||||
|
|
||||||
|
assert set(unsp for unsp in unspents) == {
|
||||||
|
inputs[1].fulfills,
|
||||||
|
tx2.to_inputs()[0].fulfills,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_filter_unspent_outputs(b, user_pk, user_sk):
|
||||||
|
out = [([user_pk], 1)]
|
||||||
|
tx1 = Transaction.create([user_pk], out * 2)
|
||||||
|
tx1.sign([user_sk])
|
||||||
|
|
||||||
|
inputs = tx1.to_inputs()
|
||||||
|
|
||||||
|
tx2 = Transaction.transfer([inputs[0]], out, tx1.id)
|
||||||
|
tx2.sign([user_sk])
|
||||||
|
|
||||||
|
# tx2 produces a new unspent. input[1] remains unspent.
|
||||||
|
b.store_bulk_transactions([tx1, tx2])
|
||||||
|
|
||||||
|
outputs = b.fastquery.get_outputs_by_public_key(user_pk)
|
||||||
|
spents = b.fastquery.filter_unspent_outputs(outputs)
|
||||||
|
|
||||||
|
assert set(sp for sp in spents) == {
|
||||||
|
inputs[0].fulfills,
|
||||||
|
}
|
||||||
|
|||||||
@ -1,21 +0,0 @@
|
|||||||
import pytest
|
|
||||||
|
|
||||||
from bigchaindb.common.transaction import TransactionLink
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.bdb
|
|
||||||
|
|
||||||
|
|
||||||
def test_filter_valid_items(b, blockdata):
|
|
||||||
blocks, _ = blockdata
|
|
||||||
assert (b.fastquery.filter_valid_items(blocks, block_id_key=lambda b: b['id'])
|
|
||||||
== [blocks[0], blocks[1]])
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_outputs_by_public_key(b, user_pk, user2_pk, blockdata):
|
|
||||||
blocks, _ = blockdata
|
|
||||||
assert b.fastquery.get_outputs_by_public_key(user_pk) == [
|
|
||||||
TransactionLink(blocks[1]['block']['transactions'][0]['id'], 0)
|
|
||||||
]
|
|
||||||
assert b.fastquery.get_outputs_by_public_key(user2_pk) == [
|
|
||||||
TransactionLink(blocks[0]['block']['transactions'][0]['id'], 0)
|
|
||||||
]
|
|
||||||
Loading…
x
Reference in New Issue
Block a user