Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a2acdaa

Browse files
committedMay 29, 2025··
use blocktime and fix tests
1 parent 7c80bfb commit a2acdaa

File tree

10 files changed

+240
-83
lines changed

10 files changed

+240
-83
lines changed
 

‎chain/ethereum/src/chain.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,9 @@ pub struct FirehoseMapper {
11311131
impl BlockStreamMapper<Chain> for FirehoseMapper {
11321132
fn decode_block(
11331133
&self,
1134+
// We share the trait with substreams but for firehose the timestamp
1135+
// is in the block header so we don't need to use it here.
1136+
_timestamp: BlockTime,
11341137
output: Option<&[u8]>,
11351138
) -> Result<Option<BlockFinality>, BlockStreamError> {
11361139
let block = match output {
@@ -1199,12 +1202,19 @@ impl FirehoseMapperTrait<Chain> for FirehoseMapper {
11991202
// Check about adding basic information about the block in the firehose::Response or maybe
12001203
// define a slimmed down stuct that would decode only a few fields and ignore all the rest.
12011204
let block = codec::Block::decode(any_block.value.as_ref())?;
1205+
let timestamp = block
1206+
.header()
1207+
.timestamp
1208+
.map(|ts| BlockTime::since_epoch(ts.seconds, ts.nanos as u32))
1209+
.unwrap_or_default();
12021210

12031211
use firehose::ForkStep::*;
12041212
match step {
12051213
StepNew => {
12061214
// unwrap: Input cannot be None so output will be error or block.
1207-
let block = self.decode_block(Some(any_block.value.as_ref()))?.unwrap();
1215+
let block = self
1216+
.decode_block(timestamp, Some(any_block.value.as_ref()))?
1217+
.unwrap();
12081218
let block_with_triggers = self.block_with_triggers(logger, block).await?;
12091219

12101220
Ok(BlockStreamEvent::ProcessBlock(

‎chain/near/src/chain.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use graph::blockchain::client::ChainClient;
33
use graph::blockchain::firehose_block_ingestor::FirehoseBlockIngestor;
44
use graph::blockchain::substreams_block_stream::SubstreamsBlockStream;
55
use graph::blockchain::{
6-
BasicBlockchainBuilder, BlockIngestor, BlockchainBuilder, BlockchainKind, NoopDecoderHook,
7-
NoopRuntimeAdapter, Trigger, TriggerFilterWrapper,
6+
BasicBlockchainBuilder, BlockIngestor, BlockTime, BlockchainBuilder, BlockchainKind,
7+
NoopDecoderHook, NoopRuntimeAdapter, Trigger, TriggerFilterWrapper,
88
};
99
use graph::cheap_clone::CheapClone;
1010
use graph::components::network_provider::ChainName;
@@ -432,6 +432,7 @@ pub struct FirehoseMapper {
432432
impl BlockStreamMapper<Chain> for FirehoseMapper {
433433
fn decode_block(
434434
&self,
435+
_timestamp: BlockTime,
435436
output: Option<&[u8]>,
436437
) -> Result<Option<codec::Block>, BlockStreamError> {
437438
let block = match output {
@@ -528,7 +529,10 @@ impl FirehoseMapperTrait<Chain> for FirehoseMapper {
528529
// Check about adding basic information about the block in the bstream::BlockResponseV2 or maybe
529530
// define a slimmed down stuct that would decode only a few fields and ignore all the rest.
530531
// unwrap: Input cannot be None so output will be error or block.
531-
let block = self.decode_block(Some(any_block.value.as_ref()))?.unwrap();
532+
let block = self
533+
// the block time is inside the block.
534+
.decode_block(BlockTime::MIN, Some(any_block.value.as_ref()))?
535+
.unwrap();
532536

533537
use ForkStep::*;
534538
match step {

‎chain/substreams/src/chain.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub enum ParsedChanges {
4343
pub struct Block {
4444
pub hash: BlockHash,
4545
pub number: BlockNumber,
46+
pub timestamp: BlockTime,
4647
pub changes: EntityChanges,
4748
pub parsed_changes: Vec<ParsedChanges>,
4849
}
@@ -60,7 +61,7 @@ impl blockchain::Block for Block {
6061
}
6162

6263
fn timestamp(&self) -> BlockTime {
63-
BlockTime::NONE
64+
self.timestamp
6465
}
6566
}
6667

‎chain/substreams/src/mapper.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub struct WasmBlockMapper {
3232
impl BlockStreamMapper<Chain> for WasmBlockMapper {
3333
fn decode_block(
3434
&self,
35+
_timestamp: BlockTime,
3536
_output: Option<&[u8]>,
3637
) -> Result<Option<crate::Block>, BlockStreamError> {
3738
unreachable!("WasmBlockMapper does not do block decoding")
@@ -104,7 +105,11 @@ pub struct Mapper {
104105

105106
#[async_trait]
106107
impl BlockStreamMapper<Chain> for Mapper {
107-
fn decode_block(&self, output: Option<&[u8]>) -> Result<Option<Block>, BlockStreamError> {
108+
fn decode_block(
109+
&self,
110+
timestamp: BlockTime,
111+
output: Option<&[u8]>,
112+
) -> Result<Option<Block>, BlockStreamError> {
108113
let changes: EntityChanges = match output {
109114
Some(msg) => Message::decode(msg).map_err(SubstreamsError::DecodingError)?,
110115
None => EntityChanges {
@@ -125,6 +130,7 @@ impl BlockStreamMapper<Chain> for Mapper {
125130
number,
126131
changes,
127132
parsed_changes,
133+
timestamp,
128134
};
129135

130136
Ok(Some(block))
@@ -152,9 +158,13 @@ impl BlockStreamMapper<Chain> for Mapper {
152158
) -> Result<BlockStreamEvent<Chain>, BlockStreamError> {
153159
let block_number: BlockNumber = clock.number.try_into().map_err(Error::from)?;
154160
let block_hash = clock.id.as_bytes().to_vec().into();
161+
let timestamp = clock
162+
.timestamp
163+
.map(|ts| BlockTime::since_epoch(ts.seconds, ts.nanos as u32))
164+
.unwrap_or_default();
155165

156166
let block = self
157-
.decode_block(Some(&block))?
167+
.decode_block(timestamp, Some(&block))?
158168
.ok_or_else(|| anyhow!("expected block to not be empty"))?;
159169

160170
let block = self.block_with_triggers(logger, block).await.map(|bt| {

‎graph/src/blockchain/block_stream.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,11 @@ pub trait FirehoseMapper<C: Blockchain>: Send + Sync {
685685

686686
#[async_trait]
687687
pub trait BlockStreamMapper<C: Blockchain>: Send + Sync {
688-
fn decode_block(&self, output: Option<&[u8]>) -> Result<Option<C::Block>, BlockStreamError>;
688+
fn decode_block(
689+
&self,
690+
timestamp: BlockTime,
691+
output: Option<&[u8]>,
692+
) -> Result<Option<C::Block>, BlockStreamError>;
689693

690694
async fn block_with_triggers(
691695
&self,

‎graph/src/blockchain/types.rs

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use anyhow::anyhow;
2+
use chrono::DateTime;
23
use diesel::deserialize::FromSql;
34
use diesel::pg::Pg;
45
use diesel::serialize::{Output, ToSql};
@@ -7,6 +8,7 @@ use diesel::sql_types::{Bytea, Nullable, Text};
78
use diesel_derives::{AsExpression, FromSqlRow};
89
use serde::{Deserialize, Deserializer};
910
use std::convert::TryFrom;
11+
use std::num::ParseIntError;
1012
use std::time::Duration;
1113
use std::{fmt, str::FromStr};
1214
use web3::types::{Block, H256, U256, U64};
@@ -16,9 +18,9 @@ use crate::components::store::BlockNumber;
1618
use crate::data::graphql::IntoValue;
1719
use crate::data::store::scalar::Timestamp;
1820
use crate::derive::CheapClone;
19-
use crate::object;
2021
use crate::prelude::{r, Value};
2122
use crate::util::stable_hash_glue::{impl_stable_hash, AsBytes};
23+
use crate::{bail, object};
2224

2325
/// A simple marker for byte arrays that are really block hashes
2426
#[derive(Clone, Default, PartialEq, Eq, Hash, FromSqlRow, AsExpression)]
@@ -477,10 +479,7 @@ impl TryFrom<(Option<H256>, Option<U64>, H256, U256)> for ExtendedBlockPtr {
477479
let block_number =
478480
i32::try_from(number).map_err(|_| anyhow!("Block number out of range"))?;
479481

480-
// Convert `U256` to `BlockTime`
481-
let secs =
482-
i64::try_from(timestamp_u256).map_err(|_| anyhow!("Timestamp out of range for i64"))?;
483-
let block_time = BlockTime::since_epoch(secs, 0);
482+
let block_time = BlockTime::try_from(timestamp_u256)?;
484483

485484
Ok(ExtendedBlockPtr {
486485
hash: hash.into(),
@@ -497,16 +496,13 @@ impl TryFrom<(H256, i32, H256, U256)> for ExtendedBlockPtr {
497496
fn try_from(tuple: (H256, i32, H256, U256)) -> Result<Self, Self::Error> {
498497
let (hash, block_number, parent_hash, timestamp_u256) = tuple;
499498

500-
// Convert `U256` to `BlockTime`
501-
let secs =
502-
i64::try_from(timestamp_u256).map_err(|_| anyhow!("Timestamp out of range for i64"))?;
503-
let block_time = BlockTime::since_epoch(secs, 0);
499+
let timestamp = BlockTime::try_from(timestamp_u256)?;
504500

505501
Ok(ExtendedBlockPtr {
506502
hash: hash.into(),
507503
number: block_number,
508504
parent_hash: parent_hash.into(),
509-
timestamp: block_time,
505+
timestamp,
510506
})
511507
}
512508
}
@@ -562,14 +558,67 @@ impl fmt::Display for ChainIdentifier {
562558
#[diesel(sql_type = Timestamptz)]
563559
pub struct BlockTime(Timestamp);
564560

561+
impl Default for BlockTime {
562+
fn default() -> Self {
563+
BlockTime::NONE
564+
}
565+
}
566+
567+
impl TryFrom<BlockTime> for U256 {
568+
type Error = anyhow::Error;
569+
570+
fn try_from(value: BlockTime) -> Result<Self, Self::Error> {
571+
if value.as_secs_since_epoch() < 0 {
572+
bail!("unable to convert block time into U256");
573+
}
574+
575+
Ok(U256::from(value.as_secs_since_epoch() as u64))
576+
}
577+
}
578+
579+
impl TryFrom<U256> for BlockTime {
580+
type Error = anyhow::Error;
581+
582+
fn try_from(value: U256) -> Result<Self, Self::Error> {
583+
i64::try_from(value)
584+
.map_err(|_| anyhow!("Timestamp out of range for i64"))
585+
.map(|ts| BlockTime::since_epoch(ts, 0))
586+
}
587+
}
588+
589+
impl TryFrom<Option<String>> for BlockTime {
590+
type Error = ParseIntError;
591+
592+
fn try_from(ts: Option<String>) -> Result<Self, Self::Error> {
593+
match ts {
594+
Some(str) => return BlockTime::from_str(&str),
595+
None => return Ok(BlockTime::NONE),
596+
};
597+
}
598+
}
599+
600+
impl FromStr for BlockTime {
601+
type Err = ParseIntError;
602+
603+
fn from_str(ts: &str) -> Result<Self, Self::Err> {
604+
let (radix, idx) = if ts.starts_with("0x") {
605+
(16, 2)
606+
} else {
607+
(10, 0)
608+
};
609+
610+
u64::from_str_radix(&ts[idx..], radix).map(|ts| BlockTime::since_epoch(ts as i64, 0))
611+
}
612+
}
613+
565614
impl BlockTime {
566-
/// A timestamp from a long long time ago used to indicate that we don't
567-
/// have a timestamp
568-
pub const NONE: Self = Self(Timestamp::NONE);
615+
// /// A timestamp from a long long time ago used to indicate that we don't
616+
// /// have a timestamp
617+
pub const NONE: Self = Self::MIN;
569618

570619
pub const MAX: Self = Self(Timestamp::MAX);
571620

572-
pub const MIN: Self = Self(Timestamp::MIN);
621+
pub const MIN: Self = Self(Timestamp(DateTime::from_timestamp_nanos(0)));
573622

574623
/// Construct a block time that is the given number of seconds and
575624
/// nanoseconds after the Unix epoch
@@ -586,7 +635,12 @@ impl BlockTime {
586635
/// hourly rollups in tests
587636
#[cfg(debug_assertions)]
588637
pub fn for_test(ptr: &BlockPtr) -> Self {
589-
Self::since_epoch(ptr.number as i64 * 45 * 60, 0)
638+
Self::for_test_number(&ptr.number)
639+
}
640+
641+
#[cfg(debug_assertions)]
642+
pub fn for_test_number(number: &BlockNumber) -> Self {
643+
Self::since_epoch(*number as i64 * 45 * 60, 0)
590644
}
591645

592646
pub fn as_secs_since_epoch(&self) -> i64 {

‎graph/src/data_source/offchain.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ impl DataSource {
216216
data_source::MappingTrigger::Offchain(trigger.clone()),
217217
self.mapping.handler.clone(),
218218
BlockPtr::new(Default::default(), self.creation_block.unwrap_or(0)),
219-
BlockTime::NONE,
219+
BlockTime::MIN,
220220
))
221221
}
222222

‎store/postgres/src/chain_store.rs

Lines changed: 103 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -550,14 +550,33 @@ mod data {
550550
conn: &mut PgConnection,
551551
lowest_block: i32,
552552
) -> Result<(), StoreError> {
553-
let table_name = match &self {
554-
Storage::Shared => ETHEREUM_BLOCKS_TABLE_NAME,
555-
Storage::Private(Schema { blocks, .. }) => &blocks.qname,
553+
let query = match &self {
554+
Storage::Shared => format!(
555+
"
556+
DELETE FROM {}
557+
WHERE data->'block'->'data' = 'null'::jsonb
558+
AND number >= {};",
559+
ETHEREUM_BLOCKS_TABLE_NAME, lowest_block,
560+
),
561+
562+
Storage::Private(Schema {
563+
blocks,
564+
block_pointers,
565+
..
566+
}) => format!(
567+
"
568+
delete from {}
569+
WHERE data->'block'->'data' = 'null'::jsonb
570+
AND hash IN (
571+
SELECT hash
572+
FROM {}
573+
WHERE number >= {}
574+
);",
575+
blocks.qname, block_pointers.qname, lowest_block,
576+
),
556577
};
557-
conn.batch_execute(&format!(
558-
"delete from {} WHERE number >= {} AND data->'block'->'data' = 'null'::jsonb;",
559-
table_name, lowest_block,
560-
))?;
578+
579+
conn.batch_execute(&query)?;
561580
Ok(())
562581
}
563582

@@ -652,7 +671,7 @@ mod data {
652671
"insert into {pointers_table}(hash, number, parent_hash, timestamp) \
653672
values ($1, $2, $3, $5) \
654673
on conflict(hash) \
655-
do update set number = $2, parent_hash = $3;
674+
do update set number = $2, parent_hash = $3, timestamp = $5;
656675
",
657676
pointers_table = block_pointers.qname,
658677
)
@@ -875,10 +894,10 @@ mod data {
875894
.execute(conn)
876895
.map_err(Error::from)
877896
}
878-
Storage::Private(Schema { blocks, .. }) => {
897+
Storage::Private(Schema { block_pointers, .. }) => {
879898
let query = format!(
880899
"delete from {} where number = $1 and hash != $2",
881-
blocks.qname
900+
block_pointers.qname
882901
);
883902
sql_query(query)
884903
.bind::<BigInt, _>(number)
@@ -934,7 +953,17 @@ mod data {
934953
.filter(block_pointers.hash().eq(hash.as_slice()))
935954
.first::<(i64, BlockTime, Vec<u8>)>(conn)
936955
.optional()?
937-
.map(|(number, ts, parent_hash)| (number, Some(ts), Some(parent_hash))),
956+
.map(|(number, ts, parent_hash)| {
957+
(
958+
number,
959+
if ts == BlockTime::NONE {
960+
None
961+
} else {
962+
Some(ts)
963+
},
964+
Some(parent_hash),
965+
)
966+
}),
938967
};
939968

940969
match number {
@@ -1055,7 +1084,7 @@ mod data {
10551084
};
10561085
Ok(missing)
10571086
}
1058-
Storage::Private(Schema { blocks, .. }) => {
1087+
Storage::Private(Schema { block_pointers, .. }) => {
10591088
// This is the same as `MISSING_PARENT_SQL` above except that
10601089
// the blocks table has a different name and that it does
10611090
// not have a `network_name` column
@@ -1082,7 +1111,7 @@ mod data {
10821111
from chain
10831112
where chain.parent_hash is null;
10841113
",
1085-
qname = blocks.qname
1114+
qname = block_pointers.qname
10861115
);
10871116

10881117
let missing = sql_query(query)
@@ -1148,25 +1177,25 @@ mod data {
11481177
fn ancestor_block_query(
11491178
&self,
11501179
short_circuit_predicate: &str,
1151-
blocks_table_name: &str,
1180+
block_ptrs_table_name: &str,
11521181
) -> String {
11531182
format!(
11541183
"
11551184
with recursive ancestors(block_hash, block_offset) as (
11561185
values ($1, 0)
11571186
union all
11581187
select b.parent_hash, a.block_offset + 1
1159-
from ancestors a, {blocks_table_name} b
1188+
from ancestors a, {block_ptrs_table_name} b
11601189
where a.block_hash = b.hash
11611190
and a.block_offset < $2
11621191
{short_circuit_predicate}
11631192
)
11641193
select a.block_hash as hash, b.number as number
11651194
from ancestors a
1166-
inner join {blocks_table_name} b on a.block_hash = b.hash
1195+
inner join {block_ptrs_table_name} b on a.block_hash = b.hash
11671196
order by a.block_offset desc limit 1
11681197
",
1169-
blocks_table_name = blocks_table_name,
1198+
block_ptrs_table_name = block_ptrs_table_name,
11701199
short_circuit_predicate = short_circuit_predicate,
11711200
)
11721201
}
@@ -1229,9 +1258,15 @@ mod data {
12291258
)),
12301259
}
12311260
}
1232-
Storage::Private(Schema { blocks, .. }) => {
1233-
let query =
1234-
self.ancestor_block_query(short_circuit_predicate, blocks.qname.as_str());
1261+
Storage::Private(Schema {
1262+
blocks,
1263+
block_pointers,
1264+
..
1265+
}) => {
1266+
let query = self.ancestor_block_query(
1267+
short_circuit_predicate,
1268+
block_pointers.qname.as_str(),
1269+
);
12351270

12361271
#[derive(QueryableByName)]
12371272
struct BlockHashAndNumber {
@@ -1307,16 +1342,33 @@ mod data {
13071342
.execute(conn)
13081343
.map_err(Error::from)
13091344
}
1310-
Storage::Private(Schema { blocks, .. }) => {
1311-
let query = format!(
1312-
"delete from {} where number < $1 and number > 0",
1313-
blocks.qname
1314-
);
1315-
sql_query(query)
1316-
.bind::<BigInt, _>(block)
1345+
Storage::Private(Schema {
1346+
blocks,
1347+
block_pointers,
1348+
..
1349+
}) => conn.transaction(|conn| {
1350+
sql_query(&format!(
1351+
"
1352+
DELETE FROM {blocks}
1353+
WHERE hash in (
1354+
SELECT hash
1355+
FROM {block_ptrs}
1356+
WHERE number < $1 AND number > 0
1357+
);",
1358+
blocks = blocks.qname,
1359+
block_ptrs = block_pointers.qname,
1360+
))
1361+
.bind::<BigInt, _>(block)
1362+
.execute(conn)
1363+
.and_then(|_| {
1364+
sql_query(format!(
1365+
"DELETE FROM {block_ptrs} WHERE number < {block} AND number > 0;",
1366+
block_ptrs = block_pointers.qname
1367+
))
13171368
.execute(conn)
1318-
.map_err(Error::from)
1319-
}
1369+
})
1370+
.map_err(Error::from)
1371+
}),
13201372
}
13211373
}
13221374

@@ -1342,10 +1394,22 @@ mod data {
13421394
.execute(conn)
13431395
.map_err(Error::from)
13441396
}
1345-
Storage::Private(Schema { blocks, .. }) => {
1397+
Storage::Private(Schema {
1398+
blocks,
1399+
block_pointers,
1400+
..
1401+
}) => {
13461402
let query = format!(
1347-
"delete from {} where hash = any($1) and number > 0",
1348-
blocks.qname
1403+
"
1404+
DELETE FROM {blocks}
1405+
WHERE hash in (
1406+
SELECT FROM {block_ptrs}
1407+
WHERE hash = any($1) AND number > 0;
1408+
);
1409+
DELETE FROM {block_ptrs} WHERE hash = any($1) AND number > 0;
1410+
",
1411+
blocks = blocks.qname,
1412+
block_ptrs = block_pointers.qname
13491413
);
13501414

13511415
let hashes: Vec<&[u8]> =
@@ -1688,9 +1752,15 @@ mod data {
16881752
blocks,
16891753
call_meta,
16901754
call_cache,
1755+
block_pointers,
16911756
..
16921757
}) => {
1693-
for qname in &[&blocks.qname, &call_meta.qname, &call_cache.qname] {
1758+
for qname in &[
1759+
&blocks.qname,
1760+
&call_meta.qname,
1761+
&call_cache.qname,
1762+
&block_pointers.qname,
1763+
] {
16941764
let query = format!("delete from {}", qname);
16951765
sql_query(query)
16961766
.execute(conn)

‎store/test-store/src/block_store.rs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,53 +21,53 @@ lazy_static! {
2121
pub static ref GENESIS_BLOCK: FakeBlock = FakeBlock {
2222
number: super::GENESIS_PTR.number,
2323
hash: super::GENESIS_PTR.hash_hex(),
24-
timestamp: None,
24+
timestamp: BlockTime::NONE,
2525
parent_hash: NO_PARENT.to_string()
2626
};
2727
pub static ref BLOCK_ONE: FakeBlock = GENESIS_BLOCK
28-
.make_child("8511fa04b64657581e3f00e14543c1d522d5d7e771b54aa3060b662ade47da13", None);
28+
.make_child("8511fa04b64657581e3f00e14543c1d522d5d7e771b54aa3060b662ade47da13", BlockTime::NONE);
2929
pub static ref BLOCK_ONE_SIBLING: FakeBlock =
30-
GENESIS_BLOCK.make_child("b98fb783b49de5652097a989414c767824dff7e7fd765a63b493772511db81c1", None);
30+
GENESIS_BLOCK.make_child("b98fb783b49de5652097a989414c767824dff7e7fd765a63b493772511db81c1", BlockTime::NONE);
3131
pub static ref BLOCK_ONE_NO_PARENT: FakeBlock = FakeBlock::make_no_parent(
3232
1,
3333
"7205bdfcf4521874cf38ce38c879ff967bf3a069941286bfe267109ad275a63d"
3434
);
3535

36-
pub static ref BLOCK_TWO: FakeBlock = BLOCK_ONE.make_child("f8ccbd3877eb98c958614f395dd351211afb9abba187bfc1fb4ac414b099c4a6", None);
36+
pub static ref BLOCK_TWO: FakeBlock = BLOCK_ONE.make_child("f8ccbd3877eb98c958614f395dd351211afb9abba187bfc1fb4ac414b099c4a6", BlockTime::NONE);
3737
pub static ref BLOCK_TWO_NO_PARENT: FakeBlock = FakeBlock::make_no_parent(2, "3b652b00bff5e168b1218ff47593d516123261c4487629c4175f642ee56113fe");
3838
pub static ref BLOCK_THREE_SKIPPED_2: FakeBlock = BLOCK_ONE.make_skipped_child(
3939
"d8ccbd3877eb98c958614f395dd351211afb9abba187bfc1fb4ac414b099c4a6",
40-
None,
40+
BlockTime::NONE,
4141
1,
4242
);
43-
pub static ref BLOCK_THREE: FakeBlock = BLOCK_TWO.make_child("7347afe69254df06729e123610b00b8b11f15cfae3241f9366fb113aec07489c", None);
43+
pub static ref BLOCK_THREE: FakeBlock = BLOCK_TWO.make_child("7347afe69254df06729e123610b00b8b11f15cfae3241f9366fb113aec07489c", BlockTime::NONE);
4444
pub static ref BLOCK_THREE_NO_PARENT: FakeBlock = FakeBlock::make_no_parent(3, "fa9ebe3f74de4c56908b49f5c4044e85825f7350f3fa08a19151de82a82a7313");
45-
pub static ref BLOCK_THREE_TIMESTAMP: FakeBlock = BLOCK_TWO.make_child("6b834521bb753c132fdcf0e1034803ed9068e324112f8750ba93580b393a986b", Some(U256::from(1657712166)));
46-
pub static ref BLOCK_THREE_TIMESTAMP_FIREHOSE: FakeBlock = BLOCK_TWO.make_child("6b834521bb753c132fdcf0e1034803ed9068e324112f8750ba93580b393a986f", Some(U256::from(1657712166)));
45+
pub static ref BLOCK_THREE_TIMESTAMP: FakeBlock = BLOCK_TWO.make_child("6b834521bb753c132fdcf0e1034803ed9068e324112f8750ba93580b393a986b", BlockTime::try_from(U256::from(1657712166)).unwrap()) ;
46+
pub static ref BLOCK_THREE_TIMESTAMP_FIREHOSE: FakeBlock = BLOCK_TWO.make_child("6b834521bb753c132fdcf0e1034803ed9068e324112f8750ba93580b393a986f", BlockTime::try_from(U256::from(1657712166)).unwrap());
4747
// This block is special and serializes in a slightly different way, this is needed to simulate non-ethereum behaviour at the store level. If you're not sure
4848
// what you are doing, don't use this block for other tests.
49-
pub static ref BLOCK_THREE_NO_TIMESTAMP: FakeBlock = BLOCK_TWO.make_child("6b834521bb753c132fdcf0e1034803ed9068e324112f8750ba93580b393a986b", None);
50-
pub static ref BLOCK_FOUR: FakeBlock = BLOCK_THREE.make_child("7cce080f5a49c2997a6cc65fc1cee9910fd8fc3721b7010c0b5d0873e2ac785e", None);
51-
pub static ref BLOCK_FOUR_SKIPPED_2_AND_3: FakeBlock = BLOCK_ONE.make_skipped_child("9cce080f5a49c2997a6cc65fc1cee9910fd8fc3721b7010c0b5d0873e2ac785e", None, 2);
52-
pub static ref BLOCK_FIVE_AFTER_SKIP: FakeBlock = BLOCK_FOUR_SKIPPED_2_AND_3.make_child("8b0ea919e258eb2b119eb32de56b85d12d50ac6a9f7c5909f843d6172c8ba196", None);
53-
pub static ref BLOCK_FIVE: FakeBlock = BLOCK_FOUR.make_child("7b0ea919e258eb2b119eb32de56b85d12d50ac6a9f7c5909f843d6172c8ba196", None);
49+
pub static ref BLOCK_THREE_NO_TIMESTAMP: FakeBlock = BLOCK_TWO.make_child("6b834521bb753c132fdcf0e1034803ed9068e324112f8750ba93580b393a986b", BlockTime::NONE);
50+
pub static ref BLOCK_FOUR: FakeBlock = BLOCK_THREE.make_child("7cce080f5a49c2997a6cc65fc1cee9910fd8fc3721b7010c0b5d0873e2ac785e", BlockTime::NONE);
51+
pub static ref BLOCK_FOUR_SKIPPED_2_AND_3: FakeBlock = BLOCK_ONE.make_skipped_child("9cce080f5a49c2997a6cc65fc1cee9910fd8fc3721b7010c0b5d0873e2ac785e", BlockTime::NONE, 2);
52+
pub static ref BLOCK_FIVE_AFTER_SKIP: FakeBlock = BLOCK_FOUR_SKIPPED_2_AND_3.make_child("8b0ea919e258eb2b119eb32de56b85d12d50ac6a9f7c5909f843d6172c8ba196", BlockTime::NONE);
53+
pub static ref BLOCK_FIVE: FakeBlock = BLOCK_FOUR.make_child("7b0ea919e258eb2b119eb32de56b85d12d50ac6a9f7c5909f843d6172c8ba196", BlockTime::NONE);
5454
pub static ref BLOCK_SIX_NO_PARENT: FakeBlock = FakeBlock::make_no_parent(6, "6b834521bb753c132fdcf0e1034803ed9068e324112f8750ba93580b393a986b");
5555
}
5656

5757
// Hash indicating 'no parent'
5858
pub const NO_PARENT: &str = "0000000000000000000000000000000000000000000000000000000000000000";
5959
/// The parts of an Ethereum block that are interesting for these tests:
6060
/// the block number, hash, and the hash of the parent block
61-
#[derive(Clone, Debug, PartialEq)]
61+
#[derive(Default, Clone, Debug, PartialEq)]
6262
pub struct FakeBlock {
6363
pub number: BlockNumber,
6464
pub hash: String,
6565
pub parent_hash: String,
66-
pub timestamp: Option<U256>,
66+
pub timestamp: BlockTime,
6767
}
6868

6969
impl FakeBlock {
70-
pub fn make_child(&self, hash: &str, timestamp: Option<U256>) -> Self {
70+
pub fn make_child(&self, hash: &str, timestamp: BlockTime) -> Self {
7171
FakeBlock {
7272
number: self.number + 1,
7373
hash: hash.to_owned(),
@@ -76,7 +76,7 @@ impl FakeBlock {
7676
}
7777
}
7878

79-
pub fn make_skipped_child(&self, hash: &str, timestamp: Option<U256>, skip: i32) -> Self {
79+
pub fn make_skipped_child(&self, hash: &str, timestamp: BlockTime, skip: i32) -> Self {
8080
FakeBlock {
8181
number: self.number + 1 + skip,
8282
hash: hash.to_owned(),
@@ -90,7 +90,7 @@ impl FakeBlock {
9090
number,
9191
hash: hash.to_owned(),
9292
parent_hash: NO_PARENT.to_string(),
93-
timestamp: None,
93+
timestamp: BlockTime::for_test_number(&number),
9494
}
9595
}
9696

@@ -109,9 +109,7 @@ impl FakeBlock {
109109
block.number = Some(self.number.into());
110110
block.parent_hash = parent_hash;
111111
block.hash = Some(H256(self.block_hash().as_slice().try_into().unwrap()));
112-
if let Some(ts) = self.timestamp {
113-
block.timestamp = ts;
114-
}
112+
block.timestamp = self.timestamp.try_into().unwrap();
115113

116114
EthereumBlock {
117115
block: Arc::new(block),
@@ -126,10 +124,15 @@ impl FakeBlock {
126124

127125
let mut header = BlockHeader::default();
128126
header.parent_hash = self.parent_hash.clone().into_bytes();
129-
header.timestamp = self.timestamp.map(|ts| Timestamp {
130-
seconds: i64::from_str_radix(&ts.to_string(), 10).unwrap(),
131-
nanos: 0,
132-
});
127+
header.timestamp = if self.timestamp == BlockTime::NONE {
128+
None
129+
} else {
130+
Some(Timestamp {
131+
seconds: self.timestamp.as_secs_since_epoch(),
132+
nanos: 0,
133+
})
134+
};
135+
133136
block.header = Some(header);
134137

135138
block
@@ -178,7 +181,7 @@ impl BlockchainBlock for FakeBlock {
178181
}
179182

180183
fn timestamp(&self) -> BlockTime {
181-
BlockTime::NONE
184+
self.timestamp
182185
}
183186
}
184187

‎store/test-store/tests/graphql/query.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ lazy_static! {
5353
/// The id of the sole publisher in the test data
5454
static ref PUB1: IdVal = IdType::Bytes.parse("0xb1");
5555
/// The chain we actually put into the chain store, blocks 0 to 3
56+
// static ref CHAIN: Vec<FakeBlock> = vec![GENESIS_BLOCK.clone(), BLOCK_ONE.clone(), BLOCK_TWO.clone(), BLOCK_THREE.clone()];
5657
static ref CHAIN: Vec<FakeBlock> = vec![GENESIS_BLOCK.clone(), BLOCK_ONE.clone(), BLOCK_TWO.clone(), BLOCK_THREE.clone()];
5758
/// The known block pointers for blocks 0 to 3 from the chain plus a
5859
/// nonexistent block 4

0 commit comments

Comments
 (0)
Please sign in to comment.