Skip to content

graphql-alt: Epoch #21997

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

Open
wants to merge 2 commits into
base: amnn/gql-vis
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//# init --protocol-version 70 --accounts A --simulator

//# create-checkpoint

//# advance-epoch

//# create-checkpoint

//# create-checkpoint

//# advance-epoch

//# create-checkpoint
Comment on lines +4 to +16
Copy link
Contributor

Choose a reason for hiding this comment

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

wheres c7 coming from?

e0
c0: init
c1: L6
c2: L8 advance-epoch

e1
c3 L10
c4 L12
c5 L14 advance epoch

and then c6 from L16


//# run-graphql
{
c0: checkpoint(sequenceNumber: 0) { epoch { epochId } }
c1: checkpoint(sequenceNumber: 1) { epoch { epochId } }
c2: checkpoint(sequenceNumber: 2) { epoch { epochId } }
c3: checkpoint(sequenceNumber: 3) { epoch { epochId } }
c4: checkpoint(sequenceNumber: 4) { epoch { epochId } }
c5: checkpoint(sequenceNumber: 5) { epoch { epochId } }
c6: checkpoint(sequenceNumber: 6) { epoch { epochId } }
c7: checkpoint(sequenceNumber: 7) { epoch { epochId } }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
source: external-crates/move/crates/move-transactional-test-runner/src/framework.rs
---
processed 8 tasks

init:
A: object(0,0)

task 1, line 6:
//# create-checkpoint
Checkpoint created: 1

task 2, line 8:
//# advance-epoch
Epoch advanced: 0

task 3, line 10:
//# create-checkpoint
Checkpoint created: 3

task 4, line 12:
//# create-checkpoint
Checkpoint created: 4

task 5, line 14:
//# advance-epoch
Epoch advanced: 1

task 6, line 16:
//# create-checkpoint
Checkpoint created: 6

task 7, lines 18-28:
//# run-graphql
Response: {
"data": {
"c0": {
"epoch": {
"epochId": 0
}
},
"c1": {
"epoch": {
"epochId": 0
}
},
"c2": {
"epoch": {
"epochId": 0
}
},
"c3": {
"epoch": {
"epochId": 1
}
},
"c4": {
"epoch": {
"epochId": 1
}
},
"c5": {
"epoch": {
"epochId": 1
}
},
"c6": {
"epoch": {
"epochId": 2
}
},
"c7": null
}
}
46 changes: 46 additions & 0 deletions crates/sui-indexer-alt-e2e-tests/tests/graphql/epochs/query.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//# init --protocol-version 70 --accounts A --simulator

//# advance-clock --duration-ns 123000000

//# advance-epoch

//# advance-clock --duration-ns 321000000

//# advance-epoch

//# advance-epoch

//# run-graphql
{
e0: epoch(epochId: 0) { ...E }
e1: epoch(epochId: 1) { ...E }
e2: epoch(epochId: 2) { ...E }

# This epoch doesn't exist yet
e3: epoch(epochId: 3) { ...E }
}

fragment E on Epoch {
epochId
referenceGasPrice
startTimestamp
endTimestamp
}

//# run-graphql
{ # This checkpoint is half way through the epoch, so the epoch should return
# its starting information, but not its ending information.
checkpoint(sequenceNumber: 2) {
query {
epoch(epochId: 1) {
epochId
referenceGasPrice
startTimestamp
endTimestamp
}
}
}
}
62 changes: 62 additions & 0 deletions crates/sui-indexer-alt-e2e-tests/tests/graphql/epochs/query.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
source: external-crates/move/crates/move-transactional-test-runner/src/framework.rs
---
processed 8 tasks

init:
A: object(0,0)

task 2, line 8:
//# advance-epoch
Epoch advanced: 0

task 4, line 12:
//# advance-epoch
Epoch advanced: 1

task 5, line 14:
//# advance-epoch
Epoch advanced: 2

task 6, lines 16-31:
//# run-graphql
Response: {
"data": {
"e0": {
"epochId": 0,
"referenceGasPrice": "1000",
"startTimestamp": "1970-01-01T00:00:00Z",
"endTimestamp": "1970-01-01T00:00:00.123Z"
},
"e1": {
"epochId": 1,
"referenceGasPrice": "1000",
"startTimestamp": "1970-01-01T00:00:00.123Z",
"endTimestamp": "1970-01-01T00:00:00.444Z"
},
"e2": {
"epochId": 2,
"referenceGasPrice": "1000",
"startTimestamp": "1970-01-01T00:00:00.444Z",
"endTimestamp": null
},
"e3": null
}
}

task 7, lines 33-46:
//# run-graphql
Response: {
"data": {
"checkpoint": {
"query": {
"epoch": {
"epochId": 1,
"referenceGasPrice": "1000",
"startTimestamp": "1970-01-01T00:00:00.123Z",
"endTimestamp": null
}
}
}
}
}
52 changes: 52 additions & 0 deletions crates/sui-indexer-alt-graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ String containing Base64-encoded binary data.
"""
scalar Base64

"""
String representation of an arbitrary width, possibly signed integer
"""
scalar BigInt


"""
Checkpoints contain finalized transactions and are used for node synchronization and global transaction ordering.
Expand All @@ -24,6 +29,10 @@ type Checkpoint {
"""
query: Query
"""
The epoch that this checkpoint is part of.
"""
epoch: Epoch
"""
The timestamp at which the checkpoint is agreed to have happened according to consensus. Transactions that access time in this checkpoint will observe this timestamp.
"""
timestamp: DateTime
Expand All @@ -34,6 +43,37 @@ ISO-8601 Date and Time: RFC3339 in UTC with format: YYYY-MM-DDTHH:MM:SS.mmmZ. No
"""
scalar DateTime

"""
Activity on Sui is partitioned in time, into epochs.

Epoch changes are opportunities for the network to reconfigure itself (perform protocol or system package upgrades, or change the committee) and distribute staking rewards. The network aims to keep epochs roughly the same duration as each other.

During a particular epoch the following data is fixed:

- protocol version,
- reference gas price,
- system package versions,
- validators in the committee.
"""
type Epoch {
"""
The epoch's id as a sequence number that starts at 0 and is incremented by one at every epoch change.
"""
epochId: UInt53!
"""
The minimum gas price that a quorum of validators are guaranteed to sign a transaction for in this epoch.
"""
referenceGasPrice: BigInt
"""
The timestamp associated with the first checkpoint in the epoch.
"""
startTimestamp: DateTime
"""
The timestamp associated with the last checkpoint in the epoch (or `null` if the epoch has not finished yet).
"""
endTimestamp: DateTime
}


"""
Interface implemented by GraphQL types representing entities that are identified by an address.
Expand Down Expand Up @@ -270,12 +310,24 @@ type Query {
"""
checkpoint(sequenceNumber: UInt53): Checkpoint
"""
Fetch an epoch by its ID.

Returns `null` if the epoch does not exist yet, or was pruned.
"""
epoch(epochId: UInt53!): Epoch
"""
Fetch checkpoints by their sequence numbers.

Returns a list of checkpoints that is guaranteed to be the same length as `keys`. If a checkpoint in `keys` could not be found in the store, its corresponding entry in the result will be `null`. This could be because the checkpoint does not exist yet, or because it was pruned.
"""
multiGetCheckpoints(keys: [UInt53!]!): [Checkpoint]!
"""
Fetch epochs by their IDs.

Returns a list of epochs that is guarnateed to be the same length as `keys`. If an epoch in `keys` could not be found in the store, its corresponding entry in the result will be `null`. This could be because the epocch does not exist yet, or because it was pruned.
"""
multiGetEpochs(keys: [UInt53!]!): [Epoch]!
"""
Fetch objects by their keys.

Returns a list of objects that is guaranteed to be the same length as `keys`. If an object in `keys` could not be found in the store, its corresponding entry in the result will be `null`. This could be because the object never existed, or because it was pruned.
Expand Down
25 changes: 25 additions & 0 deletions crates/sui-indexer-alt-graphql/src/api/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use super::{
scalars::{digest::Digest, sui_address::SuiAddress, uint53::UInt53},
types::{
checkpoint::Checkpoint,
epoch::Epoch,
move_package::{self, MovePackage, PackageKey},
object::{self, Object, ObjectKey},
service_config::ServiceConfig,
Expand Down Expand Up @@ -50,6 +51,14 @@ impl Query {
Ok(Checkpoint::with_sequence_number(scope, sequence_number))
}

/// Fetch an epoch by its ID.
///
/// Returns `null` if the epoch does not exist yet, or was pruned.
async fn epoch(&self, ctx: &Context<'_>, epoch_id: UInt53) -> Result<Option<Epoch>, RpcError> {
let scope = self.scope(ctx)?;
Epoch::fetch(ctx, scope, epoch_id).await
}

/// Fetch checkpoints by their sequence numbers.
///
/// Returns a list of checkpoints that is guaranteed to be the same length as `keys`. If a checkpoint in `keys` could not be found in the store, its corresponding entry in the result will be `null`. This could be because the checkpoint does not exist yet, or because it was pruned.
Expand All @@ -65,6 +74,22 @@ impl Query {
.collect())
}

/// Fetch epochs by their IDs.
///
/// Returns a list of epochs that is guarnateed to be the same length as `keys`. If an epoch in `keys` could not be found in the store, its corresponding entry in the result will be `null`. This could be because the epocch does not exist yet, or because it was pruned.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Returns a list of epochs that is guarnateed to be the same length as `keys`. If an epoch in `keys` could not be found in the store, its corresponding entry in the result will be `null`. This could be because the epocch does not exist yet, or because it was pruned.
/// Returns a list of epochs that is guaranteed to be the same length as `keys`. If an epoch in `keys` could not be found in the store, its corresponding entry in the result will be `null`. This could be because the epoch does not exist yet, or because it was pruned.

async fn multi_get_epochs(
&self,
ctx: &Context<'_>,
keys: Vec<UInt53>,
) -> Result<Vec<Option<Epoch>>, RpcError> {
let scope = self.scope(ctx)?;
let epochs = keys
.into_iter()
.map(|k| Epoch::fetch(ctx, scope.clone(), k));

try_join_all(epochs).await
}

/// Fetch objects by their keys.
///
/// Returns a list of objects that is guaranteed to be the same length as `keys`. If an object in `keys` could not be found in the store, its corresponding entry in the result will be `null`. This could be because the object never existed, or because it was pruned.
Expand Down
Loading
Loading