|
7 | 7 | import asyncio
|
8 | 8 | from collections import deque
|
9 | 9 | import traceback
|
10 |
| -from typing import Callable, Iterator, List |
| 10 | +from typing import Callable, Iterator, List, Iterable, Literal |
11 | 11 | import time
|
12 | 12 | from abc import ABC, abstractmethod
|
13 | 13 | import threading
|
|
29 | 29 | Validator,
|
30 | 30 | )
|
31 | 31 | from backend.node.base import Node
|
32 |
| -from backend.node.types import ExecutionMode, Receipt, Vote, ExecutionResultStatus |
| 32 | +from backend.node.types import ( |
| 33 | + ExecutionMode, |
| 34 | + Receipt, |
| 35 | + Vote, |
| 36 | + ExecutionResultStatus, |
| 37 | + PendingTransaction, |
| 38 | +) |
33 | 39 | from backend.protocol_rpc.message_handler.base import MessageHandler
|
34 | 40 | from backend.protocol_rpc.message_handler.types import (
|
35 | 41 | LogEvent,
|
@@ -107,6 +113,7 @@ def contract_snapshot_factory(
|
107 | 113 | ret = ContractSnapshot(None, session)
|
108 | 114 | ret.contract_address = transaction.to_address
|
109 | 115 | ret.contract_code = transaction.data["contract_code"]
|
| 116 | + ret.balance = transaction.value or 0 |
110 | 117 | ret.states = {"accepted": {}, "finalized": {}}
|
111 | 118 | ret.encoded_state = ret.states["accepted"]
|
112 | 119 | return ret
|
@@ -1861,6 +1868,8 @@ async def handle(self, context):
|
1861 | 1868 | accepted_state=leader_receipt.contract_state
|
1862 | 1869 | )
|
1863 | 1870 |
|
| 1871 | + _emit_transactions(context, leader_receipt.pending_transactions, "accepted") |
| 1872 | + |
1864 | 1873 | # Set the transaction appeal undetermined status to false and return appeal status
|
1865 | 1874 | if context.transaction.appeal_undetermined:
|
1866 | 1875 | context.transactions_processor.set_transaction_appeal_undetermined(
|
@@ -2009,62 +2018,69 @@ async def handle(self, context):
|
2009 | 2018 |
|
2010 | 2019 | if context.transaction.status != TransactionStatus.UNDETERMINED:
|
2011 | 2020 | # Insert pending transactions generated by contract-to-contract calls
|
2012 |
| - pending_transactions = ( |
2013 |
| - context.transaction.consensus_data.leader_receipt.pending_transactions |
| 2021 | + _emit_transactions( |
| 2022 | + context, |
| 2023 | + context.transaction.consensus_data.leader_receipt.pending_transactions, |
| 2024 | + "finalized", |
2014 | 2025 | )
|
2015 |
| - for pending_transaction in pending_transactions: |
2016 |
| - nonce = context.transactions_processor.get_transaction_count( |
2017 |
| - context.transaction.to_address |
| 2026 | + |
| 2027 | + |
| 2028 | +def _emit_transactions( |
| 2029 | + context: TransactionContext, |
| 2030 | + pending_transactions: Iterable[PendingTransaction], |
| 2031 | + on: Literal["accepted", "finalized"], |
| 2032 | +): |
| 2033 | + for pending_transaction in filter(lambda t: t.on == on, pending_transactions): |
| 2034 | + nonce = context.transactions_processor.get_transaction_count( |
| 2035 | + context.transaction.to_address |
| 2036 | + ) |
| 2037 | + data: dict |
| 2038 | + transaction_type: TransactionType |
| 2039 | + if pending_transaction.is_deploy(): |
| 2040 | + transaction_type = TransactionType.DEPLOY_CONTRACT |
| 2041 | + new_contract_address: str |
| 2042 | + if pending_transaction.salt_nonce == 0: |
| 2043 | + # NOTE: this address is random, which doesn't 100% align with consensus spec |
| 2044 | + new_contract_address = ( |
| 2045 | + context.accounts_manager.create_new_account().address |
2018 | 2046 | )
|
2019 |
| - data: dict |
2020 |
| - transaction_type: TransactionType |
2021 |
| - if pending_transaction.is_deploy(): |
2022 |
| - transaction_type = TransactionType.DEPLOY_CONTRACT |
2023 |
| - new_contract_address: str |
2024 |
| - if pending_transaction.salt_nonce == 0: |
2025 |
| - # NOTE: this address is random, which doesn't 100% align with consensus spec |
2026 |
| - new_contract_address = ( |
2027 |
| - context.accounts_manager.create_new_account().address |
2028 |
| - ) |
2029 |
| - else: |
2030 |
| - from eth_utils.crypto import keccak |
2031 |
| - from backend.node.types import Address |
2032 |
| - from backend.node.base import SIMULATOR_CHAIN_ID |
2033 |
| - |
2034 |
| - arr = bytearray() |
2035 |
| - arr.append(1) |
2036 |
| - arr.extend(Address(context.transaction.to_address).as_bytes) |
2037 |
| - arr.extend( |
2038 |
| - pending_transaction.salt_nonce.to_bytes( |
2039 |
| - 32, "big", signed=False |
2040 |
| - ) |
2041 |
| - ) |
2042 |
| - arr.extend(SIMULATOR_CHAIN_ID.to_bytes(32, "big", signed=False)) |
2043 |
| - new_contract_address = Address(keccak(arr)[:20]).as_hex |
2044 |
| - context.accounts_manager.create_new_account_with_address( |
2045 |
| - new_contract_address |
2046 |
| - ) |
2047 |
| - pending_transaction.address = new_contract_address |
2048 |
| - data = { |
2049 |
| - "contract_address": new_contract_address, |
2050 |
| - "contract_code": pending_transaction.code, |
2051 |
| - "calldata": pending_transaction.calldata, |
2052 |
| - } |
2053 |
| - else: |
2054 |
| - transaction_type = TransactionType.RUN_CONTRACT |
2055 |
| - data = { |
2056 |
| - "calldata": pending_transaction.calldata, |
2057 |
| - } |
2058 |
| - context.transactions_processor.insert_transaction( |
2059 |
| - context.transaction.to_address, # new calls are done by the contract |
2060 |
| - pending_transaction.address, |
2061 |
| - data, |
2062 |
| - value=0, # we only handle EOA transfers at the moment, so no value gets transferred |
2063 |
| - type=transaction_type.value, |
2064 |
| - nonce=nonce, |
2065 |
| - leader_only=context.transaction.leader_only, # Cascade |
2066 |
| - triggered_by_hash=context.transaction.hash, |
| 2047 | + else: |
| 2048 | + from eth_utils.crypto import keccak |
| 2049 | + from backend.node.types import Address |
| 2050 | + from backend.node.base import SIMULATOR_CHAIN_ID |
| 2051 | + |
| 2052 | + arr = bytearray() |
| 2053 | + arr.append(1) |
| 2054 | + arr.extend(Address(context.transaction.to_address).as_bytes) |
| 2055 | + arr.extend( |
| 2056 | + pending_transaction.salt_nonce.to_bytes(32, "big", signed=False) |
| 2057 | + ) |
| 2058 | + arr.extend(SIMULATOR_CHAIN_ID.to_bytes(32, "big", signed=False)) |
| 2059 | + new_contract_address = Address(keccak(arr)[:20]).as_hex |
| 2060 | + context.accounts_manager.create_new_account_with_address( |
| 2061 | + new_contract_address |
2067 | 2062 | )
|
| 2063 | + pending_transaction.address = new_contract_address |
| 2064 | + data = { |
| 2065 | + "contract_address": new_contract_address, |
| 2066 | + "contract_code": pending_transaction.code, |
| 2067 | + "calldata": pending_transaction.calldata, |
| 2068 | + } |
| 2069 | + else: |
| 2070 | + transaction_type = TransactionType.RUN_CONTRACT |
| 2071 | + data = { |
| 2072 | + "calldata": pending_transaction.calldata, |
| 2073 | + } |
| 2074 | + context.transactions_processor.insert_transaction( |
| 2075 | + context.transaction.to_address, # new calls are done by the contract |
| 2076 | + pending_transaction.address, |
| 2077 | + data, |
| 2078 | + value=0, # we only handle EOA transfers at the moment, so no value gets transferred |
| 2079 | + type=transaction_type.value, |
| 2080 | + nonce=nonce, |
| 2081 | + leader_only=context.transaction.leader_only, # Cascade |
| 2082 | + triggered_by_hash=context.transaction.hash, |
| 2083 | + ) |
2068 | 2084 |
|
2069 | 2085 |
|
2070 | 2086 | def rotate(nodes: list) -> Iterator[list]:
|
|
0 commit comments