diff --git a/pyproject.toml b/pyproject.toml index 48c9601af..2c67ec768 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ markers = [ "state_update", "transaction_trace", "general_workflow", + "timestamps", "web3_messaging" ] junit_family="xunit1" diff --git a/starknet_devnet/starknet_wrapper.py b/starknet_devnet/starknet_wrapper.py index 1c81be17d..ee5375c81 100644 --- a/starknet_devnet/starknet_wrapper.py +++ b/starknet_devnet/starknet_wrapper.py @@ -11,7 +11,7 @@ import dill as pickle from starkware.starknet.business_logic.internal_transaction import InternalInvokeFunction -from starkware.starknet.business_logic.state.state import CarriedState +from starkware.starknet.business_logic.state.state import CarriedState, BlockInfo from starkware.starknet.definitions.transaction_type import TransactionType from starkware.starknet.services.api.gateway.contract_address import calculate_contract_address from starkware.starknet.services.api.gateway.transaction import InvokeFunction, Deploy, Transaction @@ -109,6 +109,13 @@ async def __update_state(self): previous_state = self.__current_carried_state assert previous_state is not None current_carried_state = (await self.__get_state()).state + + current_carried_state.block_info = BlockInfo( + block_number=current_carried_state.block_info.block_number, + gas_price=current_carried_state.block_info.gas_price, + block_timestamp=int(time.time()), + ) + updated_shared_state = await current_carried_state.shared_state.apply_state_updates( ffc=current_carried_state.ffc, previous_carried_state=previous_state, @@ -319,7 +326,7 @@ async def __generate_block(self, tx_wrapper: TransactionWrapper): state = await self.__get_state() state_root = await self.__get_state_root() block_number = self.get_number_of_blocks() - timestamp = int(time.time()) + timestamp = state.state.block_info.block_timestamp signature = [] if "signature" in tx_wrapper.transaction["transaction"]: signature = [int(sig_part, 16) for sig_part in tx_wrapper.transaction["transaction"]["signature"]] diff --git a/test/contracts/cairo/timestamp.cairo b/test/contracts/cairo/timestamp.cairo new file mode 100644 index 000000000..9685577ee --- /dev/null +++ b/test/contracts/cairo/timestamp.cairo @@ -0,0 +1,14 @@ +%lang starknet + +from starkware.cairo.common.cairo_builtins import HashBuiltin +from starkware.starknet.common.syscalls import get_block_timestamp + +@view +func get_timestamp{ + syscall_ptr : felt*, + pedersen_ptr : HashBuiltin*, + range_check_ptr + }() -> (ts: felt): + let (ts) = get_block_timestamp() + return (ts) +end diff --git a/test/test_timestamps.py b/test/test_timestamps.py new file mode 100644 index 000000000..c55a53fdf --- /dev/null +++ b/test/test_timestamps.py @@ -0,0 +1,50 @@ +""" +Test block timestamps +""" + +import pytest + +from .shared import ARTIFACTS_PATH +from .util import devnet_in_background, deploy, call, get_block + +TS_CONTRACT_PATH = f"{ARTIFACTS_PATH}/timestamp.cairo/timestamp.json" +TS_ABI_PATH = f"{ARTIFACTS_PATH}/timestamp.cairo/timestamp_abi.json" + + +def deploy_ts_contract(): + """Deploys the timestamp contract""" + return deploy(TS_CONTRACT_PATH) + +def get_ts_from_contract(address): + """Returns the timestamp of the contract""" + return int(call( + function="get_timestamp", + address=address, + abi_path=TS_ABI_PATH, + )) + +def get_ts_from_last_block(): + """Returns the timestamp of the last block""" + return get_block(parse=True)["timestamp"] + +@pytest.mark.timestamps +@devnet_in_background() +def test_timestamps(): + """Test timestamp""" + deploy_info = deploy_ts_contract() + ts_after_deploy = get_ts_from_last_block() + + ts_from_first_call = get_ts_from_contract(deploy_info["address"]) + + assert ts_after_deploy == ts_from_first_call + + # deploy another contract contract to generate a new block + deploy_ts_contract() + ts_after_second_deploy = get_ts_from_last_block() + + assert ts_after_second_deploy > ts_from_first_call + + ts_from_second_call = get_ts_from_contract(deploy_info["address"]) + + assert ts_after_second_deploy == ts_from_second_call + assert ts_from_second_call > ts_from_first_call