Skip to content

Commit 65657e9

Browse files
committed
Test w/ pre-built db fixtures unzipped to a tmpdir
1 parent acd9374 commit 65657e9

File tree

4 files changed

+109
-73
lines changed

4 files changed

+109
-73
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from eth_keys import keys
2+
from eth_utils import decode_hex
3+
4+
from tests.trinity.core.integration_test_helpers import FUNDED_ACCT, load_mining_chain
5+
6+
RECEIVER = keys.PrivateKey(
7+
decode_hex("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"))
8+
9+
10+
def build_pow_fixture(write_db, num_blocks=20):
11+
chain = load_mining_chain(write_db)
12+
for i in range(num_blocks):
13+
tx = chain.create_unsigned_transaction(
14+
nonce=i,
15+
gas_price=1234,
16+
gas=123400,
17+
to=RECEIVER.public_key.to_canonical_address(),
18+
value=i,
19+
data=b'',
20+
)
21+
chain.apply_transaction(tx.as_signed_transaction(FUNDED_ACCT))
22+
chain.mine_block()
23+
return chain.chaindb

tests/trinity/core/integration_test_helpers.py

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,34 @@
11
import asyncio
2+
from enum import Enum
3+
from pathlib import Path
4+
from tempfile import TemporaryDirectory
5+
from zipfile import ZipFile
26

37
from cancel_token import OperationCancelled
8+
from eth_keys import keys
9+
from eth_utils import decode_hex
410

5-
from eth import MainnetChain, RopstenChain
11+
from eth import MainnetChain, RopstenChain, constants
612
from eth.chains.base import (
713
MiningChain,
814
)
915
from eth.db.backends.level import LevelDB
1016
from eth.db.backends.memory import MemoryDB
1117
from eth.db.atomic import AtomicDB
18+
from eth.tools.builder.chain import (
19+
build,
20+
byzantium_at,
21+
enable_pow_mining,
22+
genesis,
23+
)
24+
from eth.vm.forks.byzantium import ByzantiumVM
1225

1326
from trinity.db.base import AsyncBaseDB
1427
from trinity.db.chain import AsyncChainDB
1528
from trinity.db.header import AsyncHeaderDB
1629

30+
ZIPPED_FIXTURES_PATH = Path(__file__).parent.parent / 'integration' / 'fixtures'
31+
1732

1833
async def connect_to_peers_loop(peer_pool, nodes):
1934
"""Loop forever trying to connect to one of the given nodes if the pool is not yet full."""
@@ -96,3 +111,54 @@ class FakeAsyncChain(MiningChain):
96111
coro_import_block = coro_import_block
97112
coro_validate_chain = async_passthrough('validate_chain')
98113
coro_validate_receipt = async_passthrough('validate_receipt')
114+
chaindb_class = FakeAsyncChainDB
115+
116+
117+
class ByzantiumTestChain(FakeAsyncChain):
118+
vm_configuration = ((0, ByzantiumVM),)
119+
network_id = 999
120+
121+
122+
FUNDED_ACCT = keys.PrivateKey(
123+
decode_hex("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee"))
124+
125+
126+
def load_mining_chain(db):
127+
GENESIS_PARAMS = {
128+
'coinbase': constants.ZERO_ADDRESS,
129+
'difficulty': 5,
130+
'gas_limit': 3141592,
131+
'timestamp': 1514764800,
132+
}
133+
134+
GENESIS_STATE = {
135+
FUNDED_ACCT.public_key.to_canonical_address(): {
136+
"balance": 100000000000000000,
137+
}
138+
}
139+
140+
return build(
141+
FakeAsyncChain,
142+
byzantium_at(0),
143+
enable_pow_mining(),
144+
genesis(db=db, params=GENESIS_PARAMS, state=GENESIS_STATE),
145+
)
146+
147+
148+
class DBFixture(Enum):
149+
twenty_pow_headers = '20pow_headers.ldb'
150+
151+
152+
def load_fixture_db(db_fixture, db_class=LevelDB):
153+
"""
154+
Extract the database from the zip file to a temp directory, which has two benefits and one cost:
155+
- B1. works with xdist, multiple access to the ldb files at the same time
156+
- B2. prevents dirty-ing the git index
157+
- C1. slows down test, because of time to extract files
158+
"""
159+
assert isinstance(db_fixture, DBFixture)
160+
zipped_path = ZIPPED_FIXTURES_PATH / f"{db_fixture.value}.zip"
161+
162+
with ZipFile(zipped_path, 'r') as zipped, TemporaryDirectory() as tmpdir:
163+
zipped.extractall(tmpdir)
164+
yield db_class(Path(tmpdir) / db_fixture.value)

tests/trinity/core/p2p-proto/test_sync.py

Lines changed: 19 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@
22

33
import pytest
44

5-
from eth_keys import keys
6-
from eth_utils import decode_hex
7-
8-
from eth import constants
9-
from eth.tools.mining import POWMiningMixin
10-
from eth.vm.forks.frontier import FrontierVM
11-
12-
135
from trinity.protocol.eth.servers import ETHRequestServer
146
from trinity.protocol.les.peer import LESPeer
157
from trinity.protocol.les.servers import LightRequestServer
@@ -18,10 +10,13 @@
1810
from trinity.sync.light.chain import LightChainSyncer
1911

2012
from tests.trinity.core.integration_test_helpers import (
21-
FakeAsyncChain,
13+
ByzantiumTestChain,
2214
FakeAsyncChainDB,
2315
FakeAsyncHeaderDB,
2416
FakeAsyncAtomicDB,
17+
load_fixture_db,
18+
load_mining_chain,
19+
DBFixture,
2520
)
2621
from tests.trinity.core.peer_helpers import (
2722
get_directly_linked_peers,
@@ -46,10 +41,10 @@ async def test_fast_syncer(request, event_loop, chaindb_fresh, chaindb_20):
4641
alice_headerdb=FakeAsyncHeaderDB(chaindb_fresh.db),
4742
bob_headerdb=FakeAsyncHeaderDB(chaindb_20.db))
4843
client_peer_pool = MockPeerPoolWithConnectedPeers([client_peer])
49-
client = FastChainSyncer(FrontierTestChain(chaindb_fresh.db), chaindb_fresh, client_peer_pool)
44+
client = FastChainSyncer(ByzantiumTestChain(chaindb_fresh.db), chaindb_fresh, client_peer_pool)
5045
server_peer_pool = MockPeerPoolWithConnectedPeers([server_peer])
5146
server = RegularChainSyncer(
52-
FrontierTestChain(chaindb_20.db),
47+
ByzantiumTestChain(chaindb_20.db),
5348
chaindb_20,
5449
server_peer_pool,
5550
)
@@ -86,12 +81,12 @@ async def test_regular_syncer(request, event_loop, chaindb_fresh, chaindb_20):
8681
alice_headerdb=FakeAsyncHeaderDB(chaindb_fresh.db),
8782
bob_headerdb=FakeAsyncHeaderDB(chaindb_20.db))
8883
client = RegularChainSyncer(
89-
FrontierTestChain(chaindb_fresh.db),
84+
ByzantiumTestChain(chaindb_fresh.db),
9085
chaindb_fresh,
9186
MockPeerPoolWithConnectedPeers([client_peer]))
9287
server_peer_pool = MockPeerPoolWithConnectedPeers([server_peer])
9388
server = RegularChainSyncer(
94-
FrontierTestChain(chaindb_20.db),
89+
ByzantiumTestChain(chaindb_20.db),
9590
chaindb_20,
9691
server_peer_pool,
9792
)
@@ -126,12 +121,12 @@ async def test_light_syncer(request, event_loop, chaindb_fresh, chaindb_20):
126121
alice_headerdb=FakeAsyncHeaderDB(chaindb_fresh.db),
127122
bob_headerdb=FakeAsyncHeaderDB(chaindb_20.db))
128123
client = LightChainSyncer(
129-
FrontierTestChain(chaindb_fresh.db),
124+
ByzantiumTestChain(chaindb_fresh.db),
130125
chaindb_fresh,
131126
MockPeerPoolWithConnectedPeers([client_peer]))
132127
server_peer_pool = MockPeerPoolWithConnectedPeers([server_peer])
133128
server = LightChainSyncer(
134-
FrontierTestChain(chaindb_20.db),
129+
ByzantiumTestChain(chaindb_20.db),
135130
chaindb_20,
136131
server_peer_pool,
137132
)
@@ -157,72 +152,24 @@ def finalizer():
157152

158153

159154
@pytest.fixture
160-
def chaindb_20():
161-
chain = PoWMiningChain.from_genesis(FakeAsyncAtomicDB(), GENESIS_PARAMS, GENESIS_STATE)
162-
for i in range(20):
163-
tx = chain.create_unsigned_transaction(
164-
nonce=i,
165-
gas_price=1234,
166-
gas=1234000,
167-
to=RECEIVER.public_key.to_canonical_address(),
168-
value=i,
169-
data=b'',
170-
)
171-
chain.apply_transaction(tx.as_signed_transaction(SENDER))
172-
chain.mine_block()
155+
def leveldb_20():
156+
yield from load_fixture_db(DBFixture.twenty_pow_headers)
157+
158+
159+
@pytest.fixture
160+
def chaindb_20(leveldb_20):
161+
chain = load_mining_chain(FakeAsyncAtomicDB(leveldb_20))
162+
assert chain.chaindb.get_canonical_head().block_number == 20
173163
return chain.chaindb
174164

175165

176166
@pytest.fixture
177167
def chaindb_fresh():
178-
chain = PoWMiningChain.from_genesis(FakeAsyncAtomicDB(), GENESIS_PARAMS, GENESIS_STATE)
168+
chain = load_mining_chain(FakeAsyncAtomicDB())
179169
assert chain.chaindb.get_canonical_head().block_number == 0
180170
return chain.chaindb
181171

182172

183-
SENDER = keys.PrivateKey(
184-
decode_hex("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee"))
185-
RECEIVER = keys.PrivateKey(
186-
decode_hex("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"))
187-
GENESIS_PARAMS = {
188-
'parent_hash': constants.GENESIS_PARENT_HASH,
189-
'uncles_hash': constants.EMPTY_UNCLE_HASH,
190-
'coinbase': constants.ZERO_ADDRESS,
191-
'transaction_root': constants.BLANK_ROOT_HASH,
192-
'receipt_root': constants.BLANK_ROOT_HASH,
193-
'bloom': 0,
194-
'difficulty': 5,
195-
'block_number': constants.GENESIS_BLOCK_NUMBER,
196-
'gas_limit': 3141592,
197-
'gas_used': 0,
198-
'timestamp': 1514764800,
199-
'extra_data': constants.GENESIS_EXTRA_DATA,
200-
'nonce': constants.GENESIS_NONCE
201-
}
202-
GENESIS_STATE = {
203-
SENDER.public_key.to_canonical_address(): {
204-
"balance": 100000000000000000,
205-
"code": b"",
206-
"nonce": 0,
207-
"storage": {}
208-
}
209-
}
210-
211-
212-
class FrontierTestChain(FakeAsyncChain):
213-
vm_configuration = ((0, FrontierVM),)
214-
chaindb_class = FakeAsyncChainDB
215-
network_id = 999
216-
217-
218-
class POWFrontierVM(POWMiningMixin, FrontierVM):
219-
pass
220-
221-
222-
class PoWMiningChain(FrontierTestChain):
223-
vm_configuration = ((0, POWFrontierVM),)
224-
225-
226173
async def wait_for_head(headerdb, header):
227174
# A full header sync may involve several round trips, so we must be willing to wait a little
228175
# bit for them.
Binary file not shown.

0 commit comments

Comments
 (0)