From 0eb7180e647add9cd3ea762933844f6a99c0cdfe Mon Sep 17 00:00:00 2001 From: Shashank Date: Mon, 22 Jun 2026 11:14:20 +0530 Subject: [PATCH 1/4] use NotNullVec --- src/lotus_json/vec.rs | 3 +- src/rpc/methods/eth.rs | 38 ++++++++++++++++--- .../forest__rpc__tests__rpc__v0.snap | 17 +++------ .../forest__rpc__tests__rpc__v1.snap | 17 +++------ .../forest__rpc__tests__rpc__v2.snap | 17 +++------ 5 files changed, 52 insertions(+), 40 deletions(-) diff --git a/src/lotus_json/vec.rs b/src/lotus_json/vec.rs index 342139fa9463..afae9ed49c2a 100644 --- a/src/lotus_json/vec.rs +++ b/src/lotus_json/vec.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0, MIT use super::*; +use get_size2::GetSize; impl HasLotusJson for Vec // TODO(forest): https://github.com/ChainSafe/forest/issues/4032 @@ -37,7 +38,7 @@ where // while an empty `NotNullVec` serializes into `[]` // this is a temporary workaround and will likely be deprecated once // other issues on serde of `Vec` are resolved. -#[derive(Debug, Clone, PartialEq, JsonSchema)] +#[derive(Debug, Clone, Default, PartialEq, JsonSchema, GetSize)] pub struct NotNullVec(pub Vec); impl HasLotusJson for NotNullVec diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index b8f1c3f99436..46347eafdbd6 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -26,7 +26,7 @@ use crate::eth::{ EAMMethod, EVMMethod, EthChainId as EthChainIdType, EthEip1559TxArgs, EthLegacyEip155TxArgs, EthLegacyHomesteadTxArgs, parse_eth_transaction, }; -use crate::lotus_json::{HasLotusJson, lotus_json_with_self}; +use crate::lotus_json::{HasLotusJson, NotNullVec, lotus_json_with_self}; use crate::message::{ChainMessage, MessageRead as _, MessageReadWrite as _, SignedMessage}; use crate::networks::Height; use crate::prelude::*; @@ -642,9 +642,9 @@ pub struct ApiEthTx { pub max_priority_fee_per_gas: Option, #[serde(skip_serializing_if = "Option::is_none", default)] pub gas_price: Option, - #[schemars(with = "Option>")] + #[schemars(with = "Vec")] #[serde(with = "crate::lotus_json")] - pub access_list: Vec, + pub access_list: NotNullVec, pub v: EthBigInt, pub r: EthBigInt, pub s: EthBigInt, @@ -846,7 +846,7 @@ impl RpcMethod<0> for EthAccounts { ); type Params = (); - type Ok = Vec; + type Ok = NotNullVec; async fn handle( _: Ctx, @@ -854,7 +854,7 @@ impl RpcMethod<0> for EthAccounts { _: &http::Extensions, ) -> Result { // EthAccounts will always return [] since we don't expect Forest to manage private keys - Ok(vec![]) + Ok(NotNullVec(vec![])) } } @@ -1263,7 +1263,7 @@ fn eth_tx_from_native_message( gas: EthUint64(msg.gas_limit), max_fee_per_gas: Some(msg.gas_fee_cap.clone().into()), max_priority_fee_per_gas: Some(msg.gas_premium.clone().into()), - access_list: vec![], + access_list: NotNullVec(vec![]), ..ApiEthTx::default() }) } @@ -4202,6 +4202,32 @@ mod test { } } + #[test] + fn empty_access_list_serializes_as_empty_array() { + let tx = ApiEthTx::default(); + assert!(tx.access_list.0.is_empty()); + let json = serde_json::to_value(tx.into_lotus_json()).unwrap(); + assert_eq!(json["accessList"], serde_json::json!([])); + } + + #[test] + fn populated_access_list_serializes_as_array() { + let tx = ApiEthTx { + access_list: NotNullVec(vec![EthHash::default()]), + ..Default::default() + }; + let json = serde_json::to_value(tx.into_lotus_json()).unwrap(); + assert!(json["accessList"].is_array()); + assert_eq!(json["accessList"].as_array().unwrap().len(), 1); + } + + #[test] + fn empty_eth_accounts_serializes_as_empty_array() { + let accounts: NotNullVec = NotNullVec(vec![]); + let json = serde_json::to_value(accounts.into_lotus_json()).unwrap(); + assert_eq!(json, serde_json::json!([])); + } + #[quickcheck] fn gas_price_result_serde_roundtrip(i: u128) { let r = EthBigInt(ethereum_types::U256::from(i)); diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap index 3c699e5a5fbd..129bb4729d0d 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap @@ -474,11 +474,9 @@ methods: params: [] result: name: Filecoin.EthAccounts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: type: string paramStructure: by-position @@ -487,11 +485,9 @@ methods: params: [] result: name: eth_accounts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: type: string paramStructure: by-position @@ -4759,9 +4755,7 @@ components: type: object properties: accessList: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthHash" blockHash: @@ -4820,6 +4814,7 @@ components: - type - input - gas + - accessList - v - r - s diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap index ab6785285969..5a019a2b68e2 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap @@ -470,11 +470,9 @@ methods: params: [] result: name: Filecoin.EthAccounts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: type: string paramStructure: by-position @@ -483,11 +481,9 @@ methods: params: [] result: name: eth_accounts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: type: string paramStructure: by-position @@ -4829,9 +4825,7 @@ components: type: object properties: accessList: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthHash" blockHash: @@ -4890,6 +4884,7 @@ components: - type - input - gas + - accessList - v - r - s diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap index 719d85d9ad27..3a248fba219e 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap @@ -74,11 +74,9 @@ methods: params: [] result: name: Filecoin.EthAccounts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: type: string paramStructure: by-position @@ -87,11 +85,9 @@ methods: params: [] result: name: eth_accounts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: type: string paramStructure: by-position @@ -1686,9 +1682,7 @@ components: type: object properties: accessList: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthHash" blockHash: @@ -1747,6 +1741,7 @@ components: - type - input - gas + - accessList - v - r - s From e4615f4ddc4900924f7da6574d92dadfd7dacdc3 Mon Sep 17 00:00:00 2001 From: Shashank Date: Mon, 22 Jun 2026 11:36:42 +0530 Subject: [PATCH 2/4] fix other methods --- src/rpc/methods/eth.rs | 37 +++++----- .../forest__rpc__tests__rpc__v0.snap | 72 +++++++------------ .../forest__rpc__tests__rpc__v1.snap | 72 +++++++------------ .../forest__rpc__tests__rpc__v2.snap | 72 +++++++------------ 4 files changed, 91 insertions(+), 162 deletions(-) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index 46347eafdbd6..864076fd88ff 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -1602,7 +1602,7 @@ impl RpcMethod<1> for EthGetBlockReceipts { ); type Params = (BlockNumberOrHash,); - type Ok = Vec; + type Ok = NotNullVec; async fn handle( ctx: Ctx, @@ -1615,6 +1615,7 @@ impl RpcMethod<1> for EthGetBlockReceipts { .await?; get_block_receipts(&ctx, ts, None) .await + .map(NotNullVec) .map_err(ServerError::from) } } @@ -1631,7 +1632,7 @@ impl RpcMethod<2> for EthGetBlockReceiptsLimited { ); type Params = (BlockNumberOrHash, ChainEpoch); - type Ok = Vec; + type Ok = NotNullVec; async fn handle( ctx: Ctx, @@ -1644,6 +1645,7 @@ impl RpcMethod<2> for EthGetBlockReceiptsLimited { .await?; get_block_receipts(&ctx, ts, Some(limit)) .await + .map(NotNullVec) .map_err(ServerError::from) } } @@ -3573,7 +3575,7 @@ impl RpcMethod<1> for EthTraceBlock { const DESCRIPTION: Option<&'static str> = Some("Returns traces created at given block."); type Params = (BlockNumberOrHash,); - type Ok = Vec; + type Ok = NotNullVec; async fn handle( ctx: Ctx, (block_param,): Self::Params, @@ -3583,7 +3585,9 @@ impl RpcMethod<1> for EthTraceBlock { let ts = resolver .tipset_by_block_number_or_hash(block_param, ResolveNullTipset::TakeOlder) .await?; - eth_trace_block(&ctx.state_manager, &ts).await + eth_trace_block(&ctx.state_manager, &ts) + .await + .map(NotNullVec) } } @@ -3972,7 +3976,7 @@ impl RpcMethod<1> for EthTraceTransaction { Some("Returns the traces for a specific transaction."); type Params = (String,); - type Ok = Vec; + type Ok = NotNullVec; async fn handle( ctx: Ctx, (tx_hash,): Self::Params, @@ -3993,7 +3997,7 @@ impl RpcMethod<1> for EthTraceTransaction { .into_iter() .filter(|trace| trace.transaction_hash == eth_hash) .collect(); - Ok(traces) + Ok(NotNullVec(traces)) } } @@ -4010,7 +4014,7 @@ impl RpcMethod<2> for EthTraceReplayBlockTransactions { ); type Params = (BlockNumberOrHash, Vec); - type Ok = Vec; + type Ok = NotNullVec; async fn handle( ctx: Ctx, @@ -4029,7 +4033,9 @@ impl RpcMethod<2> for EthTraceReplayBlockTransactions { .tipset_by_block_number_or_hash(block_param, ResolveNullTipset::TakeOlder) .await?; - eth_trace_replay_block_transactions(&ctx, &ts).await + eth_trace_replay_block_transactions(&ctx, &ts) + .await + .map(NotNullVec) } } @@ -4082,7 +4088,7 @@ impl RpcMethod<1> for EthTraceFilter { const DESCRIPTION: Option<&'static str> = Some("Returns the traces for transactions matching the filter criteria."); type Params = (EthTraceFilterCriteria,); - type Ok = Vec; + type Ok = NotNullVec; async fn handle( ctx: Ctx, @@ -4116,7 +4122,9 @@ impl RpcMethod<1> for EthTraceFilter { return Err(EthErrors::limit_exceeded(max_block_range, range).into()); } } - Ok(trace_filter(ctx, filter, from_block, to_block, ext).await?) + Ok(NotNullVec( + trace_filter(ctx, filter, from_block, to_block, ext).await?, + )) } } @@ -4148,7 +4156,7 @@ async fn trace_filter( ext, ) .await?; - for block_trace in block_traces { + for block_trace in block_traces.0 { if block_trace .trace .match_filter_criteria(filter.from_address.as_ref(), filter.to_address.as_ref())? @@ -4221,13 +4229,6 @@ mod test { assert_eq!(json["accessList"].as_array().unwrap().len(), 1); } - #[test] - fn empty_eth_accounts_serializes_as_empty_array() { - let accounts: NotNullVec = NotNullVec(vec![]); - let json = serde_json::to_value(accounts.into_lotus_json()).unwrap(); - assert_eq!(json, serde_json::json!([])); - } - #[quickcheck] fn gas_price_result_serde_roundtrip(i: u128) { let r = EthBigInt(ethereum_types::U256::from(i)); diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap index 129bb4729d0d..d3bd5e2ac6f3 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap @@ -844,11 +844,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: Filecoin.EthGetBlockReceipts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -861,11 +859,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: eth_getBlockReceipts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -883,11 +879,9 @@ methods: format: int64 result: name: Filecoin.EthGetBlockReceiptsLimited.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -905,11 +899,9 @@ methods: format: int64 result: name: eth_getBlockReceiptsLimited.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -1616,11 +1608,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: Filecoin.EthTraceBlock.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1633,11 +1623,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: trace_block.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1650,11 +1638,9 @@ methods: $ref: "#/components/schemas/EthTraceFilterCriteria" result: name: Filecoin.EthTraceFilter.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1667,11 +1653,9 @@ methods: $ref: "#/components/schemas/EthTraceFilterCriteria" result: name: trace_filter.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1684,11 +1668,9 @@ methods: type: string result: name: Filecoin.EthTraceTransaction.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1701,11 +1683,9 @@ methods: type: string result: name: trace_transaction.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1726,11 +1706,9 @@ methods: type: string result: name: Filecoin.EthTraceReplayBlockTransactions.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthReplayBlockTransactionTrace" paramStructure: by-position @@ -1751,11 +1729,9 @@ methods: type: string result: name: trace_replayBlockTransactions.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthReplayBlockTransactionTrace" paramStructure: by-position diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap index 5a019a2b68e2..a7a23e7ad689 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap @@ -840,11 +840,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: Filecoin.EthGetBlockReceipts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -857,11 +855,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: eth_getBlockReceipts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -879,11 +875,9 @@ methods: format: int64 result: name: Filecoin.EthGetBlockReceiptsLimited.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -901,11 +895,9 @@ methods: format: int64 result: name: eth_getBlockReceiptsLimited.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -1612,11 +1604,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: Filecoin.EthTraceBlock.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1629,11 +1619,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: trace_block.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1692,11 +1680,9 @@ methods: $ref: "#/components/schemas/EthTraceFilterCriteria" result: name: Filecoin.EthTraceFilter.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1709,11 +1695,9 @@ methods: $ref: "#/components/schemas/EthTraceFilterCriteria" result: name: trace_filter.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1726,11 +1710,9 @@ methods: type: string result: name: Filecoin.EthTraceTransaction.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1743,11 +1725,9 @@ methods: type: string result: name: trace_transaction.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1806,11 +1786,9 @@ methods: type: string result: name: Filecoin.EthTraceReplayBlockTransactions.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthReplayBlockTransactionTrace" paramStructure: by-position @@ -1831,11 +1809,9 @@ methods: type: string result: name: trace_replayBlockTransactions.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthReplayBlockTransactionTrace" paramStructure: by-position diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap index 3a248fba219e..dc9b8e5d1ac8 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap @@ -444,11 +444,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: Filecoin.EthGetBlockReceipts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -461,11 +459,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: eth_getBlockReceipts.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -483,11 +479,9 @@ methods: format: int64 result: name: Filecoin.EthGetBlockReceiptsLimited.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -505,11 +499,9 @@ methods: format: int64 result: name: eth_getBlockReceiptsLimited.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthTxReceipt" paramStructure: by-position @@ -1216,11 +1208,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: Filecoin.EthTraceBlock.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1233,11 +1223,9 @@ methods: $ref: "#/components/schemas/BlockNumberOrHash" result: name: trace_block.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1296,11 +1284,9 @@ methods: $ref: "#/components/schemas/EthTraceFilterCriteria" result: name: Filecoin.EthTraceFilter.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1313,11 +1299,9 @@ methods: $ref: "#/components/schemas/EthTraceFilterCriteria" result: name: trace_filter.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1330,11 +1314,9 @@ methods: type: string result: name: Filecoin.EthTraceTransaction.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1347,11 +1329,9 @@ methods: type: string result: name: trace_transaction.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthBlockTrace" paramStructure: by-position @@ -1410,11 +1390,9 @@ methods: type: string result: name: Filecoin.EthTraceReplayBlockTransactions.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthReplayBlockTransactionTrace" paramStructure: by-position @@ -1435,11 +1413,9 @@ methods: type: string result: name: trace_replayBlockTransactions.Result - required: false + required: true schema: - type: - - array - - "null" + type: array items: $ref: "#/components/schemas/EthReplayBlockTransactionTrace" paramStructure: by-position From e9d6f48fefba174098a3db964c6d123339d8666b Mon Sep 17 00:00:00 2001 From: Shashank Date: Mon, 22 Jun 2026 11:44:54 +0530 Subject: [PATCH 3/4] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89a0b17906d8..0176e9e1ec7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ - [#6975](https://github.com/ChainSafe/forest/issues/6975): Fixed `Filecoin.MpoolSelect` to not remove the messages from the live pool, only simulate the head change. +- [#7205](https://github.com/ChainSafe/forest/issues/7205): Fixed eth methods serializing empty lists as `null` instead of `[]`. + ## Forest v0.33.6 "Ebb" Non-mandatory release for all node operators. It fixes a critical memory leak in `v0.33.5`. (Earlier releases are not affected) From 57a72628b872c9387562dc6fd7188f63999a7f9b Mon Sep 17 00:00:00 2001 From: Shashank Date: Mon, 22 Jun 2026 13:15:22 +0530 Subject: [PATCH 4/4] make access list option --- src/rpc/methods/eth.rs | 14 ++++++++------ src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap | 5 +++-- src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap | 5 +++-- src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap | 5 +++-- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index 864076fd88ff..50fb92ee3467 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -642,9 +642,9 @@ pub struct ApiEthTx { pub max_priority_fee_per_gas: Option, #[serde(skip_serializing_if = "Option::is_none", default)] pub gas_price: Option, - #[schemars(with = "Vec")] + #[schemars(with = "Option>")] #[serde(with = "crate::lotus_json")] - pub access_list: NotNullVec, + pub access_list: Option>, pub v: EthBigInt, pub r: EthBigInt, pub s: EthBigInt, @@ -1263,7 +1263,7 @@ fn eth_tx_from_native_message( gas: EthUint64(msg.gas_limit), max_fee_per_gas: Some(msg.gas_fee_cap.clone().into()), max_priority_fee_per_gas: Some(msg.gas_premium.clone().into()), - access_list: NotNullVec(vec![]), + access_list: Some(NotNullVec(vec![])), ..ApiEthTx::default() }) } @@ -4212,8 +4212,10 @@ mod test { #[test] fn empty_access_list_serializes_as_empty_array() { - let tx = ApiEthTx::default(); - assert!(tx.access_list.0.is_empty()); + let tx = ApiEthTx { + access_list: Some(NotNullVec(vec![])), + ..Default::default() + }; let json = serde_json::to_value(tx.into_lotus_json()).unwrap(); assert_eq!(json["accessList"], serde_json::json!([])); } @@ -4221,7 +4223,7 @@ mod test { #[test] fn populated_access_list_serializes_as_array() { let tx = ApiEthTx { - access_list: NotNullVec(vec![EthHash::default()]), + access_list: Some(NotNullVec(vec![EthHash::default()])), ..Default::default() }; let json = serde_json::to_value(tx.into_lotus_json()).unwrap(); diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap index d3bd5e2ac6f3..33de3da4fbee 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap @@ -4731,7 +4731,9 @@ components: type: object properties: accessList: - type: array + type: + - array + - "null" items: $ref: "#/components/schemas/EthHash" blockHash: @@ -4790,7 +4792,6 @@ components: - type - input - gas - - accessList - v - r - s diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap index a7a23e7ad689..a2312c629b44 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap @@ -4801,7 +4801,9 @@ components: type: object properties: accessList: - type: array + type: + - array + - "null" items: $ref: "#/components/schemas/EthHash" blockHash: @@ -4860,7 +4862,6 @@ components: - type - input - gas - - accessList - v - r - s diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap index dc9b8e5d1ac8..b1b96964be81 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap @@ -1658,7 +1658,9 @@ components: type: object properties: accessList: - type: array + type: + - array + - "null" items: $ref: "#/components/schemas/EthHash" blockHash: @@ -1717,7 +1719,6 @@ components: - type - input - gas - - accessList - v - r - s