@@ -273,6 +273,13 @@ def fixture_vm_class(fixture_data):
273273 raise ValueError ("Unknown Fork Name: {0}" .format (fork_name ))
274274
275275
276+ PRE_STATE_CLEARING_VMS = (
277+ FrontierVMForTesting ,
278+ HomesteadVMForTesting ,
279+ TangerineWhistleVMForTesting ,
280+ )
281+
282+
276283def test_state_fixtures (fixture , fixture_vm_class ):
277284 header = BlockHeader (
278285 coinbase = fixture ['env' ]['currentCoinbase' ],
@@ -320,19 +327,44 @@ def test_state_fixtures(fixture, fixture_vm_class):
320327 r = r ,
321328 s = s ,
322329 )
330+ else :
331+ raise Exception ("Invariant: No transaction specified" )
323332
324333 try :
325334 header , receipt , computation = vm .apply_transaction (vm .block .header , transaction )
326- transactions = vm .block .transactions + (transaction , )
327- receipts = vm .block .get_receipts (chaindb ) + (receipt , )
328- block = vm .set_block_transactions (vm .block , header , transactions , receipts )
329335 except ValidationError as err :
330- block = vm .block
331- transaction_error = err
332336 logger .warning ("Got transaction error" , exc_info = True )
337+ transaction_error = err
333338 else :
334339 transaction_error = False
335340
341+ transactions = vm .block .transactions + (transaction , )
342+ receipts = vm .block .get_receipts (chaindb ) + (receipt , )
343+ vm .block = vm .set_block_transactions (vm .block , header , transactions , receipts )
344+ finally :
345+ # This is necessary due to the manner in which the state tests are
346+ # generated. State tests are generated from the BlockChainTest tests
347+ # in which these transactions are included in the larger context of a
348+ # block and thus, the mechanisms which would touch/create/clear the
349+ # coinbase account based on the mining reward are present during test
350+ # generation, but not part of the execution, thus we must artificially
351+ # create the account in VMs prior to the state clearing rules,
352+ # as well as conditionally cleaning up the coinbase account when left
353+ # empty in VMs after the state clearing rules came into effect.
354+ # Related change in geth:
355+ # https://github.com/ethereum/go-ethereum/commit/32f28a9360d26a661d55915915f12fd3c70f012b#diff-f53696be8527ac422b8d4de7c8e945c1R149 # noqa: E501
356+
357+ if isinstance (vm , PRE_STATE_CLEARING_VMS ):
358+ state .account_db .touch_account (vm .block .header .coinbase )
359+ state .account_db .persist ()
360+ vm .block = vm .block .copy (header = vm .block .header .copy (state_root = state .state_root ))
361+ elif state .account_db .account_is_empty (vm .block .header .coinbase ):
362+ state .account_db .delete_account (vm .block .header .coinbase )
363+ state .account_db .persist ()
364+ vm .block = vm .block .copy (header = vm .block .header .copy (state_root = state .state_root ))
365+
366+ block = vm .block
367+
336368 if not transaction_error :
337369 log_entries = computation .get_log_entries ()
338370 actual_logs_hash = hash_log_entries (log_entries )
0 commit comments