Skip to content
Snippets Groups Projects
Commit 06fc3c70 authored by Vincent Texier's avatar Vincent Texier
Browse files

add blockchain repository

parent e9191c5c
Branches
Tags
1 merge request!537Feature/backend
from .identity import Identity
from .community import Community
from .blockchain import Blockchain
from .certification import Certification
from .transaction import Transaction
from .node import Node
......@@ -4,11 +4,19 @@ from duniterpy.documents import block_uid, BlockUID
@attr.s()
class Blockchain:
# block number and hash
current_buid = attr.ib(convert=block_uid, default=BlockUID.empty())
# Number of members
nb_members = attr.ib(convert=int, default=0, cmp=False)
# Current monetary mass in units
current_mass = attr.ib(convert=int, default=0, cmp=False)
# Median time in seconds
median_time = attr.ib(convert=int, default=0, cmp=False)
# Last UD amount in units (multiply by 10^base)
last_ud = attr.ib(convert=int, default=0, cmp=False)
# Last UD base
last_ud_base = attr.ib(convert=int, default=0, cmp=False)
# Previous monetary mass in units
previous_mass = attr.ib(convert=int, default=0, cmp=False)
# Currency name
currency = attr.ib(convert=str, default="", cmp=False)
from .identities import IdentitiesRepo
from .communities import CommunitiesRepo
from .blockchains import BlockchainsRepo
from .meta import MetaDatabase
from .certifications import CertificationsRepo
from .transactions import TransactionsRepo
......
import attr
from ..entities import Blockchain
@attr.s(frozen=True)
class BlockchainsRepo:
"""The repository for Blockchain entities.
"""
_conn = attr.ib() # :type sqlite3.Connection
_primary_keys = (Blockchain.currency,)
def insert(self, blockchain):
"""
Commit a blockchain to the database
:param sakia.data.entities.Blockchain blockchain: the blockchain to commit
"""
with self._conn:
blockchain_tuple = attr.astuple(blockchain)
values = ",".join(['?'] * len(blockchain_tuple))
self._conn.execute("INSERT INTO blockchains VALUES ({0})".format(values), blockchain_tuple)
def update(self, blockchain):
"""
Update an existing blockchain in the database
:param sakia.data.entities.Blockchain blockchain: the blockchain to update
"""
with self._conn:
updated_fields = attr.astuple(blockchain, filter=attr.filters.exclude(*BlockchainsRepo._primary_keys))
where_fields = attr.astuple(blockchain, filter=attr.filters.include(*BlockchainsRepo._primary_keys))
self._conn.execute("""UPDATE blockchains SET
current_buid=?,
nb_members=?,
current_mass=?,
median_time=?,
last_ud=?,
last_ud_base=?,
previous_mass=?
WHERE
currency=?""",
updated_fields + where_fields)
def get_one(self, **search):
"""
Get an existing blockchain in the database
:param dict search: the criterions of the lookup
:rtype: sakia.data.entities.Blockchain
"""
with self._conn:
filters = []
values = []
for k, v in search.items():
filters.append("{k}=?".format(k=k))
values.append(v)
request = "SELECT * FROM blockchains WHERE {filters}".format(filters=" AND ".join(filters))
c = self._conn.execute(request, tuple(values))
data = c.fetchone()
if data:
return Blockchain(*data)
def get_all(self, **search):
"""
Get all existing blockchain in the database corresponding to the search
:param dict search: the criterions of the lookup
:rtype: sakia.data.entities.Blockchain
"""
with self._conn:
filters = []
values = []
for k, v in search.items():
operator = "LIKE" if k == "currency" else "="
value = "%{value}%".format(value=v) if k == "currency" else v
filters.append("{key} {operator} ?".format(key=k, operator=operator))
values.append(value)
request = "SELECT * FROM blockchains WHERE {filters}".format(filters=" AND ".join(filters))
c = self._conn.execute(request, tuple(values))
datas = c.fetchall()
if datas:
return [Blockchain(*data) for data in datas]
return []
def drop(self, blockchain):
"""
Drop an existing blockchain from the database
:param sakia.data.entities.Blockchain blockchain: the blockchain to update
"""
with self._conn:
where_fields = attr.astuple(blockchain, filter=attr.filters.include(*BlockchainsRepo._primary_keys))
self._conn.execute("DELETE FROM blockchains WHERE currency=?", where_fields)
......@@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS identities(
PRIMARY KEY (currency, pubkey, uid, blockstamp)
);
-- COMMUNITY TABLE
-- COMMUNITIES TABLE
CREATE TABLE IF NOT EXISTS communities (
c FLOAT(1, 6),
dt INT,
......@@ -38,6 +38,19 @@ CREATE TABLE IF NOT EXISTS communities(
PRIMARY KEY (currency)
);
-- BLOCKCHAIN TABLE
CREATE TABLE IF NOT EXISTS blockchains (
current_buid INT,
nb_members INT,
current_mass INT,
median_time INT,
last_ud INT,
last_ud_base INT,
previous_mass INT,
currency VARCHAR(30),
PRIMARY KEY (currency)
);
-- CERTIFICATIONS TABLE
CREATE TABLE IF NOT EXISTS certifications(
......
import sqlite3
import unittest
from duniterpy.documents import BlockUID
from sakia.data.entities import Blockchain
from sakia.data.repositories import BlockchainsRepo, MetaDatabase
class TestBlockchainsRepo(unittest.TestCase):
def setUp(self):
sqlite3.register_adapter(BlockUID, str)
sqlite3.register_adapter(bool, int)
sqlite3.register_converter("BOOLEAN", lambda v: bool(int(v)))
self.con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
def tearDown(self):
self.con.close()
def test_add_get_drop_blockchain(self):
meta_repo = MetaDatabase(self.con)
meta_repo.prepare()
meta_repo.upgrade_database()
blockchains_repo = BlockchainsRepo(self.con)
blockchains_repo.insert(Blockchain(
"20-7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
10,
1000000,
86400,
100000,
0,
999999,
"testcurrency"
))
blockchain = blockchains_repo.get_one(currency="testcurrency")
self.assertEqual(blockchain.currency, "testcurrency")
self.assertEqual(blockchain.current_buid, BlockUID(20,
"7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67")
)
self.assertEqual(blockchain.nb_members, 10)
blockchains_repo.drop(blockchain)
blockchain = blockchains_repo.get_one(currency="testcurrency")
self.assertIsNone(blockchain)
def test_add_get_multiple_blockchain(self):
meta_repo = MetaDatabase(self.con)
meta_repo.prepare()
meta_repo.upgrade_database()
blockchains_repo = BlockchainsRepo(self.con)
blockchains_repo.insert(Blockchain(
"20-7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
10,
1000000,
86400,
100000,
0,
999999,
"testcurrency"
)
)
blockchains_repo.insert(Blockchain(
"20-7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
20,
1000000,
86400,
100000,
0,
999999,
"testcurrency2"
)
)
blockchains = blockchains_repo.get_all(currency="testcurrency")
self.assertIn("testcurrency", [i.currency for i in blockchains])
self.assertIn("testcurrency2", [i.currency for i in blockchains])
self.assertIn(10, [i.nb_members for i in blockchains])
self.assertIn(20, [i.nb_members for i in blockchains])
def test_add_update_blockchain(self):
meta_repo = MetaDatabase(self.con)
meta_repo.prepare()
meta_repo.upgrade_database()
blockchains_repo = BlockchainsRepo(self.con)
blockchain = Blockchain(
"20-7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67",
10,
1000000,
86400,
100000,
0,
999999,
"testcurrency"
)
blockchains_repo.insert(blockchain)
blockchain.nb_members = 30
blockchains_repo.update(blockchain)
blockchain2 = blockchains_repo.get_one(currency="testcurrency")
self.assertEquals(30, blockchain2.nb_members)
......@@ -7,7 +7,7 @@ from sakia.data.entities import Community
from sakia.data.repositories import CommunitiesRepo, MetaDatabase
class TestIdentitiesRepo(unittest.TestCase):
class TestCommunitiesRepo(unittest.TestCase):
def setUp(self):
sqlite3.register_adapter(BlockUID, str)
sqlite3.register_adapter(bool, int)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment