mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Move common code to util module
This commit is contained in:
parent
6614f7a102
commit
b3b54e7529
@ -1,12 +1,11 @@
|
|||||||
import rethinkdb as r
|
import rethinkdb as r
|
||||||
import time
|
|
||||||
import random
|
import random
|
||||||
import json
|
import json
|
||||||
import rapidjson
|
import rapidjson
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import bigchaindb
|
import bigchaindb
|
||||||
|
from bigchaindb import util
|
||||||
from bigchaindb import config_utils
|
from bigchaindb import config_utils
|
||||||
from bigchaindb import exceptions
|
from bigchaindb import exceptions
|
||||||
from bigchaindb.crypto import hash_data, PublicKey, PrivateKey, generate_key_pair
|
from bigchaindb.crypto import hash_data, PublicKey, PrivateKey, generate_key_pair
|
||||||
@ -16,10 +15,6 @@ class GenesisBlockAlreadyExistsError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class KeypairNotFoundException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Bigchain(object):
|
class Bigchain(object):
|
||||||
"""Bigchain API
|
"""Bigchain API
|
||||||
|
|
||||||
@ -55,7 +50,7 @@ class Bigchain(object):
|
|||||||
self.federation_nodes = keyring or bigchaindb.config['keyring']
|
self.federation_nodes = keyring or bigchaindb.config['keyring']
|
||||||
|
|
||||||
if not self.me or not self.me_private:
|
if not self.me or not self.me_private:
|
||||||
raise KeypairNotFoundException()
|
raise exceptions.KeypairNotFoundException()
|
||||||
|
|
||||||
self._conn = None
|
self._conn = None
|
||||||
|
|
||||||
@ -100,7 +95,7 @@ class Bigchain(object):
|
|||||||
data = None
|
data = None
|
||||||
if payload is not None:
|
if payload is not None:
|
||||||
if isinstance(payload, dict):
|
if isinstance(payload, dict):
|
||||||
hash_payload = hash_data(self.serialize(payload))
|
hash_payload = hash_data(util.serialize(payload))
|
||||||
data = {
|
data = {
|
||||||
'hash': hash_payload,
|
'hash': hash_payload,
|
||||||
'payload': payload
|
'payload': payload
|
||||||
@ -108,7 +103,7 @@ class Bigchain(object):
|
|||||||
else:
|
else:
|
||||||
raise TypeError('`payload` must be an dict instance')
|
raise TypeError('`payload` must be an dict instance')
|
||||||
|
|
||||||
hash_payload = hash_data(self.serialize(payload))
|
hash_payload = hash_data(util.serialize(payload))
|
||||||
data = {
|
data = {
|
||||||
'hash': hash_payload,
|
'hash': hash_payload,
|
||||||
'payload': payload
|
'payload': payload
|
||||||
@ -119,12 +114,12 @@ class Bigchain(object):
|
|||||||
'new_owner': new_owner,
|
'new_owner': new_owner,
|
||||||
'input': tx_input,
|
'input': tx_input,
|
||||||
'operation': operation,
|
'operation': operation,
|
||||||
'timestamp': self.timestamp(),
|
'timestamp': util.timestamp(),
|
||||||
'data': data
|
'data': data
|
||||||
}
|
}
|
||||||
|
|
||||||
# serialize and convert to bytes
|
# serialize and convert to bytes
|
||||||
tx_serialized = self.serialize(tx)
|
tx_serialized = util.serialize(tx)
|
||||||
tx_hash = hash_data(tx_serialized)
|
tx_hash = hash_data(tx_serialized)
|
||||||
|
|
||||||
# create the transaction
|
# create the transaction
|
||||||
@ -149,7 +144,7 @@ class Bigchain(object):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
private_key = PrivateKey(private_key)
|
private_key = PrivateKey(private_key)
|
||||||
signature = private_key.sign(self.serialize(transaction))
|
signature = private_key.sign(util.serialize(transaction))
|
||||||
signed_transaction = transaction.copy()
|
signed_transaction = transaction.copy()
|
||||||
signed_transaction.update({'signature': signature})
|
signed_transaction.update({'signature': signature})
|
||||||
return signed_transaction
|
return signed_transaction
|
||||||
@ -175,7 +170,7 @@ class Bigchain(object):
|
|||||||
signature = data.pop('signature')
|
signature = data.pop('signature')
|
||||||
public_key_base58 = signed_transaction['transaction']['current_owner']
|
public_key_base58 = signed_transaction['transaction']['current_owner']
|
||||||
public_key = PublicKey(public_key_base58)
|
public_key = PublicKey(public_key_base58)
|
||||||
return public_key.verify(self.serialize(data), signature)
|
return public_key.verify(util.serialize(data), signature)
|
||||||
|
|
||||||
def write_transaction(self, signed_transaction):
|
def write_transaction(self, signed_transaction):
|
||||||
"""Write the transaction to bigchain.
|
"""Write the transaction to bigchain.
|
||||||
@ -360,7 +355,7 @@ class Bigchain(object):
|
|||||||
transaction['transaction']['input']))
|
transaction['transaction']['input']))
|
||||||
|
|
||||||
# Check hash of the transaction
|
# Check hash of the transaction
|
||||||
calculated_hash = hash_data(self.serialize(transaction['transaction']))
|
calculated_hash = hash_data(util.serialize(transaction['transaction']))
|
||||||
if calculated_hash != transaction['id']:
|
if calculated_hash != transaction['id']:
|
||||||
raise exceptions.InvalidHash()
|
raise exceptions.InvalidHash()
|
||||||
|
|
||||||
@ -405,14 +400,14 @@ class Bigchain(object):
|
|||||||
"""
|
"""
|
||||||
# Create the new block
|
# Create the new block
|
||||||
block = {
|
block = {
|
||||||
'timestamp': self.timestamp(),
|
'timestamp': util.timestamp(),
|
||||||
'transactions': validated_transactions,
|
'transactions': validated_transactions,
|
||||||
'node_pubkey': self.me,
|
'node_pubkey': self.me,
|
||||||
'voters': self.federation_nodes + [self.me]
|
'voters': self.federation_nodes + [self.me]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Calculate the hash of the new block
|
# Calculate the hash of the new block
|
||||||
block_data = self.serialize(block)
|
block_data = util.serialize(block)
|
||||||
block_hash = hash_data(block_data)
|
block_hash = hash_data(block_data)
|
||||||
block_signature = PrivateKey(self.me_private).sign(block_data)
|
block_signature = PrivateKey(self.me_private).sign(block_data)
|
||||||
|
|
||||||
@ -439,7 +434,7 @@ class Bigchain(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# 1. Check if current hash is correct
|
# 1. Check if current hash is correct
|
||||||
calculated_hash = hash_data(self.serialize(block['block']))
|
calculated_hash = hash_data(util.serialize(block['block']))
|
||||||
if calculated_hash != block['id']:
|
if calculated_hash != block['id']:
|
||||||
raise exceptions.InvalidHash()
|
raise exceptions.InvalidHash()
|
||||||
|
|
||||||
@ -531,10 +526,10 @@ class Bigchain(object):
|
|||||||
'previous_block': previous_block_id,
|
'previous_block': previous_block_id,
|
||||||
'is_block_valid': decision,
|
'is_block_valid': decision,
|
||||||
'invalid_reason': invalid_reason,
|
'invalid_reason': invalid_reason,
|
||||||
'timestamp': self.timestamp()
|
'timestamp': util.timestamp()
|
||||||
}
|
}
|
||||||
|
|
||||||
vote_data = self.serialize(vote)
|
vote_data = util.serialize(vote)
|
||||||
signature = PrivateKey(self.me_private).sign(vote_data)
|
signature = PrivateKey(self.me_private).sign(vote_data)
|
||||||
|
|
||||||
vote_signed = {
|
vote_signed = {
|
||||||
@ -597,26 +592,6 @@ class Bigchain(object):
|
|||||||
|
|
||||||
return unvoted
|
return unvoted
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def serialize(data):
|
|
||||||
"""Static method used to serialize a dict into a JSON formatted string.
|
|
||||||
|
|
||||||
This method enforces rules like the separator and order of keys. This ensures that all dicts
|
|
||||||
are serialized in the same way.
|
|
||||||
|
|
||||||
This is specially important for hashing data. We need to make sure that everyone serializes their data
|
|
||||||
in the same way so that we do not have hash mismatches for the same structure due to serialization
|
|
||||||
differences.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
data (dict): dict to serialize
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: JSON formatted string
|
|
||||||
|
|
||||||
"""
|
|
||||||
return json.dumps(data, skipkeys=False, ensure_ascii=False,
|
|
||||||
separators=(',', ':'), sort_keys=True)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def deserialize(data):
|
def deserialize(data):
|
||||||
@ -631,17 +606,6 @@ class Bigchain(object):
|
|||||||
"""
|
"""
|
||||||
return json.loads(data, encoding="utf-8")
|
return json.loads(data, encoding="utf-8")
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def timestamp():
|
|
||||||
"""Static method to calculate a UTC timestamp with microsecond precision.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: UTC timestamp.
|
|
||||||
|
|
||||||
"""
|
|
||||||
dt = datetime.utcnow()
|
|
||||||
return "{0:.6f}".format(time.mktime(dt.timetuple()) + dt.microsecond / 1e6)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_keys():
|
def generate_keys():
|
||||||
"""Generates a key pair.
|
"""Generates a key pair.
|
||||||
|
@ -25,3 +25,7 @@ class DatabaseAlreadyExists(Exception):
|
|||||||
class DatabaseDoesNotExist(Exception):
|
class DatabaseDoesNotExist(Exception):
|
||||||
"""Raised when trying to delete the database but the db is not there"""
|
"""Raised when trying to delete the database but the db is not there"""
|
||||||
|
|
||||||
|
class KeypairNotFoundException(Exception):
|
||||||
|
"""Raised if operation cannot proceed because the keypair was not given"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
class ProcessGroup(object):
|
class ProcessGroup(object):
|
||||||
@ -22,3 +25,35 @@ class ProcessGroup(object):
|
|||||||
proc.start()
|
proc.start()
|
||||||
self.processes.append(proc)
|
self.processes.append(proc)
|
||||||
|
|
||||||
|
|
||||||
|
def serialize(data):
|
||||||
|
"""Function used to serialize a dict into a JSON formatted string.
|
||||||
|
|
||||||
|
This function enforces rules like the separator and order of keys. This ensures that all dicts
|
||||||
|
are serialized in the same way.
|
||||||
|
|
||||||
|
This is specially important for hashing data. We need to make sure that everyone serializes their data
|
||||||
|
in the same way so that we do not have hash mismatches for the same structure due to serialization
|
||||||
|
differences.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (dict): dict to serialize
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: JSON formatted string
|
||||||
|
|
||||||
|
"""
|
||||||
|
return json.dumps(data, skipkeys=False, ensure_ascii=False,
|
||||||
|
separators=(',', ':'), sort_keys=True)
|
||||||
|
|
||||||
|
|
||||||
|
def timestamp():
|
||||||
|
"""Function to calculate a UTC timestamp with microsecond precision.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: UTC timestamp.
|
||||||
|
|
||||||
|
"""
|
||||||
|
dt = datetime.utcnow()
|
||||||
|
return "{0:.6f}".format(time.mktime(dt.timetuple()) + dt.microsecond / 1e6)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import pytest
|
|||||||
import rethinkdb as r
|
import rethinkdb as r
|
||||||
|
|
||||||
import bigchaindb
|
import bigchaindb
|
||||||
|
from bigchaindb import util
|
||||||
from bigchaindb import exceptions
|
from bigchaindb import exceptions
|
||||||
from bigchaindb import Bigchain
|
from bigchaindb import Bigchain
|
||||||
from bigchaindb.crypto import hash_data, PrivateKey, PublicKey, generate_key_pair
|
from bigchaindb.crypto import hash_data, PrivateKey, PublicKey, generate_key_pair
|
||||||
@ -69,7 +70,7 @@ class TestBigchainApi(object):
|
|||||||
'operation': 'd',
|
'operation': 'd',
|
||||||
'timestamp': tx['transaction']['timestamp'],
|
'timestamp': tx['transaction']['timestamp'],
|
||||||
'data': {
|
'data': {
|
||||||
'hash': hash_data(b.serialize(payload)),
|
'hash': hash_data(util.serialize(payload)),
|
||||||
'payload': payload
|
'payload': payload
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,7 +87,7 @@ class TestBigchainApi(object):
|
|||||||
|
|
||||||
def test_serializer(self, b):
|
def test_serializer(self, b):
|
||||||
tx = b.create_transaction('a', 'b', 'c', 'd')
|
tx = b.create_transaction('a', 'b', 'c', 'd')
|
||||||
assert b.deserialize(b.serialize(tx)) == tx
|
assert b.deserialize(util.serialize(tx)) == tx
|
||||||
|
|
||||||
@pytest.mark.usefixtures('inputs')
|
@pytest.mark.usefixtures('inputs')
|
||||||
def test_write_transaction(self, b, user_public_key, user_private_key):
|
def test_write_transaction(self, b, user_public_key, user_private_key):
|
||||||
@ -114,7 +115,7 @@ class TestBigchainApi(object):
|
|||||||
b.write_block(block, durability='hard')
|
b.write_block(block, durability='hard')
|
||||||
|
|
||||||
response = b.get_transaction(tx_signed["id"])
|
response = b.get_transaction(tx_signed["id"])
|
||||||
assert b.serialize(tx_signed) == b.serialize(response)
|
assert util.serialize(tx_signed) == util.serialize(response)
|
||||||
|
|
||||||
@pytest.mark.usefixtures('inputs')
|
@pytest.mark.usefixtures('inputs')
|
||||||
def test_assign_transaction_one_node(self, b, user_public_key, user_private_key):
|
def test_assign_transaction_one_node(self, b, user_public_key, user_private_key):
|
||||||
@ -210,11 +211,11 @@ class TestBigchainApi(object):
|
|||||||
|
|
||||||
def test_create_new_block(self, b):
|
def test_create_new_block(self, b):
|
||||||
new_block = b.create_block([])
|
new_block = b.create_block([])
|
||||||
block_hash = hash_data(b.serialize(new_block['block']))
|
block_hash = hash_data(util.serialize(new_block['block']))
|
||||||
|
|
||||||
assert new_block['block']['voters'] == [b.me]
|
assert new_block['block']['voters'] == [b.me]
|
||||||
assert new_block['block']['node_pubkey'] == b.me
|
assert new_block['block']['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(new_block['block']), new_block['signature']) is True
|
assert PublicKey(b.me).verify(util.serialize(new_block['block']), new_block['signature']) is True
|
||||||
assert new_block['id'] == block_hash
|
assert new_block['id'] == block_hash
|
||||||
assert new_block['votes'] == []
|
assert new_block['votes'] == []
|
||||||
|
|
||||||
@ -378,7 +379,7 @@ class TestBlockValidation(object):
|
|||||||
'voters': b.federation_nodes
|
'voters': b.federation_nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
block_data = b.serialize(block)
|
block_data = util.serialize(block)
|
||||||
block_hash = hash_data(block_data)
|
block_hash = hash_data(block_data)
|
||||||
block_signature = PrivateKey(b.me_private).sign(block_data)
|
block_signature = PrivateKey(b.me_private).sign(block_data)
|
||||||
|
|
||||||
@ -491,7 +492,7 @@ class TestBigchainVoter(object):
|
|||||||
assert vote['vote']['is_block_valid'] is True
|
assert vote['vote']['is_block_valid'] is True
|
||||||
assert vote['vote']['invalid_reason'] is None
|
assert vote['vote']['invalid_reason'] is None
|
||||||
assert vote['node_pubkey'] == b.me
|
assert vote['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
|
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
|
||||||
@ -533,7 +534,7 @@ class TestBigchainVoter(object):
|
|||||||
assert vote['vote']['is_block_valid'] is False
|
assert vote['vote']['is_block_valid'] is False
|
||||||
assert vote['vote']['invalid_reason'] is None
|
assert vote['vote']['invalid_reason'] is None
|
||||||
assert vote['node_pubkey'] == b.me
|
assert vote['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
|
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
|
||||||
|
|
||||||
def test_vote_creation_valid(self, b):
|
def test_vote_creation_valid(self, b):
|
||||||
# create valid block
|
# create valid block
|
||||||
@ -547,7 +548,7 @@ class TestBigchainVoter(object):
|
|||||||
assert vote['vote']['is_block_valid'] is True
|
assert vote['vote']['is_block_valid'] is True
|
||||||
assert vote['vote']['invalid_reason'] is None
|
assert vote['vote']['invalid_reason'] is None
|
||||||
assert vote['node_pubkey'] == b.me
|
assert vote['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
|
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
|
||||||
|
|
||||||
def test_vote_creation_invalid(self, b):
|
def test_vote_creation_invalid(self, b):
|
||||||
# create valid block
|
# create valid block
|
||||||
@ -561,7 +562,7 @@ class TestBigchainVoter(object):
|
|||||||
assert vote['vote']['is_block_valid'] is False
|
assert vote['vote']['is_block_valid'] is False
|
||||||
assert vote['vote']['invalid_reason'] is None
|
assert vote['vote']['invalid_reason'] is None
|
||||||
assert vote['node_pubkey'] == b.me
|
assert vote['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
|
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
|
||||||
|
|
||||||
|
|
||||||
class TestBigchainBlock(object):
|
class TestBigchainBlock(object):
|
||||||
|
@ -4,6 +4,7 @@ import rethinkdb as r
|
|||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
|
|
||||||
from bigchaindb import Bigchain
|
from bigchaindb import Bigchain
|
||||||
|
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
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ class TestBigchainVoter(object):
|
|||||||
assert vote['vote']['is_block_valid'] is True
|
assert vote['vote']['is_block_valid'] is True
|
||||||
assert vote['vote']['invalid_reason'] is None
|
assert vote['vote']['invalid_reason'] is None
|
||||||
assert vote['node_pubkey'] == b.me
|
assert vote['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
|
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):
|
||||||
@ -86,7 +87,7 @@ class TestBigchainVoter(object):
|
|||||||
assert vote['vote']['is_block_valid'] is False
|
assert vote['vote']['is_block_valid'] is False
|
||||||
assert vote['vote']['invalid_reason'] is None
|
assert vote['vote']['invalid_reason'] is None
|
||||||
assert vote['node_pubkey'] == b.me
|
assert vote['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
|
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
|
||||||
|
|
||||||
def test_vote_creation_valid(self, b):
|
def test_vote_creation_valid(self, b):
|
||||||
# create valid block
|
# create valid block
|
||||||
@ -100,7 +101,7 @@ class TestBigchainVoter(object):
|
|||||||
assert vote['vote']['is_block_valid'] is True
|
assert vote['vote']['is_block_valid'] is True
|
||||||
assert vote['vote']['invalid_reason'] is None
|
assert vote['vote']['invalid_reason'] is None
|
||||||
assert vote['node_pubkey'] == b.me
|
assert vote['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
|
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
|
||||||
|
|
||||||
def test_vote_creation_invalid(self, b):
|
def test_vote_creation_invalid(self, b):
|
||||||
# create valid block
|
# create valid block
|
||||||
@ -114,7 +115,7 @@ class TestBigchainVoter(object):
|
|||||||
assert vote['vote']['is_block_valid'] is False
|
assert vote['vote']['is_block_valid'] is False
|
||||||
assert vote['vote']['invalid_reason'] is None
|
assert vote['vote']['invalid_reason'] is None
|
||||||
assert vote['node_pubkey'] == b.me
|
assert vote['node_pubkey'] == b.me
|
||||||
assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
|
assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
|
||||||
|
|
||||||
def test_voter_considers_unvoted_blocks_when_single_node(self, b):
|
def test_voter_considers_unvoted_blocks_when_single_node(self, b):
|
||||||
# simulate a voter going donw in a single node environment
|
# simulate a voter going donw in a single node environment
|
||||||
|
@ -3,6 +3,7 @@ import copy
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import bigchaindb
|
import bigchaindb
|
||||||
|
from bigchaindb import exceptions
|
||||||
|
|
||||||
|
|
||||||
ORIGINAL_CONFIG = copy.deepcopy(bigchaindb.config)
|
ORIGINAL_CONFIG = copy.deepcopy(bigchaindb.config)
|
||||||
@ -34,5 +35,5 @@ def test_bigchain_instance_raises_when_not_configured(monkeypatch):
|
|||||||
# from existing configurations
|
# from existing configurations
|
||||||
monkeypatch.setattr(config_utils, 'autoconfigure', lambda: 0)
|
monkeypatch.setattr(config_utils, 'autoconfigure', lambda: 0)
|
||||||
|
|
||||||
with pytest.raises(bigchaindb.core.KeypairNotFoundException):
|
with pytest.raises(exceptions.KeypairNotFoundException):
|
||||||
bigchaindb.Bigchain()
|
bigchaindb.Bigchain()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user