Skip to content

Commit 6657dfe

Browse files
Bhargavasomucburgdorf
authored andcommitted
Add some more tests for Rewards
1 parent 6abf213 commit 6657dfe

File tree

1 file changed

+215
-1
lines changed

1 file changed

+215
-1
lines changed

tests/core/vm/test_rewards.py

Lines changed: 215 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import pytest
22

33
from eth_utils import (
4-
to_wei
4+
to_wei,
5+
ValidationError,
56
)
67

78
from eth.chains.base import (
@@ -12,6 +13,7 @@
1213
build,
1314
disable_pow_check,
1415
mine_block,
16+
mine_blocks,
1517
byzantium_at,
1618
frontier_at,
1719
homestead_at,
@@ -82,3 +84,215 @@ def test_rewards(vm_fn, miner_1_balance, miner_2_balance):
8284
# But we also ensure the balance matches the numbers that we calculated on paper
8385
assert coinbase_balance == to_wei(miner_1_balance, 'ether')
8486
assert other_miner_balance == to_wei(miner_2_balance, 'ether')
87+
88+
89+
@pytest.mark.parametrize(
90+
'vm_fn, fork_at_block_number, miner_1_balance, miner_2_balance',
91+
(
92+
(frontier_at, 3, 50.15625, 1.25),
93+
(frontier_at, 4, 50.15625, 1.875),
94+
(frontier_at, 5, 50.15625, 2.5),
95+
(frontier_at, 6, 50.15625, 3.125),
96+
(frontier_at, 7, 50.15625, 3.75),
97+
(frontier_at, 8, 50.15625, 4.375),
98+
99+
(homestead_at, 3, 50.15625, 1.25),
100+
(homestead_at, 4, 50.15625, 1.875),
101+
(homestead_at, 5, 50.15625, 2.5),
102+
(homestead_at, 6, 50.15625, 3.125),
103+
(homestead_at, 7, 50.15625, 3.75),
104+
(homestead_at, 8, 50.15625, 4.375),
105+
106+
(tangerine_whistle_at, 3, 50.15625, 1.25),
107+
(tangerine_whistle_at, 4, 50.15625, 1.875),
108+
(tangerine_whistle_at, 5, 50.15625, 2.5),
109+
(tangerine_whistle_at, 6, 50.15625, 3.125),
110+
(tangerine_whistle_at, 7, 50.15625, 3.75),
111+
(tangerine_whistle_at, 8, 50.15625, 4.375),
112+
113+
(spurious_dragon_at, 3, 50.15625, 1.25),
114+
(spurious_dragon_at, 4, 50.15625, 1.875),
115+
(spurious_dragon_at, 5, 50.15625, 2.5),
116+
(spurious_dragon_at, 6, 50.15625, 3.125),
117+
(spurious_dragon_at, 7, 50.15625, 3.75),
118+
(spurious_dragon_at, 8, 50.15625, 4.375),
119+
120+
(byzantium_at, 3, 30.09375, 0.75),
121+
(byzantium_at, 4, 30.09375, 1.125),
122+
(byzantium_at, 5, 30.09375, 1.5),
123+
(byzantium_at, 6, 30.09375, 1.875),
124+
(byzantium_at, 7, 30.09375, 2.25),
125+
(byzantium_at, 8, 30.09375, 2.625),
126+
127+
(constantinople_at, 3, 20.0625, 0.5),
128+
(constantinople_at, 4, 20.0625, 0.75),
129+
(constantinople_at, 5, 20.0625, 1),
130+
(constantinople_at, 6, 20.0625, 1.25),
131+
(constantinople_at, 7, 20.0625, 1.5),
132+
(constantinople_at, 8, 20.0625, 1.75),
133+
)
134+
)
135+
def test_rewards_uncle_created_at_different_generations(
136+
vm_fn,
137+
fork_at_block_number,
138+
miner_1_balance,
139+
miner_2_balance):
140+
OTHER_MINER_ADDRESS = 20 * b'\x01'
141+
TOTAL_BLOCKS_CANONICAL_CHAIN = 10
142+
143+
chain = build(
144+
MiningChain,
145+
vm_fn(0),
146+
disable_pow_check(),
147+
genesis(),
148+
mine_blocks(TOTAL_BLOCKS_CANONICAL_CHAIN - 1),
149+
)
150+
151+
fork_chain = build(
152+
chain,
153+
at_block_number(fork_at_block_number),
154+
mine_block(extra_data=b'fork-it!', coinbase=OTHER_MINER_ADDRESS), # fork 2
155+
)
156+
157+
# we don't use canonical head here because the fork chain is non-canonical.
158+
uncle = fork_chain.get_block_header_by_hash(fork_chain.header.parent_hash)
159+
assert uncle.block_number == fork_at_block_number + 1
160+
161+
chain = build(
162+
chain,
163+
mine_block(uncles=[uncle]),
164+
)
165+
166+
header = chain.get_canonical_head()
167+
block = chain.get_block_by_hash(header.hash)
168+
169+
vm = chain.get_vm()
170+
coinbase_balance = vm.state.account_db.get_balance(block.header.coinbase)
171+
other_miner_balance = vm.state.account_db.get_balance(uncle.coinbase)
172+
173+
# We first test if the balance matches what we would determine
174+
# if we made all the API calls involved ourselves.
175+
assert coinbase_balance == (vm.get_block_reward() *
176+
TOTAL_BLOCKS_CANONICAL_CHAIN +
177+
vm.get_nephew_reward())
178+
179+
assert other_miner_balance == vm.get_uncle_reward(block.number, uncle)
180+
181+
# But we also ensure the balance matches the numbers that we calculated on paper
182+
assert coinbase_balance == to_wei(miner_1_balance, 'ether')
183+
assert other_miner_balance == to_wei(miner_2_balance, 'ether')
184+
185+
186+
@pytest.mark.parametrize(
187+
'vm_fn',
188+
(
189+
frontier_at,
190+
homestead_at,
191+
tangerine_whistle_at,
192+
spurious_dragon_at,
193+
byzantium_at,
194+
constantinople_at,
195+
)
196+
)
197+
def test_uncle_block_inclusion_validity(vm_fn):
198+
# This test ensures that a forked block which is behind by
199+
# more than 6 layers cannot act as an ancestor to the current block
200+
201+
OTHER_MINER_ADDRESS = 20 * b'\x01'
202+
203+
chain = build(
204+
MiningChain,
205+
vm_fn(0),
206+
disable_pow_check(),
207+
genesis(),
208+
mine_block(), # 1
209+
mine_block(), # 2
210+
)
211+
212+
fork_chain = build(
213+
chain,
214+
at_block_number(1),
215+
mine_block(extra_data=b'fork-it!', coinbase=OTHER_MINER_ADDRESS), # fork 2
216+
)
217+
218+
# we don't use canonical head here because the fork chain is non-canonical.
219+
uncle = fork_chain.get_block_header_by_hash(fork_chain.header.parent_hash)
220+
assert uncle.block_number == 2
221+
222+
with pytest.raises(ValidationError):
223+
chain = build(
224+
chain,
225+
# Mines blocks from 3 to 8 (both numbers inclusive)
226+
mine_blocks(6),
227+
# Mine block 9 with uncle
228+
mine_block(uncles=[uncle]),
229+
)
230+
231+
232+
@pytest.mark.parametrize(
233+
'vm_fn_uncle, vm_fn_nephew, miner_1_balance, miner_2_balance',
234+
(
235+
(frontier_at, homestead_at, 50.15625, 1.25),
236+
(homestead_at, tangerine_whistle_at, 50.15625, 1.25),
237+
(tangerine_whistle_at, spurious_dragon_at, 50.15625, 1.25),
238+
(spurious_dragon_at, byzantium_at, 36.09375, 0.75),
239+
(byzantium_at, constantinople_at, 23.0625, 0.5),
240+
)
241+
)
242+
def test_rewards_nephew_uncle_different_vm(
243+
vm_fn_uncle,
244+
vm_fn_nephew,
245+
miner_1_balance,
246+
miner_2_balance):
247+
OTHER_MINER_ADDRESS = 20 * b'\x01'
248+
TOTAL_BLOCKS_CANONICAL_CHAIN = 10
249+
VM_CHANGE_BLOCK_NUMBER = 4
250+
251+
chain = build(
252+
MiningChain,
253+
vm_fn_uncle(0),
254+
vm_fn_nephew(VM_CHANGE_BLOCK_NUMBER),
255+
disable_pow_check(),
256+
genesis(),
257+
mine_blocks(TOTAL_BLOCKS_CANONICAL_CHAIN - 1),
258+
)
259+
260+
fork_chain = build(
261+
chain,
262+
at_block_number(3),
263+
mine_block(extra_data=b'fork-it!', coinbase=OTHER_MINER_ADDRESS), # fork 2
264+
)
265+
266+
# we don't use canonical head here because the fork chain is non-canonical.
267+
uncle = fork_chain.get_block_header_by_hash(fork_chain.header.parent_hash)
268+
assert uncle.block_number == 4
269+
270+
chain = build(
271+
chain,
272+
mine_block(uncles=[uncle]),
273+
)
274+
275+
header = chain.get_canonical_head()
276+
block = chain.get_block_by_hash(header.hash)
277+
assert len(block.uncles) == 1
278+
assert block.uncles[0] == uncle
279+
280+
vm = chain.get_vm()
281+
coinbase_balance = vm.state.account_db.get_balance(block.header.coinbase)
282+
other_miner_balance = vm.state.account_db.get_balance(uncle.coinbase)
283+
284+
uncle_vm = chain.get_vm_class_for_block_number(0)
285+
nephew_vm = chain.get_vm_class_for_block_number(VM_CHANGE_BLOCK_NUMBER)
286+
287+
# We first test if the balance matches what we would determine
288+
# if we made all the API calls involved ourselves.
289+
assert coinbase_balance == (
290+
uncle_vm.get_block_reward() * 3 +
291+
nephew_vm.get_block_reward() * (TOTAL_BLOCKS_CANONICAL_CHAIN - 3) +
292+
vm.get_nephew_reward()
293+
)
294+
assert other_miner_balance == vm.get_uncle_reward(block.number, uncle)
295+
296+
# But we also ensure the balance matches the numbers that we calculated on paper
297+
assert coinbase_balance == to_wei(miner_1_balance, 'ether')
298+
assert other_miner_balance == to_wei(miner_2_balance, 'ether')

0 commit comments

Comments
 (0)