fuel_core/schema/
upgrades.rs

1use crate::{
2    graphql_api::{
3        IntoApiResult,
4        api_service::ChainInfoProvider,
5        query_costs,
6    },
7    schema::{
8        ReadViewProvider,
9        chain::ConsensusParameters,
10        scalars::HexString,
11    },
12};
13use async_graphql::{
14    Context,
15    Object,
16    SimpleObject,
17};
18use fuel_core_types::{
19    blockchain::header::{
20        ConsensusParametersVersion,
21        StateTransitionBytecodeVersion,
22    },
23    fuel_types,
24    fuel_vm::UploadedBytecode as StorageUploadedBytecode,
25};
26
27#[derive(Default)]
28pub struct UpgradeQuery;
29
30#[Object]
31impl UpgradeQuery {
32    #[graphql(complexity = "query_costs().storage_read + child_complexity")]
33    async fn consensus_parameters(
34        &self,
35        ctx: &Context<'_>,
36        version: ConsensusParametersVersion,
37    ) -> async_graphql::Result<ConsensusParameters> {
38        let params = ctx
39            .data_unchecked::<ChainInfoProvider>()
40            .consensus_params_at_version(&version)?;
41
42        Ok(ConsensusParameters(params))
43    }
44
45    #[graphql(complexity = "query_costs().storage_read + child_complexity")]
46    async fn state_transition_bytecode_by_version(
47        &self,
48        ctx: &Context<'_>,
49        version: StateTransitionBytecodeVersion,
50    ) -> async_graphql::Result<Option<StateTransitionBytecode>> {
51        let query = ctx.read_view()?;
52        query
53            .state_transition_bytecode_root(version)
54            .into_api_result()
55    }
56
57    #[graphql(complexity = "query_costs().storage_read + child_complexity")]
58    async fn state_transition_bytecode_by_root(
59        &self,
60        root: HexString,
61    ) -> async_graphql::Result<StateTransitionBytecode> {
62        StateTransitionBytecode::try_from(root)
63    }
64}
65
66pub struct StateTransitionBytecode {
67    root: fuel_types::Bytes32,
68}
69
70#[Object]
71impl StateTransitionBytecode {
72    async fn root(&self) -> HexString {
73        HexString(self.root.to_vec())
74    }
75
76    #[graphql(complexity = "query_costs().state_transition_bytecode_read")]
77    async fn bytecode(
78        &self,
79        ctx: &Context<'_>,
80    ) -> async_graphql::Result<UploadedBytecode> {
81        let query = ctx.read_view()?;
82        query
83            .state_transition_bytecode(self.root)
84            .map(UploadedBytecode::from)
85            .map_err(async_graphql::Error::from)
86    }
87}
88
89impl From<fuel_types::Bytes32> for StateTransitionBytecode {
90    fn from(root: fuel_types::Bytes32) -> Self {
91        Self { root }
92    }
93}
94
95impl TryFrom<HexString> for StateTransitionBytecode {
96    type Error = async_graphql::Error;
97
98    fn try_from(root: HexString) -> Result<Self, Self::Error> {
99        let root = root.0.as_slice().try_into()?;
100        Ok(Self { root })
101    }
102}
103
104#[derive(SimpleObject)]
105pub struct UploadedBytecode {
106    /// Combined bytecode of all uploaded subsections.
107    bytecode: HexString,
108    /// Number of uploaded subsections (if incomplete).
109    uploaded_subsections_number: Option<u16>,
110    /// Indicates if the bytecode upload is complete.
111    completed: bool,
112}
113
114impl From<StorageUploadedBytecode> for UploadedBytecode {
115    fn from(value: fuel_core_types::fuel_vm::UploadedBytecode) -> Self {
116        match value {
117            StorageUploadedBytecode::Uncompleted {
118                bytecode,
119                uploaded_subsections_number,
120            } => Self {
121                bytecode: HexString(bytecode),
122                uploaded_subsections_number: Some(uploaded_subsections_number),
123                completed: false,
124            },
125            StorageUploadedBytecode::Completed(bytecode) => Self {
126                bytecode: HexString(bytecode),
127                uploaded_subsections_number: None,
128                completed: true,
129            },
130        }
131    }
132}