db lock issue, use one connection
This commit is contained in:
parent
2ccdd3860d
commit
6e01eca711
|
@ -1,6 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import Dict, Optional, List
|
from typing import Dict, Optional, List
|
||||||
from pathlib import Path
|
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
from src.types.full_block import FullBlock
|
from src.types.full_block import FullBlock
|
||||||
from src.types.hashable.coin import Coin
|
from src.types.hashable.coin import Coin
|
||||||
|
@ -37,12 +36,12 @@ class CoinStore:
|
||||||
cache_size: uint32
|
cache_size: uint32
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls, db_path: Path, cache_size: uint32 = uint32(600000)):
|
async def create(cls, connection: aiosqlite.Connection, cache_size: uint32 = uint32(600000)):
|
||||||
self = cls()
|
self = cls()
|
||||||
|
|
||||||
self.cache_size = cache_size
|
self.cache_size = cache_size
|
||||||
# All full blocks which have been added to the blockchain. Header_hash -> block
|
# All full blocks which have been added to the blockchain. Header_hash -> block
|
||||||
self.coin_record_db = await aiosqlite.connect(db_path)
|
self.coin_record_db = connection
|
||||||
await self.coin_record_db.execute(
|
await self.coin_record_db.execute(
|
||||||
(
|
(
|
||||||
f"CREATE TABLE IF NOT EXISTS coin_record("
|
f"CREATE TABLE IF NOT EXISTS coin_record("
|
||||||
|
@ -81,9 +80,6 @@ class CoinStore:
|
||||||
self.head_diffs = dict()
|
self.head_diffs = dict()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def close(self):
|
|
||||||
await self.coin_record_db.close()
|
|
||||||
|
|
||||||
async def _clear_database(self):
|
async def _clear_database(self):
|
||||||
cursor = await self.coin_record_db.execute("DELETE FROM coin_record")
|
cursor = await self.coin_record_db.execute("DELETE FROM coin_record")
|
||||||
await cursor.close()
|
await cursor.close()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
from pathlib import Path
|
|
||||||
from typing import Dict, List, Optional, Tuple
|
from typing import Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from src.types.hashable.program import Program
|
from src.types.hashable.program import Program
|
||||||
|
@ -58,11 +57,11 @@ class FullNodeStore:
|
||||||
lock: asyncio.Lock
|
lock: asyncio.Lock
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls, db_path: Path):
|
async def create(cls, connection):
|
||||||
self = cls()
|
self = cls()
|
||||||
|
|
||||||
# All full blocks which have been added to the blockchain. Header_hash -> block
|
# All full blocks which have been added to the blockchain. Header_hash -> block
|
||||||
self.db = await aiosqlite.connect(db_path)
|
self.db = connection
|
||||||
await self.db.execute(
|
await self.db.execute(
|
||||||
"CREATE TABLE IF NOT EXISTS blocks(height bigint, header_hash text PRIMARY KEY, block blob)"
|
"CREATE TABLE IF NOT EXISTS blocks(height bigint, header_hash text PRIMARY KEY, block blob)"
|
||||||
)
|
)
|
||||||
|
@ -110,9 +109,6 @@ class FullNodeStore:
|
||||||
self.lock = asyncio.Lock() # external
|
self.lock = asyncio.Lock() # external
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def close(self):
|
|
||||||
await self.db.close()
|
|
||||||
|
|
||||||
async def _clear_database(self):
|
async def _clear_database(self):
|
||||||
async with self.lock:
|
async with self.lock:
|
||||||
await self.db.execute("DELETE FROM blocks")
|
await self.db.execute("DELETE FROM blocks")
|
||||||
|
|
|
@ -3,6 +3,7 @@ import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
import signal
|
import signal
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
import miniupnpc
|
import miniupnpc
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -39,11 +40,12 @@ async def main():
|
||||||
mkdir(db_path.parent)
|
mkdir(db_path.parent)
|
||||||
|
|
||||||
# Create the store (DB) and full node instance
|
# Create the store (DB) and full node instance
|
||||||
store = await FullNodeStore.create(db_path)
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
|
|
||||||
genesis: FullBlock = FullBlock.from_bytes(constants["GENESIS_BLOCK"])
|
genesis: FullBlock = FullBlock.from_bytes(constants["GENESIS_BLOCK"])
|
||||||
await store.add_block(genesis)
|
await store.add_block(genesis)
|
||||||
unspent_store = await CoinStore.create(db_path)
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
|
||||||
log.info("Initializing blockchain from disk")
|
log.info("Initializing blockchain from disk")
|
||||||
blockchain = await Blockchain.create(unspent_store, store)
|
blockchain = await Blockchain.create(unspent_store, store)
|
||||||
|
@ -129,11 +131,8 @@ async def main():
|
||||||
await rpc_cleanup()
|
await rpc_cleanup()
|
||||||
log.info("Closed RPC server.")
|
log.info("Closed RPC server.")
|
||||||
|
|
||||||
await store.close()
|
await connection.close()
|
||||||
log.info("Closed store.")
|
log.info("Closed db connection.")
|
||||||
|
|
||||||
await unspent_store.close()
|
|
||||||
log.info("Closed unspent store.")
|
|
||||||
|
|
||||||
await asyncio.get_running_loop().shutdown_asyncgens()
|
await asyncio.get_running_loop().shutdown_asyncgens()
|
||||||
log.info("Node fully closed.")
|
log.info("Node fully closed.")
|
||||||
|
|
|
@ -3,6 +3,8 @@ import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
import signal
|
import signal
|
||||||
from src.path import mkdir, path_from_root
|
from src.path import mkdir, path_from_root
|
||||||
|
from pathlib import Path
|
||||||
|
import aiosqlite
|
||||||
from src.simulator.full_node_simulator import FullNodeSimulator
|
from src.simulator.full_node_simulator import FullNodeSimulator
|
||||||
from src.simulator.simulator_constants import test_constants
|
from src.simulator.simulator_constants import test_constants
|
||||||
|
|
||||||
|
@ -34,14 +36,15 @@ async def main():
|
||||||
|
|
||||||
db_path = path_from_root(config["simulator_database_path"])
|
db_path = path_from_root(config["simulator_database_path"])
|
||||||
mkdir(db_path.parent)
|
mkdir(db_path.parent)
|
||||||
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
|
||||||
# Create the store (DB) and full node instance
|
# Create the store (DB) and full node instance
|
||||||
store = await FullNodeStore.create(db_path)
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
|
|
||||||
genesis: FullBlock = FullBlock.from_bytes(test_constants["GENESIS_BLOCK"])
|
genesis: FullBlock = FullBlock.from_bytes(test_constants["GENESIS_BLOCK"])
|
||||||
await store.add_block(genesis)
|
await store.add_block(genesis)
|
||||||
unspent_store = await CoinStore.create(db_path)
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
|
||||||
log.info("Initializing blockchain from disk")
|
log.info("Initializing blockchain from disk")
|
||||||
blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import Set, Tuple, Optional
|
from typing import Set, Tuple, Optional
|
||||||
from pathlib import Path
|
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
from src.types.sized_bytes import bytes32
|
from src.types.sized_bytes import bytes32
|
||||||
from src.util.ints import uint32, uint64
|
from src.util.ints import uint32, uint64
|
||||||
|
@ -17,12 +16,12 @@ class WalletPuzzleStore:
|
||||||
cache_size: uint32
|
cache_size: uint32
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls, db_path: Path, cache_size: uint32 = uint32(600000)):
|
async def create(cls, connection: aiosqlite.Connection, cache_size: uint32 = uint32(600000)):
|
||||||
self = cls()
|
self = cls()
|
||||||
|
|
||||||
self.cache_size = cache_size
|
self.cache_size = cache_size
|
||||||
|
|
||||||
self.db_connection = await aiosqlite.connect(db_path)
|
self.db_connection = connection
|
||||||
|
|
||||||
await self.db_connection.execute(
|
await self.db_connection.execute(
|
||||||
(
|
(
|
||||||
|
|
|
@ -4,6 +4,8 @@ from pathlib import Path
|
||||||
from typing import Dict, Optional, List, Set, Tuple, Callable
|
from typing import Dict, Optional, List, Set, Tuple, Callable
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
from chiabip158 import PyBIP158
|
from chiabip158 import PyBIP158
|
||||||
|
|
||||||
from src.types.hashable.coin import Coin
|
from src.types.hashable.coin import Coin
|
||||||
|
@ -60,6 +62,7 @@ class WalletStateManager:
|
||||||
state_changed_callback: Optional[Callable]
|
state_changed_callback: Optional[Callable]
|
||||||
pending_tx_callback: Optional[Callable]
|
pending_tx_callback: Optional[Callable]
|
||||||
db_path: Path
|
db_path: Path
|
||||||
|
db_connection: aiosqlite.Connection
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def create(
|
async def create(
|
||||||
|
@ -75,10 +78,11 @@ class WalletStateManager:
|
||||||
self.log = logging.getLogger(__name__)
|
self.log = logging.getLogger(__name__)
|
||||||
self.lock = asyncio.Lock()
|
self.lock = asyncio.Lock()
|
||||||
|
|
||||||
self.wallet_store = await WalletStore.create(db_path)
|
self.db_connection = await aiosqlite.connect(db_path)
|
||||||
self.tx_store = await WalletTransactionStore.create(db_path)
|
self.wallet_store = await WalletStore.create(self.db_connection)
|
||||||
self.puzzle_store = await WalletPuzzleStore.create(db_path)
|
self.tx_store = await WalletTransactionStore.create(self.db_connection)
|
||||||
self.user_store = await WalletUserStore.create(db_path)
|
self.puzzle_store = await WalletPuzzleStore.create(self.db_connection)
|
||||||
|
self.user_store = await WalletUserStore.create(self.db_connection)
|
||||||
self.lca = None
|
self.lca = None
|
||||||
self.sync_mode = False
|
self.sync_mode = False
|
||||||
self.height_to_hash = {}
|
self.height_to_hash = {}
|
||||||
|
@ -1035,10 +1039,7 @@ class WalletStateManager:
|
||||||
|
|
||||||
async def close_all_stores(self):
|
async def close_all_stores(self):
|
||||||
async with self.lock:
|
async with self.lock:
|
||||||
await self.wallet_store.close()
|
await self.db_connection.close()
|
||||||
await self.tx_store.close()
|
|
||||||
await self.puzzle_store.close()
|
|
||||||
await self.user_store.close()
|
|
||||||
|
|
||||||
async def clear_all_stores(self):
|
async def clear_all_stores(self):
|
||||||
async with self.lock:
|
async with self.lock:
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from typing import Dict, Optional, List, Set
|
from typing import Dict, Optional, List, Set
|
||||||
from pathlib import Path
|
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
from src.types.hashable.coin import Coin
|
from src.types.hashable.coin import Coin
|
||||||
from src.wallet.block_record import BlockRecord
|
from src.wallet.block_record import BlockRecord
|
||||||
|
@ -20,12 +19,12 @@ class WalletStore:
|
||||||
cache_size: uint32
|
cache_size: uint32
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls, db_path: Path, cache_size: uint32 = uint32(600000)):
|
async def create(cls, connection: aiosqlite.Connection, cache_size: uint32 = uint32(600000)):
|
||||||
self = cls()
|
self = cls()
|
||||||
|
|
||||||
self.cache_size = cache_size
|
self.cache_size = cache_size
|
||||||
|
|
||||||
self.db_connection = await aiosqlite.connect(db_path)
|
self.db_connection = connection
|
||||||
await self.db_connection.execute(
|
await self.db_connection.execute(
|
||||||
(
|
(
|
||||||
f"CREATE TABLE IF NOT EXISTS coin_record("
|
f"CREATE TABLE IF NOT EXISTS coin_record("
|
||||||
|
@ -75,9 +74,6 @@ class WalletStore:
|
||||||
self.coin_record_cache = dict()
|
self.coin_record_cache = dict()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def close(self):
|
|
||||||
await self.db_connection.close()
|
|
||||||
|
|
||||||
async def _clear_database(self):
|
async def _clear_database(self):
|
||||||
cursor = await self.db_connection.execute("DELETE FROM coin_record")
|
cursor = await self.db_connection.execute("DELETE FROM coin_record")
|
||||||
await cursor.close()
|
await cursor.close()
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from typing import Dict, Optional, List
|
from typing import Dict, Optional, List
|
||||||
from pathlib import Path
|
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
from src.types.sized_bytes import bytes32
|
from src.types.sized_bytes import bytes32
|
||||||
from src.util.ints import uint32, uint8
|
from src.util.ints import uint32, uint8
|
||||||
|
@ -18,12 +17,12 @@ class WalletTransactionStore:
|
||||||
tx_record_cache: Dict[bytes32, TransactionRecord]
|
tx_record_cache: Dict[bytes32, TransactionRecord]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls, db_path: Path, cache_size: uint32 = uint32(600000)):
|
async def create(cls, connection: aiosqlite.Connection, cache_size: uint32 = uint32(600000)):
|
||||||
self = cls()
|
self = cls()
|
||||||
|
|
||||||
self.cache_size = cache_size
|
self.cache_size = cache_size
|
||||||
|
|
||||||
self.db_connection = await aiosqlite.connect(db_path)
|
self.db_connection = connection
|
||||||
await self.db_connection.execute(
|
await self.db_connection.execute(
|
||||||
(
|
(
|
||||||
f"CREATE TABLE IF NOT EXISTS transaction_record("
|
f"CREATE TABLE IF NOT EXISTS transaction_record("
|
||||||
|
@ -78,9 +77,6 @@ class WalletTransactionStore:
|
||||||
self.tx_record_cache = dict()
|
self.tx_record_cache = dict()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def close(self):
|
|
||||||
await self.db_connection.close()
|
|
||||||
|
|
||||||
async def _init_cache(self):
|
async def _init_cache(self):
|
||||||
print("init cache here")
|
print("init cache here")
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from pathlib import Path
|
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
|
@ -16,10 +15,10 @@ class WalletUserStore:
|
||||||
cache_size: uint32
|
cache_size: uint32
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create(cls, db_path: Path):
|
async def create(cls, connection: aiosqlite.Connection):
|
||||||
self = cls()
|
self = cls()
|
||||||
|
|
||||||
self.db_connection = await aiosqlite.connect(db_path)
|
self.db_connection = connection
|
||||||
|
|
||||||
await self.db_connection.execute(
|
await self.db_connection.execute(
|
||||||
(
|
(
|
||||||
|
@ -52,9 +51,6 @@ class WalletUserStore:
|
||||||
if len(all_wallets) == 0:
|
if len(all_wallets) == 0:
|
||||||
await self.create_wallet("Chia Wallet", WalletType.STANDARD_WALLET, "")
|
await self.create_wallet("Chia Wallet", WalletType.STANDARD_WALLET, "")
|
||||||
|
|
||||||
async def close(self):
|
|
||||||
await self.db_connection.close()
|
|
||||||
|
|
||||||
async def _clear_database(self):
|
async def _clear_database(self):
|
||||||
cursor = await self.db_connection.execute("DELETE FROM users_wallets")
|
cursor = await self.db_connection.execute("DELETE FROM users_wallets")
|
||||||
await cursor.close()
|
await cursor.close()
|
||||||
|
|
|
@ -3,6 +3,7 @@ import time
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
import pytest
|
import pytest
|
||||||
from blspy import PrivateKey
|
from blspy import PrivateKey
|
||||||
|
|
||||||
|
@ -44,8 +45,10 @@ def event_loop():
|
||||||
class TestGenesisBlock:
|
class TestGenesisBlock:
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_basic_blockchain(self):
|
async def test_basic_blockchain(self):
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
db_path = Path("blockchain_test.db")
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
bc1 = await Blockchain.create(unspent_store, store, test_constants)
|
bc1 = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
assert len(bc1.get_current_tips()) == 1
|
assert len(bc1.get_current_tips()) == 1
|
||||||
|
@ -56,8 +59,7 @@ class TestGenesisBlock:
|
||||||
) == genesis_block.weight
|
) == genesis_block.weight
|
||||||
assert bc1.get_next_min_iters(bc1.genesis) > 0
|
assert bc1.get_next_min_iters(bc1.genesis) > 0
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
|
|
||||||
|
|
||||||
class TestBlockValidation:
|
class TestBlockValidation:
|
||||||
|
@ -67,17 +69,18 @@ class TestBlockValidation:
|
||||||
Provides a list of 10 valid blocks, as well as a blockchain with 9 blocks added to it.
|
Provides a list of 10 valid blocks, as well as a blockchain with 9 blocks added to it.
|
||||||
"""
|
"""
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 10, [], 10)
|
blocks = bt.get_consecutive_blocks(test_constants, 10, [], 10)
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
db_path = Path("blockchain_test.db")
|
||||||
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
unspent_store = await CoinStore.create(connection)
|
||||||
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
for i in range(1, 9):
|
for i in range(1, 9):
|
||||||
result, removed = await b.receive_block(blocks[i])
|
result, removed = await b.receive_block(blocks[i])
|
||||||
assert result == ReceiveBlockResult.ADDED_TO_HEAD
|
assert result == ReceiveBlockResult.ADDED_TO_HEAD
|
||||||
yield (blocks, b)
|
yield (blocks, b)
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_prev_pointer(self, initial_blockchain):
|
async def test_prev_pointer(self, initial_blockchain):
|
||||||
|
@ -294,9 +297,10 @@ class TestBlockValidation:
|
||||||
num_blocks = 30
|
num_blocks = 30
|
||||||
# Make it 5x faster than target time
|
# Make it 5x faster than target time
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 2)
|
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 2)
|
||||||
|
db_path = Path("blockchain_test.db")
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
connection = await aiosqlite.connect(db_path)
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
for i in range(1, num_blocks):
|
for i in range(1, num_blocks):
|
||||||
|
@ -317,16 +321,17 @@ class TestBlockValidation:
|
||||||
assert (b.get_next_min_iters(blocks[26])) > (b.get_next_min_iters(blocks[25]))
|
assert (b.get_next_min_iters(blocks[26])) > (b.get_next_min_iters(blocks[25]))
|
||||||
assert (b.get_next_min_iters(blocks[27])) == (b.get_next_min_iters(blocks[26]))
|
assert (b.get_next_min_iters(blocks[27])) == (b.get_next_min_iters(blocks[26]))
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
|
|
||||||
|
|
||||||
class TestReorgs:
|
class TestReorgs:
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_basic_reorg(self):
|
async def test_basic_reorg(self):
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 100, [], 9)
|
blocks = bt.get_consecutive_blocks(test_constants, 100, [], 9)
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
db_path = Path("blockchain_test.db")
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
|
|
||||||
|
@ -348,14 +353,15 @@ class TestReorgs:
|
||||||
assert result == ReceiveBlockResult.ADDED_TO_HEAD
|
assert result == ReceiveBlockResult.ADDED_TO_HEAD
|
||||||
assert b.get_current_tips()[0].height == 119
|
assert b.get_current_tips()[0].height == 119
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_reorg_from_genesis(self):
|
async def test_reorg_from_genesis(self):
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 20, [], 9, b"0")
|
blocks = bt.get_consecutive_blocks(test_constants, 20, [], 9, b"0")
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
db_path = Path("blockchain_test.db")
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
for i in range(1, len(blocks)):
|
for i in range(1, len(blocks)):
|
||||||
|
@ -390,14 +396,15 @@ class TestReorgs:
|
||||||
result, _ = await b.receive_block(blocks_reorg_chain_2[22])
|
result, _ = await b.receive_block(blocks_reorg_chain_2[22])
|
||||||
assert result == ReceiveBlockResult.ADDED_TO_HEAD
|
assert result == ReceiveBlockResult.ADDED_TO_HEAD
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_lca(self):
|
async def test_lca(self):
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b"0")
|
blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b"0")
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
db_path = Path("blockchain_test.db")
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
for i in range(1, len(blocks)):
|
for i in range(1, len(blocks)):
|
||||||
|
@ -417,14 +424,15 @@ class TestReorgs:
|
||||||
await b.receive_block(reorg[i])
|
await b.receive_block(reorg[i])
|
||||||
assert b.lca_block.header_hash == blocks[0].header_hash
|
assert b.lca_block.header_hash == blocks[0].header_hash
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_header_hashes(self):
|
async def test_get_header_hashes(self):
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b"0")
|
blocks = bt.get_consecutive_blocks(test_constants, 5, [], 9, b"0")
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
db_path = Path("blockchain_test.db")
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
|
|
||||||
|
@ -434,5 +442,4 @@ class TestReorgs:
|
||||||
assert len(header_hashes) == 6
|
assert len(header_hashes) == 6
|
||||||
assert header_hashes == [block.header_hash for block in blocks]
|
assert header_hashes == [block.header_hash for block in blocks]
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ from typing import Any, Dict
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
import pytest
|
import pytest
|
||||||
from src.full_node.store import FullNodeStore
|
from src.full_node.store import FullNodeStore
|
||||||
from src.types.full_block import FullBlock
|
from src.types.full_block import FullBlock
|
||||||
|
@ -50,8 +51,12 @@ class TestStore:
|
||||||
if db_filename_3.exists():
|
if db_filename_3.exists():
|
||||||
db_filename_3.unlink()
|
db_filename_3.unlink()
|
||||||
|
|
||||||
db = await FullNodeStore.create(db_filename)
|
connection = await aiosqlite.connect(db_filename)
|
||||||
db_2 = await FullNodeStore.create(db_filename_2)
|
connection_2 = await aiosqlite.connect(db_filename_2)
|
||||||
|
connection_3 = await aiosqlite.connect(db_filename_3)
|
||||||
|
|
||||||
|
db = await FullNodeStore.create(connection)
|
||||||
|
db_2 = await FullNodeStore.create(connection_2)
|
||||||
try:
|
try:
|
||||||
await db._clear_database()
|
await db._clear_database()
|
||||||
|
|
||||||
|
@ -144,19 +149,20 @@ class TestStore:
|
||||||
assert not db.seen_unfinished_block(h_hash_1)
|
assert not db.seen_unfinished_block(h_hash_1)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
await db.close()
|
await connection.close()
|
||||||
await db_2.close()
|
await connection_2.close()
|
||||||
|
await connection_3.close()
|
||||||
db_filename.unlink()
|
db_filename.unlink()
|
||||||
db_filename_2.unlink()
|
db_filename_2.unlink()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# Different database should have different data
|
# Different database should have different data
|
||||||
db_3 = await FullNodeStore.create(db_filename_3)
|
db_3 = await FullNodeStore.create(connection_3)
|
||||||
assert db_3.get_unfinished_block_leader() == (0, (1 << 64) - 1)
|
assert db_3.get_unfinished_block_leader() == (0, (1 << 64) - 1)
|
||||||
|
|
||||||
await db.close()
|
await connection.close()
|
||||||
await db_2.close()
|
await connection_2.close()
|
||||||
await db_3.close()
|
await connection_3.close()
|
||||||
db_filename.unlink()
|
db_filename.unlink()
|
||||||
db_filename_2.unlink()
|
db_filename_2.unlink()
|
||||||
db_filename_3.unlink()
|
db_filename_3.unlink()
|
||||||
|
@ -169,7 +175,8 @@ class TestStore:
|
||||||
if db_filename.exists():
|
if db_filename.exists():
|
||||||
db_filename.unlink()
|
db_filename.unlink()
|
||||||
|
|
||||||
db = await FullNodeStore.create(db_filename)
|
connection = await aiosqlite.connect(db_filename)
|
||||||
|
db = await FullNodeStore.create(connection)
|
||||||
tasks = []
|
tasks = []
|
||||||
|
|
||||||
for i in range(10000):
|
for i in range(10000):
|
||||||
|
@ -191,5 +198,5 @@ class TestStore:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
await asyncio.gather(*tasks)
|
await asyncio.gather(*tasks)
|
||||||
await db.close()
|
await connection.close()
|
||||||
db_filename.unlink()
|
db_filename.unlink()
|
||||||
|
|
|
@ -2,6 +2,7 @@ import asyncio
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from src.full_node.blockchain import Blockchain, ReceiveBlockResult
|
from src.full_node.blockchain import Blockchain, ReceiveBlockResult
|
||||||
|
@ -40,7 +41,9 @@ class TestUnspent:
|
||||||
async def test_basic_unspent_store(self):
|
async def test_basic_unspent_store(self):
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 9, [], 9, b"0")
|
blocks = bt.get_consecutive_blocks(test_constants, 9, [], 9, b"0")
|
||||||
|
|
||||||
db = await CoinStore.create(Path("fndb_test.db"))
|
db_path = Path("fndb_test.db")
|
||||||
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
db = await CoinStore.create(connection)
|
||||||
await db._clear_database()
|
await db._clear_database()
|
||||||
|
|
||||||
# Save/get block
|
# Save/get block
|
||||||
|
@ -51,14 +54,16 @@ class TestUnspent:
|
||||||
assert block.header.data.coinbase == unspent.coin
|
assert block.header.data.coinbase == unspent.coin
|
||||||
assert block.header.data.fees_coin == unspent_fee.coin
|
assert block.header.data.fees_coin == unspent_fee.coin
|
||||||
|
|
||||||
await db.close()
|
await connection.close()
|
||||||
Path("fndb_test.db").unlink()
|
Path("fndb_test.db").unlink()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_set_spent(self):
|
async def test_set_spent(self):
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 9, [], 9, b"0")
|
blocks = bt.get_consecutive_blocks(test_constants, 9, [], 9, b"0")
|
||||||
|
|
||||||
db = await CoinStore.create(Path("fndb_test.db"))
|
db_path = Path("fndb_test.db")
|
||||||
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
db = await CoinStore.create(connection)
|
||||||
await db._clear_database()
|
await db._clear_database()
|
||||||
|
|
||||||
# Save/get block
|
# Save/get block
|
||||||
|
@ -76,14 +81,16 @@ class TestUnspent:
|
||||||
assert unspent.spent == 1
|
assert unspent.spent == 1
|
||||||
assert unspent_fee.spent == 1
|
assert unspent_fee.spent == 1
|
||||||
|
|
||||||
await db.close()
|
await connection.close()
|
||||||
Path("fndb_test.db").unlink()
|
Path("fndb_test.db").unlink()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_rollback(self):
|
async def test_rollback(self):
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 9, [], 9, b"0")
|
blocks = bt.get_consecutive_blocks(test_constants, 9, [], 9, b"0")
|
||||||
|
|
||||||
db = await CoinStore.create(Path("fndb_test.db"))
|
db_path = Path("fndb_test.db")
|
||||||
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
db = await CoinStore.create(connection)
|
||||||
await db._clear_database()
|
await db._clear_database()
|
||||||
|
|
||||||
# Save/get block
|
# Save/get block
|
||||||
|
@ -114,14 +121,16 @@ class TestUnspent:
|
||||||
assert unspent is None
|
assert unspent is None
|
||||||
assert unspent_fee is None
|
assert unspent_fee is None
|
||||||
|
|
||||||
await db.close()
|
await connection.close()
|
||||||
Path("fndb_test.db").unlink()
|
Path("fndb_test.db").unlink()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_basic_reorg(self):
|
async def test_basic_reorg(self):
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, 100, [], 9)
|
blocks = bt.get_consecutive_blocks(test_constants, 100, [], 9)
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
db_path = Path("blockchain_test.db")
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
try:
|
try:
|
||||||
|
@ -166,21 +175,21 @@ class TestUnspent:
|
||||||
assert unspent.spent_block_index == 0
|
assert unspent.spent_block_index == 0
|
||||||
assert b.get_current_tips()[0].height == 119
|
assert b.get_current_tips()[0].height == 119
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
Path("blockchain_test.db").unlink()
|
Path("blockchain_test.db").unlink()
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
Path("blockchain_test.db").unlink()
|
Path("blockchain_test.db").unlink()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_puzzle_hash(self):
|
async def test_get_puzzle_hash(self):
|
||||||
num_blocks = 20
|
num_blocks = 20
|
||||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 9)
|
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 9)
|
||||||
unspent_store = await CoinStore.create(Path("blockchain_test.db"))
|
db_path = Path("blockchain_test.db")
|
||||||
store = await FullNodeStore.create(Path("blockchain_test.db"))
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
unspent_store = await CoinStore.create(connection)
|
||||||
|
store = await FullNodeStore.create(connection)
|
||||||
await store._clear_database()
|
await store._clear_database()
|
||||||
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
b: Blockchain = await Blockchain.create(unspent_store, store, test_constants)
|
||||||
try:
|
try:
|
||||||
|
@ -197,11 +206,9 @@ class TestUnspent:
|
||||||
)
|
)
|
||||||
assert len(coins) == (num_blocks + 1) * 2
|
assert len(coins) == (num_blocks + 1) * 2
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
Path("blockchain_test.db").unlink()
|
Path("blockchain_test.db").unlink()
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
await unspent_store.close()
|
await connection.close()
|
||||||
await store.close()
|
|
||||||
Path("blockchain_test.db").unlink()
|
Path("blockchain_test.db").unlink()
|
||||||
|
|
|
@ -2,6 +2,8 @@ import signal
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
import blspy
|
import blspy
|
||||||
from secrets import token_bytes
|
from secrets import token_bytes
|
||||||
|
|
||||||
|
@ -55,9 +57,11 @@ async def setup_full_node_simulator(db_name, port, introducer_port=None, dic={})
|
||||||
for k in dic.keys():
|
for k in dic.keys():
|
||||||
test_constants_copy[k] = dic[k]
|
test_constants_copy[k] = dic[k]
|
||||||
|
|
||||||
store_1 = await FullNodeStore.create(Path(db_name))
|
db_path = Path(db_name)
|
||||||
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
store_1 = await FullNodeStore.create(connection)
|
||||||
await store_1._clear_database()
|
await store_1._clear_database()
|
||||||
unspent_store_1 = await CoinStore.create(Path(db_name))
|
unspent_store_1 = await CoinStore.create(connection)
|
||||||
await unspent_store_1._clear_database()
|
await unspent_store_1._clear_database()
|
||||||
mempool_1 = MempoolManager(unspent_store_1, test_constants_copy)
|
mempool_1 = MempoolManager(unspent_store_1, test_constants_copy)
|
||||||
|
|
||||||
|
@ -93,8 +97,7 @@ async def setup_full_node_simulator(db_name, port, introducer_port=None, dic={})
|
||||||
full_node_1._shutdown()
|
full_node_1._shutdown()
|
||||||
server_1.close_all()
|
server_1.close_all()
|
||||||
await server_1.await_closed()
|
await server_1.await_closed()
|
||||||
await store_1.close()
|
await connection.close()
|
||||||
await unspent_store_1.close()
|
|
||||||
Path(db_name).unlink()
|
Path(db_name).unlink()
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,9 +107,11 @@ async def setup_full_node(db_name, port, introducer_port=None, dic={}):
|
||||||
for k in dic.keys():
|
for k in dic.keys():
|
||||||
test_constants_copy[k] = dic[k]
|
test_constants_copy[k] = dic[k]
|
||||||
|
|
||||||
store_1 = await FullNodeStore.create(Path(db_name))
|
db_path = Path(db_name)
|
||||||
|
connection = await aiosqlite.connect(db_path)
|
||||||
|
store_1 = await FullNodeStore.create(connection)
|
||||||
await store_1._clear_database()
|
await store_1._clear_database()
|
||||||
unspent_store_1 = await CoinStore.create(Path(db_name))
|
unspent_store_1 = await CoinStore.create(connection)
|
||||||
await unspent_store_1._clear_database()
|
await unspent_store_1._clear_database()
|
||||||
mempool_1 = MempoolManager(unspent_store_1, test_constants_copy)
|
mempool_1 = MempoolManager(unspent_store_1, test_constants_copy)
|
||||||
|
|
||||||
|
@ -139,9 +144,7 @@ async def setup_full_node(db_name, port, introducer_port=None, dic={}):
|
||||||
# TEARDOWN
|
# TEARDOWN
|
||||||
full_node_1._shutdown()
|
full_node_1._shutdown()
|
||||||
server_1.close_all()
|
server_1.close_all()
|
||||||
await server_1.await_closed()
|
await connection.close()
|
||||||
await store_1.close()
|
|
||||||
await unspent_store_1.close()
|
|
||||||
Path(db_name).unlink()
|
Path(db_name).unlink()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue