From 008d4d90ab1ad6eb994792729d40af84bb06c209 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 2 Oct 2024 02:10:47 +0200 Subject: [PATCH 1/6] Change complexity block --- crates/fuel-core/src/graphql_api.rs | 2 + crates/fuel-core/src/schema/block.rs | 6 +- tests/tests/dos.rs | 91 +++++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/crates/fuel-core/src/graphql_api.rs b/crates/fuel-core/src/graphql_api.rs index c3fc9abb991..e469a4471ca 100644 --- a/crates/fuel-core/src/graphql_api.rs +++ b/crates/fuel-core/src/graphql_api.rs @@ -40,6 +40,7 @@ pub struct Costs { pub storage_read: usize, pub storage_iterator: usize, pub bytecode_read: usize, + pub get_block: usize, } pub const QUERY_COSTS: Costs = Costs { @@ -59,6 +60,7 @@ pub const QUERY_COSTS: Costs = Costs { storage_read: 10, storage_iterator: 100, bytecode_read: 2000, + get_block: 1990, }; #[derive(Clone, Debug)] diff --git a/crates/fuel-core/src/schema/block.rs b/crates/fuel-core/src/schema/block.rs index ee9c3e78f8c..aedb936a6cb 100644 --- a/crates/fuel-core/src/schema/block.rs +++ b/crates/fuel-core/src/schema/block.rs @@ -246,7 +246,7 @@ pub struct BlockQuery; #[Object] impl BlockQuery { - #[graphql(complexity = "2 * QUERY_COSTS.storage_read + child_complexity")] + #[graphql(complexity = "QUERY_COSTS.get_block")] async fn block( &self, ctx: &Context<'_>, @@ -277,8 +277,8 @@ impl BlockQuery { #[graphql(complexity = "{\ QUERY_COSTS.storage_iterator\ - + (QUERY_COSTS.storage_read + first.unwrap_or_default() as usize) * child_complexity \ - + (QUERY_COSTS.storage_read + last.unwrap_or_default() as usize) * child_complexity\ + + (QUERY_COSTS.get_block * first.unwrap_or_default() as usize) \ + + (QUERY_COSTS.get_block * last.unwrap_or_default() as usize) \ }")] async fn blocks( &self, diff --git a/tests/tests/dos.rs b/tests/tests/dos.rs index e038c70d297..8c49765d21b 100644 --- a/tests/tests/dos.rs +++ b/tests/tests/dos.rs @@ -85,7 +85,96 @@ async fn complex_queries__10_blocks__works() { blocks(first: 10) { nodes { transactions { - id + status { + __typename + ... on SubmittedStatus { + time + } + ... on SuccessStatus { + blockHeight + time + programState { + returnType + data + } + receipts { + param1 + param2 + amount + assetId + gas + digest + id + is + pc + ptr + ra + rb + rc + rd + reason + receiptType + to + toAddress + val + len + result + gasUsed + data + sender + recipient + nonce + contractId + subId + } + totalGas + totalFee + } + ... on SqueezedOutStatus { + reason + } + ... on FailureStatus { + blockHeight + time + reason + programState { + returnType + data + } + receipts { + param1 + param2 + amount + assetId + gas + digest + id + is + pc + ptr + ra + rb + rc + rd + reason + receiptType + to + toAddress + val + len + result + gasUsed + data + sender + recipient + nonce + contractId + subId + } + totalGas + totalFee + } + } } } } From 114713638ba009069a94cbd75bc011a759206200 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 2 Oct 2024 03:54:00 +0200 Subject: [PATCH 2/6] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b9a61b3498..25948d102d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [2204](https://github.com/FuelLabs/fuel-core/pull/2204): Added `dnsaddr` resolution for TLD without suffixes. ### Changed +- [2276](https://github.com/FuelLabs/fuel-core/pull/2276): Change complexity block query to allow fetching of 10 blocks #### Breaking - [2199](https://github.com/FuelLabs/fuel-core/pull/2199): Applying several breaking changes to the WASM interface from backlog: From 18513c5a1e7cbf4ae1710b0ead624ea532fb68b8 Mon Sep 17 00:00:00 2001 From: AurelienFT Date: Wed, 2 Oct 2024 11:04:45 +0200 Subject: [PATCH 3/6] update test --- tests/tests/dos.rs | 211 +++++++++++++++++++++++++++------------------ 1 file changed, 128 insertions(+), 83 deletions(-) diff --git a/tests/tests/dos.rs b/tests/tests/dos.rs index 8c49765d21b..64a6f6e9741 100644 --- a/tests/tests/dos.rs +++ b/tests/tests/dos.rs @@ -83,100 +83,144 @@ async fn complex_queries__10_blocks__works() { let query = r#" query { blocks(first: 10) { - nodes { - transactions { - status { + edges { + cursor + node { + id + header { + id + daHeight + consensusParametersVersion + stateTransitionBytecodeVersion + transactionsCount + messageReceiptCount + transactionsRoot + messageOutboxRoot + eventInboxRoot + height + prevRoot + time + applicationHash + } + consensus { __typename - ... on SubmittedStatus { - time + ... on Genesis { + chainConfigHash + coinsRoot + contractsRoot + messagesRoot + transactionsRoot } - ... on SuccessStatus { - blockHeight - time - programState { - returnType - data + ... on PoAConsensus { + signature + } + } + transactions { + rawPayload + status { + ... on SubmittedStatus { + time } - receipts { - param1 - param2 - amount - assetId - gas - digest - id - is - pc - ptr - ra - rb - rc - rd - reason - receiptType - to - toAddress - val - len - result - gasUsed - data - sender - recipient - nonce - contractId - subId + ... on SuccessStatus { + transactionId + block { + height + } + time + programState { + returnType + data + } + receipts { + param1 + param2 + amount + assetId + gas + digest + id + is + pc + ptr + ra + rb + rc + rd + reason + receiptType + to + toAddress + val + len + result + gasUsed + data + sender + recipient + nonce + contractId + subId + } + totalGas + totalFee } - totalGas - totalFee - } - ... on SqueezedOutStatus { - reason - } - ... on FailureStatus { - blockHeight - time - reason - programState { - returnType - data + ... on SqueezedOutStatus { + reason } - receipts { - param1 - param2 - amount - assetId - gas - digest - id - is - pc - ptr - ra - rb - rc - rd + ... on FailureStatus { + transactionId + block { + height + } + time reason - receiptType - to - toAddress - val - len - result - gasUsed - data - sender - recipient - nonce - contractId - subId + programState { + returnType + data + } + receipts { + param1 + param2 + amount + assetId + gas + digest + id + is + pc + ptr + ra + rb + rc + rd + reason + receiptType + to + toAddress + val + len + result + gasUsed + data + sender + recipient + nonce + contractId + subId + } + totalGas + totalFee } - totalGas - totalFee } } } } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } } } "#; @@ -185,6 +229,7 @@ async fn complex_queries__10_blocks__works() { let url = format!("http://{}/v1/graphql", node.bound_address); let result = send_graph_ql_query(&url, query).await; + dbg!(&result); assert!(result.contains("transactions")); } From 818cc4c564121afc206628871b7bfbdb1e0c0394 Mon Sep 17 00:00:00 2001 From: green Date: Wed, 2 Oct 2024 12:04:14 +0200 Subject: [PATCH 4/6] Add more tests for DoS case. Reworked how we charge for blocks to allow many headers. Fixed DoS for `transactions`. Fixed DoS for state transition bytecode. --- crates/fuel-core/src/graphql_api.rs | 16 +- crates/fuel-core/src/schema/block.rs | 21 +- crates/fuel-core/src/schema/gas_price.rs | 2 +- crates/fuel-core/src/schema/tx.rs | 6 +- crates/fuel-core/src/schema/tx/types.rs | 6 +- crates/fuel-core/src/schema/upgrades.rs | 1 + tests/tests/dos.rs | 350 +++++++++++++++-------- 7 files changed, 260 insertions(+), 142 deletions(-) diff --git a/crates/fuel-core/src/graphql_api.rs b/crates/fuel-core/src/graphql_api.rs index e469a4471ca..961bea4ac5a 100644 --- a/crates/fuel-core/src/graphql_api.rs +++ b/crates/fuel-core/src/graphql_api.rs @@ -38,9 +38,15 @@ pub struct Costs { pub status_change: usize, pub raw_payload: usize, pub storage_read: usize, + pub tx_get: usize, + pub tx_status_read: usize, + pub tx_raw_payload: usize, + pub block_header: usize, + pub block_transactions: usize, + pub block_transactions_ids: usize, pub storage_iterator: usize, pub bytecode_read: usize, - pub get_block: usize, + pub state_transition_bytecode_read: usize, } pub const QUERY_COSTS: Costs = Costs { @@ -58,9 +64,15 @@ pub const QUERY_COSTS: Costs = Costs { status_change: 10001, raw_payload: 10, storage_read: 10, + tx_get: 50, + tx_status_read: 50, + tx_raw_payload: 150, + block_header: 150, + block_transactions: 1500, + block_transactions_ids: 50, storage_iterator: 100, bytecode_read: 2000, - get_block: 1990, + state_transition_bytecode_read: 19_000, }; #[derive(Clone, Debug)] diff --git a/crates/fuel-core/src/schema/block.rs b/crates/fuel-core/src/schema/block.rs index aedb936a6cb..81a9bf3c0af 100644 --- a/crates/fuel-core/src/schema/block.rs +++ b/crates/fuel-core/src/schema/block.rs @@ -125,6 +125,7 @@ impl Block { Ok(query.consensus(height)?.try_into()?) } + #[graphql(complexity = "QUERY_COSTS.block_transactions_ids")] async fn transaction_ids(&self) -> Vec { self.0 .transactions() @@ -134,8 +135,7 @@ impl Block { } // Assume that in average we have 32 transactions per block. - #[graphql(complexity = "QUERY_COSTS.storage_iterator\ - + (QUERY_COSTS.storage_read + child_complexity) * 32")] + #[graphql(complexity = "QUERY_COSTS.block_transactions + child_complexity")] async fn transactions( &self, ctx: &Context<'_>, @@ -246,7 +246,7 @@ pub struct BlockQuery; #[Object] impl BlockQuery { - #[graphql(complexity = "QUERY_COSTS.get_block")] + #[graphql(complexity = "QUERY_COSTS.block_header + child_complexity")] async fn block( &self, ctx: &Context<'_>, @@ -276,9 +276,8 @@ impl BlockQuery { } #[graphql(complexity = "{\ - QUERY_COSTS.storage_iterator\ - + (QUERY_COSTS.get_block * first.unwrap_or_default() as usize) \ - + (QUERY_COSTS.get_block * last.unwrap_or_default() as usize) \ + (QUERY_COSTS.block_header + child_complexity) \ + * (first.unwrap_or_default() as usize + last.unwrap_or_default() as usize) \ }")] async fn blocks( &self, @@ -305,7 +304,7 @@ pub struct HeaderQuery; #[Object] impl HeaderQuery { - #[graphql(complexity = "QUERY_COSTS.storage_read + child_complexity")] + #[graphql(complexity = "QUERY_COSTS.block_header + child_complexity")] async fn header( &self, ctx: &Context<'_>, @@ -319,9 +318,8 @@ impl HeaderQuery { } #[graphql(complexity = "{\ - QUERY_COSTS.storage_iterator\ - + (QUERY_COSTS.storage_read + first.unwrap_or_default() as usize) * child_complexity \ - + (QUERY_COSTS.storage_read + last.unwrap_or_default() as usize) * child_complexity\ + (QUERY_COSTS.block_header + child_complexity) \ + * (first.unwrap_or_default() as usize + last.unwrap_or_default() as usize) \ }")] async fn headers( &self, @@ -374,13 +372,14 @@ impl BlockMutation { start_timestamp: Option, blocks_to_produce: U32, ) -> async_graphql::Result { - let consensus_module = ctx.data_unchecked::(); let config = ctx.data_unchecked::().clone(); if !config.debug { return Err(anyhow!("`debug` must be enabled to use this endpoint").into()) } + let consensus_module = ctx.data_unchecked::(); + let start_time = start_timestamp.map(|timestamp| timestamp.0); let blocks_to_produce: u32 = blocks_to_produce.into(); consensus_module diff --git a/crates/fuel-core/src/schema/gas_price.rs b/crates/fuel-core/src/schema/gas_price.rs index 577d68cec9e..f1ded5fc106 100644 --- a/crates/fuel-core/src/schema/gas_price.rs +++ b/crates/fuel-core/src/schema/gas_price.rs @@ -46,7 +46,7 @@ pub struct LatestGasPriceQuery {} #[Object] impl LatestGasPriceQuery { - #[graphql(complexity = "2 * QUERY_COSTS.storage_read")] + #[graphql(complexity = "QUERY_COSTS.block_header")] async fn latest_gas_price( &self, ctx: &Context<'_>, diff --git a/crates/fuel-core/src/schema/tx.rs b/crates/fuel-core/src/schema/tx.rs index ce860a97084..6785c1f79df 100644 --- a/crates/fuel-core/src/schema/tx.rs +++ b/crates/fuel-core/src/schema/tx.rs @@ -111,10 +111,10 @@ impl TxQuery { } } + // We assume that each block has 100 transactions. #[graphql(complexity = "{\ - QUERY_COSTS.storage_iterator\ - + (QUERY_COSTS.storage_read + first.unwrap_or_default() as usize) * child_complexity \ - + (QUERY_COSTS.storage_read + last.unwrap_or_default() as usize) * child_complexity\ + (QUERY_COSTS.tx_get + child_complexity) \ + * (first.unwrap_or_default() as usize + last.unwrap_or_default() as usize) }")] async fn transactions( &self, diff --git a/crates/fuel-core/src/schema/tx/types.rs b/crates/fuel-core/src/schema/tx/types.rs index 9496a5bda22..b7394fd1751 100644 --- a/crates/fuel-core/src/schema/tx/types.rs +++ b/crates/fuel-core/src/schema/tx/types.rs @@ -182,7 +182,7 @@ impl SuccessStatus { self.block_height.into() } - #[graphql(complexity = "QUERY_COSTS.storage_read + child_complexity")] + #[graphql(complexity = "QUERY_COSTS.block_header + child_complexity")] async fn block(&self, ctx: &Context<'_>) -> async_graphql::Result { let query = ctx.read_view()?; let block = query.block(&self.block_height)?; @@ -238,7 +238,7 @@ impl FailureStatus { self.block_height.into() } - #[graphql(complexity = "QUERY_COSTS.storage_read + child_complexity")] + #[graphql(complexity = "QUERY_COSTS.block_header + child_complexity")] async fn block(&self, ctx: &Context<'_>) -> async_graphql::Result { let query = ctx.read_view()?; let block = query.block(&self.block_height)?; @@ -693,7 +693,7 @@ impl Transaction { } } - #[graphql(complexity = "QUERY_COSTS.storage_read + child_complexity")] + #[graphql(complexity = "QUERY_COSTS.tx_status_read + child_complexity")] async fn status( &self, ctx: &Context<'_>, diff --git a/crates/fuel-core/src/schema/upgrades.rs b/crates/fuel-core/src/schema/upgrades.rs index bda98240304..d9e62906a1e 100644 --- a/crates/fuel-core/src/schema/upgrades.rs +++ b/crates/fuel-core/src/schema/upgrades.rs @@ -74,6 +74,7 @@ impl StateTransitionBytecode { HexString(self.root.to_vec()) } + #[graphql(complexity = "QUERY_COSTS.state_transition_bytecode_read")] async fn bytecode( &self, ctx: &Context<'_>, diff --git a/tests/tests/dos.rs b/tests/tests/dos.rs index 64a6f6e9741..821a76599ff 100644 --- a/tests/tests/dos.rs +++ b/tests/tests/dos.rs @@ -5,6 +5,7 @@ use fuel_core::service::{ FuelService, ServiceTrait, }; +use fuel_core_types::blockchain::header::LATEST_STATE_TRANSITION_VERSION; use test_helpers::send_graph_ql_query; #[tokio::test] @@ -78,11 +79,177 @@ async fn complex_queries__recursion() { assert!(result.contains("The recursion depth of the query cannot be greater than")); } +const FULL_BLOCK_QUERY: &str = r#" + query { + blocks(first: $NUMBER_OF_BLOCKS) { + edges { + cursor + node { + id + header { + id + daHeight + consensusParametersVersion + stateTransitionBytecodeVersion + transactionsCount + messageReceiptCount + transactionsRoot + messageOutboxRoot + eventInboxRoot + height + prevRoot + time + applicationHash + } + consensus { + ... on Genesis { + chainConfigHash + coinsRoot + contractsRoot + messagesRoot + transactionsRoot + } + ... on PoAConsensus { + signature + } + } + transactions { + rawPayload + status { + ... on SubmittedStatus { + time + } + ... on SuccessStatus { + transactionId + block { + height + } + time + programState { + returnType + data + } + receipts { + param1 + param2 + amount + assetId + gas + digest + id + is + pc + ptr + ra + rb + rc + rd + reason + receiptType + to + toAddress + val + len + result + gasUsed + data + sender + recipient + nonce + contractId + subId + } + totalGas + totalFee + } + ... on SqueezedOutStatus { + reason + } + ... on FailureStatus { + transactionId + blockHeight + time + reason + programState { + returnType + data + } + receipts { + param1 + param2 + amount + assetId + gas + digest + id + is + pc + ptr + ra + rb + rc + rd + reason + receiptType + to + toAddress + val + len + result + gasUsed + data + sender + recipient + nonce + contractId + subId + } + totalGas + totalFee + } + } + } + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } +"#; + #[tokio::test] -async fn complex_queries__10_blocks__works() { +async fn complex_queries__10_full_blocks__works() { + let query = FULL_BLOCK_QUERY.to_string(); + let query = query.replace("$NUMBER_OF_BLOCKS", "10"); + + let node = FuelService::new_node(Config::local_node()).await.unwrap(); + let url = format!("http://{}/v1/graphql", node.bound_address); + + let result = send_graph_ql_query(&url, query.as_str()).await; + assert!(result.contains("transactions")); +} + +#[tokio::test] +async fn complex_queries__11_full_block__query_to_complex() { + let query = FULL_BLOCK_QUERY.to_string(); + let query = query.replace("$NUMBER_OF_BLOCKS", "11"); + + let node = FuelService::new_node(Config::local_node()).await.unwrap(); + let url = format!("http://{}/v1/graphql", node.bound_address); + + let result = send_graph_ql_query(&url, query.as_str()).await; + assert!(result.contains("Query is too complex.")); +} + +#[tokio::test] +async fn complex_queries__100_block_headers__works() { let query = r#" query { - blocks(first: 10) { + blocks(first: 100) { edges { cursor node { @@ -103,7 +270,6 @@ async fn complex_queries__10_blocks__works() { applicationHash } consensus { - __typename ... on Genesis { chainConfigHash coinsRoot @@ -115,104 +281,6 @@ async fn complex_queries__10_blocks__works() { signature } } - transactions { - rawPayload - status { - ... on SubmittedStatus { - time - } - ... on SuccessStatus { - transactionId - block { - height - } - time - programState { - returnType - data - } - receipts { - param1 - param2 - amount - assetId - gas - digest - id - is - pc - ptr - ra - rb - rc - rd - reason - receiptType - to - toAddress - val - len - result - gasUsed - data - sender - recipient - nonce - contractId - subId - } - totalGas - totalFee - } - ... on SqueezedOutStatus { - reason - } - ... on FailureStatus { - transactionId - block { - height - } - time - reason - programState { - returnType - data - } - receipts { - param1 - param2 - amount - assetId - gas - digest - id - is - pc - ptr - ra - rb - rc - rd - reason - receiptType - to - toAddress - val - len - result - gasUsed - data - sender - recipient - nonce - contractId - subId - } - totalGas - totalFee - } - } - } } } pageInfo { @@ -221,6 +289,12 @@ async fn complex_queries__10_blocks__works() { hasPreviousPage startCursor } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } } } "#; @@ -233,27 +307,6 @@ async fn complex_queries__10_blocks__works() { assert!(result.contains("transactions")); } -#[tokio::test] -async fn complex_queries__50_block__query_to_complex() { - let query = r#" - query { - blocks(first: 50) { - nodes { - transactions { - id - } - } - } - } - "#; - - let node = FuelService::new_node(Config::local_node()).await.unwrap(); - let url = format!("http://{}/v1/graphql", node.bound_address); - - let result = send_graph_ql_query(&url, query).await; - assert!(result.contains("Query is too complex.")); -} - #[tokio::test] async fn body_limit_prevents_from_huge_queries() { // Given @@ -274,3 +327,56 @@ async fn body_limit_prevents_from_huge_queries() { let result = response.unwrap(); assert_eq!(result.status(), 413); } + +#[tokio::test] +async fn complex_queries__1_state_transition_bytecode__works() { + let version = LATEST_STATE_TRANSITION_VERSION; + let query = r#" + query { + stateTransitionBytecodeByVersion(version: $VERSION) { + bytecode { + uploadedSubsectionsNumber + bytecode + completed + } + } + }"# + .to_string(); + let query = query.replace("$VERSION", version.to_string().as_str()); + + let node = FuelService::new_node(Config::local_node()).await.unwrap(); + let url = format!("http://{}/v1/graphql", node.bound_address); + + let result = send_graph_ql_query(&url, query.as_str()).await; + assert!(result.contains("bytecode"), "{}", result); +} + +#[tokio::test] +async fn complex_queries__2_state_transition_bytecode__query_to_complex() { + let version = LATEST_STATE_TRANSITION_VERSION; + let query = r#" + query { + stateTransitionBytecodeByVersion(version: $VERSION) { + bytecode { + uploadedSubsectionsNumber + bytecode + completed + } + } + stateTransitionBytecodeByVersion(version: $VERSION) { + bytecode { + uploadedSubsectionsNumber + bytecode + completed + } + } + }"# + .to_string(); + let query = query.replace("$VERSION", version.to_string().as_str()); + + let node = FuelService::new_node(Config::local_node()).await.unwrap(); + let url = format!("http://{}/v1/graphql", node.bound_address); + + let result = send_graph_ql_query(&url, query.as_str()).await; + assert!(result.contains("Query is too complex.")); +} From 8599d7242416cd587a7ca248a43572cd1e548ff2 Mon Sep 17 00:00:00 2001 From: green Date: Wed, 2 Oct 2024 12:28:53 +0200 Subject: [PATCH 5/6] Fix the integration test --- tests/tests/regenesis.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 94d67d241ff..3ba03d27366 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -66,6 +66,7 @@ async fn take_snapshot(db_dir: &TempDir, snapshot_dir: &TempDir) -> anyhow::Resu #[tokio::test(flavor = "multi_thread")] async fn test_regenesis_old_blocks_are_preserved() -> anyhow::Result<()> { + const BLOCKS_QUERY: i32 = 50; let mut rng = StdRng::seed_from_u64(1234); let core = @@ -77,7 +78,7 @@ async fn test_regenesis_old_blocks_are_preserved() -> anyhow::Result<()> { .client .blocks(PaginationRequest { cursor: None, - results: 100, + results: BLOCKS_QUERY, direction: PageDirection::Forward, }) .await @@ -112,7 +113,7 @@ async fn test_regenesis_old_blocks_are_preserved() -> anyhow::Result<()> { .client .blocks(PaginationRequest { cursor: None, - results: 100, + results: BLOCKS_QUERY, direction: PageDirection::Forward, }) .await @@ -150,7 +151,7 @@ async fn test_regenesis_old_blocks_are_preserved() -> anyhow::Result<()> { .client .blocks(PaginationRequest { cursor: None, - results: 100, + results: BLOCKS_QUERY, direction: PageDirection::Forward, }) .await From dd6d7617d4b0a00270f36459a890a754263bacd8 Mon Sep 17 00:00:00 2001 From: green Date: Fri, 4 Oct 2024 00:31:56 +0200 Subject: [PATCH 6/6] Use 80k as a default value for complexity. --- bin/fuel-core/src/cli/run/graphql.rs | 2 +- crates/fuel-core/src/graphql_api.rs | 20 ++++++++++---------- crates/fuel-core/src/service/config.rs | 2 +- tests/tests/dos.rs | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/bin/fuel-core/src/cli/run/graphql.rs b/bin/fuel-core/src/cli/run/graphql.rs index 66ab6f06886..422c4e202a6 100644 --- a/bin/fuel-core/src/cli/run/graphql.rs +++ b/bin/fuel-core/src/cli/run/graphql.rs @@ -17,7 +17,7 @@ pub struct GraphQLArgs { pub graphql_max_depth: usize, /// The max complexity of GraphQL queries. - #[clap(long = "graphql-max-complexity", default_value = "20000", env)] + #[clap(long = "graphql-max-complexity", default_value = "80000", env)] pub graphql_max_complexity: usize, /// The max recursive depth of GraphQL queries. diff --git a/crates/fuel-core/src/graphql_api.rs b/crates/fuel-core/src/graphql_api.rs index 961bea4ac5a..fefab94b0ef 100644 --- a/crates/fuel-core/src/graphql_api.rs +++ b/crates/fuel-core/src/graphql_api.rs @@ -51,17 +51,17 @@ pub struct Costs { pub const QUERY_COSTS: Costs = Costs { // balance_query: 4000, - balance_query: 10001, - coins_to_spend: 10001, + balance_query: 40001, + coins_to_spend: 40001, // get_peers: 2000, - get_peers: 10001, + get_peers: 40001, // estimate_predicates: 3000, - estimate_predicates: 10001, - dry_run: 3000, + estimate_predicates: 40001, + dry_run: 12000, // submit: 5000, - submit: 10001, - submit_and_await: 10001, - status_change: 10001, + submit: 40001, + submit_and_await: 40001, + status_change: 40001, raw_payload: 10, storage_read: 10, tx_get: 50, @@ -71,8 +71,8 @@ pub const QUERY_COSTS: Costs = Costs { block_transactions: 1500, block_transactions_ids: 50, storage_iterator: 100, - bytecode_read: 2000, - state_transition_bytecode_read: 19_000, + bytecode_read: 8000, + state_transition_bytecode_read: 76_000, }; #[derive(Clone, Debug)] diff --git a/crates/fuel-core/src/service/config.rs b/crates/fuel-core/src/service/config.rs index 092909929a1..83ae8002143 100644 --- a/crates/fuel-core/src/service/config.rs +++ b/crates/fuel-core/src/service/config.rs @@ -134,7 +134,7 @@ impl Config { 0, ), max_queries_depth: 16, - max_queries_complexity: 20000, + max_queries_complexity: 80000, max_queries_recursive_depth: 16, request_body_bytes_limit: 16 * 1024 * 1024, query_log_threshold_time: Duration::from_secs(2), diff --git a/tests/tests/dos.rs b/tests/tests/dos.rs index 821a76599ff..1bfc527555c 100644 --- a/tests/tests/dos.rs +++ b/tests/tests/dos.rs @@ -222,9 +222,9 @@ const FULL_BLOCK_QUERY: &str = r#" "#; #[tokio::test] -async fn complex_queries__10_full_blocks__works() { +async fn complex_queries__40_full_blocks__works() { let query = FULL_BLOCK_QUERY.to_string(); - let query = query.replace("$NUMBER_OF_BLOCKS", "10"); + let query = query.replace("$NUMBER_OF_BLOCKS", "40"); let node = FuelService::new_node(Config::local_node()).await.unwrap(); let url = format!("http://{}/v1/graphql", node.bound_address); @@ -234,9 +234,9 @@ async fn complex_queries__10_full_blocks__works() { } #[tokio::test] -async fn complex_queries__11_full_block__query_to_complex() { +async fn complex_queries__41_full_block__query_to_complex() { let query = FULL_BLOCK_QUERY.to_string(); - let query = query.replace("$NUMBER_OF_BLOCKS", "11"); + let query = query.replace("$NUMBER_OF_BLOCKS", "41"); let node = FuelService::new_node(Config::local_node()).await.unwrap(); let url = format!("http://{}/v1/graphql", node.bound_address);