Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sandbox): fast forward timestamp and epoch height #6211

Merged
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
f9aa23f
Added fast-forwarding to sandbox
ChaoticTempest Jan 21, 2022
232e901
Changed name to delta_height for better clarity
ChaoticTempest Jan 21, 2022
c9f9492
Remove print statements
ChaoticTempest Jan 21, 2022
85eb896
Cargo format
ChaoticTempest Jan 21, 2022
b70475a
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Jan 21, 2022
9b0d8ed
Added sandbox fast forward test
ChaoticTempest Jan 21, 2022
f5b1eb1
Move import into inplaced location as full path
ChaoticTempest Jan 21, 2022
691a2dc
Move other sandbox imports into inplaced locations
ChaoticTempest Jan 22, 2022
f35d1a5
Added forwarded timestmaps for sandbox after fast-forwarding
ChaoticTempest Jan 27, 2022
31a9397
Change visibility of fastforward delta
ChaoticTempest Jan 27, 2022
0a4631b
Update epoch_height based on block info for sandbox
ChaoticTempest Jan 27, 2022
d7370d0
Correct timestamp after each block produced after forwarding
ChaoticTempest Jan 28, 2022
671350d
Added integration test for timestamp
ChaoticTempest Jan 28, 2022
a001fd2
Cargo fmt
ChaoticTempest Jan 28, 2022
6cb23f0
Added overflow panic for sandbox_delta_time
ChaoticTempest Jan 28, 2022
f6b18e6
Merge branch 'master' of github.com:near/nearcore into phuong/sandbox…
ChaoticTempest Feb 3, 2022
df6fa4e
Fix merge conflict typo
ChaoticTempest Feb 4, 2022
1eec9d2
Use accrued delta height to update timestamps
ChaoticTempest Feb 4, 2022
f8cc241
Update fast_forward pytest w/ time travel assertions
ChaoticTempest Feb 4, 2022
cc3872c
Merge branch 'master' of github.com:near/nearcore into phuong/sandbox…
ChaoticTempest Feb 4, 2022
61e168a
Fix formatting and another merge that slipped in
ChaoticTempest Feb 4, 2022
15836ad
Address comments
ChaoticTempest Feb 5, 2022
864a20d
Correct typo & use wait_for_blocks
ChaoticTempest Feb 7, 2022
f9a507c
Merge branch 'master' of github.com:near/nearcore into phuong/sandbox…
ChaoticTempest Feb 7, 2022
17a4518
Removed redundant test
ChaoticTempest Feb 8, 2022
b7d6fb4
Merge branch 'master' of github.com:near/nearcore into phuong/sandbox…
ChaoticTempest Feb 8, 2022
5d2de98
Update epoch height calculation & add unit test
ChaoticTempest Feb 11, 2022
b66850d
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Feb 11, 2022
8adb77f
Added block hash fix and added in more pytest checks
ChaoticTempest Mar 16, 2022
0158ad1
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Mar 16, 2022
3e4f833
Fix typo
ChaoticTempest Mar 16, 2022
79e1a25
Added new way to fast forward wrt epoch boundaries
ChaoticTempest Mar 24, 2022
427652f
Added timeout for fast-forward to complete
ChaoticTempest Mar 24, 2022
eab87db
Added epoch boundary test
ChaoticTempest Mar 24, 2022
07775d7
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Mar 24, 2022
6a1903d
Remove sandbox feature from epoch_manager
ChaoticTempest Mar 24, 2022
39f429b
Remove outdated integration test
ChaoticTempest Mar 24, 2022
7bc2983
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Mar 24, 2022
bf98f33
Cleanup sandbox related code in chain/client.rs
ChaoticTempest Mar 25, 2022
832a604
Added large constant for sandbox acceptable time diff
ChaoticTempest Mar 28, 2022
7c53fdc
Cleanup and added pre/post_block_production methods
ChaoticTempest Mar 28, 2022
d6f3261
Cleaned up block produce logic
ChaoticTempest Mar 28, 2022
e3634c6
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Mar 28, 2022
625e036
Added extra produce block argument
ChaoticTempest Mar 28, 2022
d9e674c
Some more cleanup
ChaoticTempest Mar 29, 2022
3e6aa18
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Mar 29, 2022
7e0761d
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Mar 30, 2022
98d1d50
Merge branch 'phuong/sandbox-fast-forward-timestamp-and-epoch-height'…
ChaoticTempest Mar 30, 2022
2a1ca7f
Adjusted raw timestamp type for Duration type
ChaoticTempest Mar 31, 2022
8170d09
Changed fastforward_delta to not be an Option type
ChaoticTempest Mar 31, 2022
66adcad
Updated to Duration type
ChaoticTempest Mar 31, 2022
83203a0
Merge branch 'master' of https://github.com/near/nearcore into phuong…
ChaoticTempest Mar 31, 2022
0d90208
Merge branch 'master' into phuong/sandbox-fast-forward-timestamp-and-…
ChaoticTempest Apr 1, 2022
c1a31d6
Merge master into phuong/sandbox-fast-forward-timestamp-and-epoch-height
near-bulldozer[bot] Apr 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions chain/chain/src/chain.rs
Expand Up @@ -91,7 +91,12 @@ pub const NUM_ORPHAN_ANCESTORS_CHECK: u64 = 3;
// It should almost never be hit
const MAX_ORPHAN_MISSING_CHUNKS: usize = 5;

/// 10000 years in seconds. Big constant for sandbox to allow time traveling.
#[cfg(feature = "sandbox")]
const ACCEPTABLE_TIME_DIFFERENCE: i64 = 60 * 60 * 24 * 365 * 10000;

/// Refuse blocks more than this many block intervals in the future (as in bitcoin).
#[cfg(not(feature = "sandbox"))]
const ACCEPTABLE_TIME_DIFFERENCE: i64 = 12 * 10;

/// Over this block height delta in advance if we are not chunk producer - route tx to upcoming validators.
Expand Down Expand Up @@ -2220,7 +2225,7 @@ impl Chain {
blocks_catch_up_state: &mut BlocksCatchUpState,
block_catch_up_scheduler: &dyn Fn(BlockCatchUpRequest),
) -> Result<(), Error> {
debug!(target:"catchup", "catch up blocks: pending blocks: {:?}, processed {:?}, scheduled: {:?}, done: {:?}",
debug!(target:"catchup", "catch up blocks: pending blocks: {:?}, processed {:?}, scheduled: {:?}, done: {:?}",
blocks_catch_up_state.pending_blocks, blocks_catch_up_state.processed_blocks.keys().collect::<Vec<_>>(),
blocks_catch_up_state.scheduled_blocks.keys().collect::<Vec<_>>(), blocks_catch_up_state.done_blocks.len());
for (queued_block, (saved_store_update, results)) in
Expand Down Expand Up @@ -4383,7 +4388,7 @@ impl<'a> ChainUpdate<'a> {
provenance: &Provenance,
on_challenge: &mut dyn FnMut(ChallengeBody),
) -> Result<(), Error> {
// Refuse blocks from the too distant future.
// Refuse blocks from the too distant future
if header.timestamp() > Clock::utc() + Duration::seconds(ACCEPTABLE_TIME_DIFFERENCE) {
return Err(ErrorKind::InvalidBlockFutureTime(header.timestamp()).into());
}
Expand Down
1 change: 1 addition & 0 deletions chain/chain/src/tests/simple_chain.rs
Expand Up @@ -116,6 +116,7 @@ fn build_chain_with_orhpans() {
&*signer,
*last_block.header().next_bp_hash(),
CryptoHash::default(),
None,
);
assert_eq!(chain.process_block_test(&None, block).unwrap_err().kind(), ErrorKind::Orphan);
assert_eq!(
Expand Down
40 changes: 36 additions & 4 deletions chain/client/src/client.rs
Expand Up @@ -67,6 +67,10 @@ pub struct Client {
#[cfg(feature = "test_features")]
pub adv_produce_blocks_only_valid: bool,

/// Fast Forward accrued delta height used to calculate fast forwarded timestamps for each block.
#[cfg(feature = "sandbox")]
pub(crate) accrued_fastforward_delta: near_primitives::types::BlockHeightDelta,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, if only we did the work for virtualizing time, than we'd be able to express this in a much cleaner way, by just making the time go forward faster.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this was definitely a hack to circumvent that. Maybe we can revisit this in the future, but for now, this was pretty simple to do just for contract testing side of things


pub config: ClientConfig,
pub sync_status: SyncStatus,
pub chain: Chain,
Expand Down Expand Up @@ -172,6 +176,8 @@ impl Client {
adv_produce_blocks: false,
#[cfg(feature = "test_features")]
adv_produce_blocks_only_valid: false,
#[cfg(feature = "sandbox")]
accrued_fastforward_delta: 0,
config,
sync_status,
chain,
Expand Down Expand Up @@ -445,6 +451,22 @@ impl Client {
prev_next_bp_hash
};

#[cfg(feature = "sandbox")]
let delta_time = self.sandbox_delta_time();
ChaoticTempest marked this conversation as resolved.
Show resolved Hide resolved

let at = to_timestamp(Clock::utc());
let timestamp_override = Option::<u64>::None;

// Sandbox can override the timestamp normally produced from a Block. This new timestamp
// is from when a fast_forward request that has been processed.
#[cfg(feature = "sandbox")]
let (at, timestamp_override) = if delta_time > 0 {
let at = at + delta_time;
(at, Some(at))
} else {
(at, timestamp_override)
};

// Get block extra from previous block.
let mut block_merkle_tree =
self.chain.mut_store().get_block_merkle_tree(&prev_hash)?.clone();
Expand Down Expand Up @@ -514,13 +536,11 @@ impl Client {
&*validator_signer,
next_bp_hash,
block_merkle_root,
timestamp_override,
);

// Update latest known even before returning block out, to prevent race conditions.
self.chain.mut_store().save_latest_known(LatestKnown {
height: next_height,
seen: to_timestamp(Clock::utc()),
})?;
self.chain.mut_store().save_latest_known(LatestKnown { height: next_height, seen: at })?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I don't like that at here at LatestKnown and the timestamp of the block are different, but this is pre-existing behavior. So, no need to change anything in this PR, but I woneder if the following change makes sense as a follow-up:

diff --git a/chain/client/src/client.rs b/chain/client/src/client.rs
index c6091c459..f5982fa6b 100644
--- a/chain/client/src/client.rs
+++ b/chain/client/src/client.rs
@@ -451,21 +451,10 @@ impl Client {
             prev_next_bp_hash
         };
 
-        #[cfg(feature = "sandbox")]
-        let delta_time = self.sandbox_delta_time();
-
-        let at = to_timestamp(Clock::utc());
+        #[cfg(not(feature = "sandbox"))]
         let timestamp_override = Option::<u64>::None;
-
-        // Sandbox can override the timestamp normally produced from a Block. This new timestamp
-        // is from when a fast_forward request that has been processed.
         #[cfg(feature = "sandbox")]
-        let (at, timestamp_override) = if delta_time > 0 {
-            let at = at + delta_time;
-            (at, Some(at))
-        } else {
-            (at, timestamp_override)
-        };
+        let timestamp_override = to_timetamp(Clock::now()) + self.sandbox_delta_time();
 
         // Get block extra from previous block.
         let mut block_merkle_tree =
@@ -538,9 +527,11 @@ impl Client {
             block_merkle_root,
             timestamp_override,
         );
+        let latest_known =
+            LatestKnown { height: block.header().height(), seen: block.header().timestamp() };
 
         // Update latest known even before returning block out, to prevent race conditions.
-        self.chain.mut_store().save_latest_known(LatestKnown { height: next_height, seen: at })?;
+        self.chain.mut_store().save_latest_known(latest_known)?;
 
         metrics::BLOCK_PRODUCED_TOTAL.inc();
 

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up changing it to what you suggested, since I had to change it already for swapping the return type of sandbox_delta_time to Duration. And pretty much same logic at the end of the day too, so it should work the same


metrics::BLOCK_PRODUCED_TOTAL.inc();

Expand Down Expand Up @@ -960,6 +980,18 @@ impl Client {
Ok(())
}

/// Gets the advanced timestamp delta in nanoseconds for sandbox once it has been fast-forwarded
#[cfg(feature = "sandbox")]
pub fn sandbox_delta_time(&self) -> u64 {
ChaoticTempest marked this conversation as resolved.
Show resolved Hide resolved
let avg_block_prod_time = (self.config.min_block_production_delay.as_nanos()
+ self.config.max_block_production_delay.as_nanos())
/ 2;
ChaoticTempest marked this conversation as resolved.
Show resolved Hide resolved
(self.accrued_fastforward_delta as u128 * avg_block_prod_time).try_into().expect(&format!(
"Too high of a delta_height {} to convert into u64",
self.accrued_fastforward_delta
))
}

pub fn send_approval(
&mut self,
parent_hash: &CryptoHash,
Expand Down
110 changes: 96 additions & 14 deletions chain/client/src/client_actor.rs
Expand Up @@ -384,9 +384,22 @@ impl ClientActor {
)
}
near_network_primitives::types::NetworkSandboxMessage::SandboxFastForward(delta_height) => {
if self.fastforward_delta.is_some() {
return NetworkClientResponses::SandboxResult(
near_network_primitives::types::SandboxResponse::SandboxFastForwardFailed(
"Consecutive fast_forward requests cannot be made while a current one is going on.".to_string()));
}

self.fastforward_delta = Some(delta_height);
ChaoticTempest marked this conversation as resolved.
Show resolved Hide resolved
NetworkClientResponses::NoResponse
}
near_network_primitives::types::NetworkSandboxMessage::SandboxFastForwardStatus => {
NetworkClientResponses::SandboxResult(
near_network_primitives::types::SandboxResponse::SandboxFastForwardFinished(
self.fastforward_delta.is_none(),
),
)
}
};
}
NetworkClientMessages::Transaction { transaction, is_forwarded, check_only } => {
Expand Down Expand Up @@ -890,6 +903,86 @@ impl ClientActor {
}
}

/// Process the sandbox fast forward request. If the change in block height is past an epoch,
/// we fast forward to just right before the epoch, produce some blocks to get past and into
/// a new epoch, then we continue on with the residual amount to fast forward.
#[cfg(feature = "sandbox")]
fn sandbox_process_fast_forward(
ChaoticTempest marked this conversation as resolved.
Show resolved Hide resolved
&mut self,
block_height: BlockHeight,
) -> Result<Option<near_chain::types::LatestKnown>, Error> {
let mut delta_height = match self.fastforward_delta.take() {
Some(delta_height) if delta_height > 0 => delta_height,
ChaoticTempest marked this conversation as resolved.
Show resolved Hide resolved
_ => return Ok(None),
};

let epoch_length = self.client.config.epoch_length;
if epoch_length <= 3 {
return Err(Error::Other(
"Unsupported: fast_forward with an epoch length of 3 or less".to_string(),
));
}

// Check if we are at epoch boundary. If we are, do not fast forward until new
// epoch is here. Decrement the fast_forward count by 1 when a block is produced
// during this period of waiting
let block_height_wrt_epoch = block_height % epoch_length;
if epoch_length - block_height_wrt_epoch <= 3 || block_height_wrt_epoch == 0 {
// wait for doomslug to call into produce block
self.fastforward_delta = Some(delta_height);
return Ok(None);
}

let delta_height = if block_height_wrt_epoch + delta_height >= epoch_length {
// fast forward to just right before epoch boundary to have epoch_manager
// handle the epoch_height updates as normal. `- 3` since this is being
// done 3 blocks before the epoch ends.
let right_before_epoch_update = epoch_length - block_height_wrt_epoch - 3;

delta_height -= right_before_epoch_update;
self.fastforward_delta = Some(delta_height);
right_before_epoch_update
} else {
delta_height
};

self.client.accrued_fastforward_delta += delta_height;
let timestamp_delta_ns = self.client.sandbox_delta_time();
let new_latest_known = near_chain::types::LatestKnown {
height: block_height + delta_height,
seen: near_primitives::utils::to_timestamp(Clock::utc()) + timestamp_delta_ns,
};

Ok(Some(new_latest_known))
}

fn pre_block_production(&mut self) -> Result<(), Error> {
#[cfg(feature = "sandbox")]
{
let latest_known = self.client.chain.mut_store().get_latest_known()?;
if let Some(new_latest_known) =
self.sandbox_process_fast_forward(latest_known.height)?
{
self.client.chain.mut_store().save_latest_known(new_latest_known.clone())?;
self.client.sandbox_update_tip(new_latest_known.height)?;
}
}
Ok(())
}

fn post_block_production(&mut self) {
#[cfg(feature = "sandbox")]
if let Some(delta_height) = self.fastforward_delta.take() {
// Decrease the delta_height by 1 since we've produced a single block. This
// ensures that we advanced the right amount of blocks when fast forwarding
// and fast forwarding triggers regular block production in the case of
// stepping between epoch boundaries.
if delta_height > 0 {
self.fastforward_delta = Some(delta_height - 1);
}
}
}

/// Retrieves latest height, and checks if must produce next block.
/// Otherwise wait for block arrival or suggest to skip after timeout.
fn handle_block_production(&mut self) -> Result<(), Error> {
Expand All @@ -900,23 +993,10 @@ impl ClientActor {

let _ = self.client.check_and_update_doomslug_tip();

self.pre_block_production()?;
let head = self.client.chain.head()?;
let latest_known = self.client.chain.mut_store().get_latest_known()?;

#[cfg(feature = "sandbox")]
let latest_known = if let Some(delta_height) = self.fastforward_delta.take() {
let new_latest_known = near_chain::types::LatestKnown {
height: latest_known.height + delta_height,
seen: near_primitives::utils::to_timestamp(Clock::utc()),
};

self.client.chain.mut_store().save_latest_known(new_latest_known.clone())?;
self.client.sandbox_update_tip(new_latest_known.height)?;
new_latest_known
} else {
latest_known
};

assert!(
head.height <= latest_known.height,
"Latest known height is invalid {} vs {}",
Expand Down Expand Up @@ -948,6 +1028,8 @@ impl ClientActor {
if let Err(err) = self.produce_block(height) {
// If there is an error, report it and let it retry on the next loop step.
error!(target: "client", "Block production failed: {}", err);
} else {
self.post_block_production();
}
}
}
Expand Down
1 change: 1 addition & 0 deletions chain/client/src/sync.rs
Expand Up @@ -1502,6 +1502,7 @@ mod test {
&*signers[3],
*last_block.header().next_bp_hash(),
block_merkle_tree.root(),
None,
);
block_merkle_tree.insert(*block.hash());

Expand Down
10 changes: 8 additions & 2 deletions chain/client/src/test_utils.rs
Expand Up @@ -66,6 +66,11 @@ use near_primitives::utils::MaybeValidated;

pub type PeerManagerMock = Mocker<PeerManagerActor>;

/// min block production time in milliseconds
pub const MIN_BLOCK_PROD_TIME: u64 = 100;
ChaoticTempest marked this conversation as resolved.
Show resolved Hide resolved
/// max block production time in milliseconds
pub const MAX_BLOCK_PROD_TIME: u64 = 200;

const TEST_SEED: RngSeed = [3; 32];
/// Sets up ClientActor and ViewClientActor viewing the same store/runtime.
pub fn setup(
Expand Down Expand Up @@ -285,8 +290,8 @@ pub fn setup_mock_with_validity_period_and_no_epoch_sync(
5,
account_id,
skip_sync_wait,
100,
200,
MIN_BLOCK_PROD_TIME,
MAX_BLOCK_PROD_TIME,
enable_doomslug,
false,
false,
Expand Down Expand Up @@ -1669,6 +1674,7 @@ pub fn create_chunk(
&*client.validator_signer.as_ref().unwrap().clone(),
*last_block.header().next_bp_hash(),
block_merkle_tree.root(),
None,
);
(chunk, merkle_paths, receipts, block)
}
Expand Down
1 change: 1 addition & 0 deletions chain/client/src/tests/query_client.rs
Expand Up @@ -89,6 +89,7 @@ fn query_status_not_crash() {
&signer,
block.header.next_bp_hash,
block_merkle_tree.root(),
None,
);
next_block.mut_header().get_mut().inner_lite.timestamp =
to_timestamp(next_block.header().timestamp() + chrono::Duration::seconds(60));
Expand Down
32 changes: 32 additions & 0 deletions chain/jsonrpc/src/lib.rs
Expand Up @@ -1180,13 +1180,45 @@ impl JsonRpcHandler {
near_jsonrpc_primitives::types::sandbox::RpcSandboxFastForwardResponse,
near_jsonrpc_primitives::types::sandbox::RpcSandboxFastForwardError,
> {
use near_network_primitives::types::SandboxResponse;

self.client_addr
.send(NetworkClientMessages::Sandbox(
near_network_primitives::types::NetworkSandboxMessage::SandboxFastForward(
fast_forward_request.delta_height,
),
))
.await?;

// Hard limit the request to timeout at an hour, since fast forwarding can take a while,
// where we can leave it to the rpc clients to set their own timeouts if necessary.
timeout(Duration::from_secs(60 * 60), async {
loop {
let fast_forward_finished = self
.client_addr
.send(NetworkClientMessages::Sandbox(
near_network_primitives::types::NetworkSandboxMessage::SandboxFastForwardStatus {},
))
.await;

match fast_forward_finished {
Ok(NetworkClientResponses::SandboxResult(SandboxResponse::SandboxFastForwardFinished(true))) => break,
Ok(NetworkClientResponses::SandboxResult(SandboxResponse::SandboxFastForwardFailed(err))) => return Err(err),
_ => (),
}

let _ = sleep(self.polling_config.polling_interval).await;
}
Ok(())
})
.await
.map_err(|_| near_jsonrpc_primitives::types::sandbox::RpcSandboxFastForwardError::InternalError {
error_message: "sandbox failed to fast forward within reasonable time of an hour".to_string()
})?
.map_err(|err| near_jsonrpc_primitives::types::sandbox::RpcSandboxFastForwardError::InternalError {
error_message: format!("sandbox failed to fast forward due to: {:?}", err),
})?;

Ok(near_jsonrpc_primitives::types::sandbox::RpcSandboxFastForwardResponse {})
}
}
Expand Down
3 changes: 3 additions & 0 deletions chain/network-primitives/src/types.rs
Expand Up @@ -278,12 +278,15 @@ pub enum NetworkSandboxMessage {
SandboxPatchState(Vec<near_primitives::state_record::StateRecord>),
SandboxPatchStateStatus,
SandboxFastForward(near_primitives::types::BlockHeightDelta),
SandboxFastForwardStatus,
}

#[cfg(feature = "sandbox")]
#[derive(Eq, PartialEq, Debug)]
pub enum SandboxResponse {
SandboxPatchStateFinished(bool),
SandboxFastForwardFinished(bool),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not important, but a better name here would be FastForwardInProgress, to not think aboUt "fast forward not even started" case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with what was already there for patching state. It's only being used internally right now, so not too important to change IMO

SandboxFastForwardFailed(String),
}

#[derive(actix::Message, AsStaticStr)]
Expand Down
1 change: 1 addition & 0 deletions core/primitives/benches/serialization.rs
Expand Up @@ -68,6 +68,7 @@ fn create_block() -> Block {
&signer,
CryptoHash::default(),
CryptoHash::default(),
None,
)
}

Expand Down
3 changes: 2 additions & 1 deletion core/primitives/src/block.rs
Expand Up @@ -214,6 +214,7 @@ impl Block {
signer: &dyn ValidatorSigner,
next_bp_hash: CryptoHash,
block_merkle_root: CryptoHash,
timestamp_override: Option<u64>,
ChaoticTempest marked this conversation as resolved.
Show resolved Hide resolved
) -> Self {
// Collect aggregate of validators and gas usage/limits from chunks.
let mut validator_proposals = vec![];
Expand Down Expand Up @@ -243,7 +244,7 @@ impl Block {
);

let new_total_supply = prev.total_supply() + minted_amount.unwrap_or(0) - balance_burnt;
let now = to_timestamp(Clock::utc());
let now = timestamp_override.unwrap_or_else(|| to_timestamp(Clock::utc()));
let time = if now <= prev.raw_timestamp() { prev.raw_timestamp() + 1 } else { now };

let (vrf_value, vrf_proof) = signer.compute_vrf_with_proof(prev.random_value().as_ref());
Expand Down