-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Add GraphQL extension to provide current STF and CP versions #2715
base: master
Are you sure you want to change the base?
Conversation
…sus_parameters_with_version()`
if let Ok(view) = db.view() { | ||
if let Ok(latest_block) = view.latest_block() { | ||
let current_stf_version = | ||
latest_block.header().state_transition_bytecode_version(); | ||
response.extensions.insert( | ||
CURRENT_STF_VERSION.to_string(), | ||
Value::Number(current_stf_version.into()), | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might prefer reading the current STF version directly from on chain DB table StateTransitionBytecodeVersions
similarly to how it's done in BlockProducerDatabase::latest_state_transition_bytecode_version()
, but I couldn't figure out how to access this in GraphQL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to have a place where we cache this kind of information. Maybe, we could extend consensus parameters provider to also provide this kind of information, because fetch it from the database it a lot of waste work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do that, it might be useful to also add the block height to the information retrieved, as in this case all the extension metadata will come from the same place.
Btw, If I am not mistaken all the information we want to fetch comes from the block header right now, so maybe a HeaderProvider
trait with a function that returns the whole block header, and then stf_version
and consensus_parameters_version
and block_height
can be provided methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'll prefer to extend (and rename) the "Consensus Parameters Provider". However, I find caching the entire block header not optimal and my preference would be to cache exactly what we need. So, in addition to the current data, it'll store:
- current STF version
- current block height
wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the STF version is cached in the "Consensus Parameters Provider", so we do not read from the DB every time, but handling of the current block height remains unchanged from the original implementation.
…onal_graphql_extensions
…d via GraphQL extension
We're currently attaching some substantial number of bytes to every response. Even if user requests just the node version, he will get a bunch of additional data, which, AFAIK, cannot be opted-out from.
Not sure if this should be a concern, but I thought it's worth pointing out. |
we miss the whole point of graphql here, if we provide data no one asked for :( |
Exactly, that's why I was thinking that we should just provide this data via some info endpoint, but IIUC, the idea here is to provide this data proactively instead of requiring users to poll regularly. Maybe there's a way to opt out from extensions which I'm just missing. |
.extension(RequiredFuelBlockHeightExtension::new()) | ||
.extension(CurrentStfVersionExtension::new()) | ||
.extension(CurrentConsensusParametersVersionExtension::new()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think spawning a separate extension for the field it is too overkill=D It decreases performance without any reason
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can have one extension fully dedicated to return information to the end user. Like STFV, CPV, current block height(we can remove setting of the current height from the RequiredFuelBlockHeightExtension
).
In this case we will have one extension that we can use to add any metadata
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following changes have been made:
- Both STF and CP extensions have been merged into "chain state info" extension
- The "chain state info" extension is now also providing data about the current block height
if let Ok(view) = db.view() { | ||
if let Ok(latest_block) = view.latest_block() { | ||
let current_stf_version = | ||
latest_block.header().state_transition_bytecode_version(); | ||
response.extensions.insert( | ||
CURRENT_STF_VERSION.to_string(), | ||
Value::Number(current_stf_version.into()), | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to have a place where we cache this kind of information. Maybe, we could extend consensus parameters provider to also provide this kind of information, because fetch it from the database it a lot of waste work.
tests/test-helpers/src/lib.rs
Outdated
vec![op::ret(1)].into_iter().collect::<Vec<u8>>() | ||
} | ||
|
||
pub fn get_graphql_extension_field_value(result_json: &str, name: &str) -> u64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fuel-core-client
should fetch this information in the same way how it is done for the required block height. We have ExtensionsResponse
where you can add several new fields.
Implementation details: In the case of the CPV and STFV we don't need any policy, we just can fetch the latest one and provide a getter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in ef9c445
The |
crates/fuel-core/src/graphql_api/extensions/current_consensus_parameters_version.rs
Outdated
Show resolved
Hide resolved
420319f
to
3f3e971
Compare
Done in: b861a51 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to mee, small things to change and we are good to go=)
crates/client/src/client.rs
Outdated
@@ -333,6 +388,8 @@ impl FuelClient { | |||
.await | |||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; | |||
|
|||
self.update_chain_state_info(&response); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to do it in the Self::decode_response
function because we also want to handle the case of subscriptions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in 3aa2d2d
// `RequiredFuelBlockHeightExtension` uses the view set by the ViewExtension. | ||
// Do not reorder this line before adding the `ViewExtension`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// `RequiredFuelBlockHeightExtension` uses the view set by the ViewExtension. | |
// Do not reorder this line before adding the `ViewExtension`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 3f32362
let current_stf_version = block.header().state_transition_bytecode_version(); | ||
self.stf_parameters_provider | ||
.cache_stf_version(current_stf_version); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, that was a bit of a code smell since the beginning.
Updated in 932a1c5
@@ -117,7 +117,7 @@ impl MessageCoin { | |||
async fn asset_id(&self, ctx: &Context<'_>) -> AssetId { | |||
let params = ctx | |||
.data_unchecked::<ConsensusProvider>() | |||
.latest_consensus_params(); | |||
.current_consensus_params(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May I also ask you to replace Mutex
in the ConsensusProvider
with RwLock
please?=)
Since we only read in most of the cases and write happens once per month
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in d8ea573
pub(crate) consensus_parameters: | ||
SharedMutex<HashMap<ConsensusParametersVersion, Arc<ConsensusParameters>>>, | ||
pub(crate) latest_stf_version: SharedMutex<StateTransitionBytecodeVersion>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May I also ask you to replace Mutex
with RwLock
for consensus_parameters
and latest_stf_version
please?=)
Since we only read in most of the cases and write happens once per month
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in d8ea573
…al_graphql_extensions
…al_graphql_extensions
…in subscriptions
…al_graphql_extensions
crates/client/src/client.rs
Outdated
fn decode_response<R, E>( | ||
&self, | ||
response: FuelGraphQlResponse<R, E>, | ||
inner_required_height: Option<Arc<Mutex<Option<BlockHeight>>>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are able to use &self
, then you can remove inner_required_height
(move logic inside update_chain_state_info
) and update everything in one function=)
if !update_cached_value( | ||
&self.shared_state.latest_consensus_parameters_version, | ||
new_consensus_parameters_version, | ||
|| self.shared_state.cache_consensus_parameters(new_consensus_parameters_version).map(|_| ()) | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have a deadlock here. self.shared_state.cache_consensus_parameters
is doing write lock inside and update_cached_value
is doing upgradable lock
Linked Issues/PRs
Closes #2596
Description
This PR adds new GraphQL extensions to provide:
Example response:
Additional housekeeping changes:
TODO
Checklist
Before requesting review
After merging, notify other teams