|
8 | 8 | using Nethermind.Blockchain.Find;
|
9 | 9 | using Nethermind.Config;
|
10 | 10 | using Nethermind.Core;
|
| 11 | +using Nethermind.Core.Collections; |
11 | 12 | using Nethermind.Evm;
|
12 | 13 | using Nethermind.Facade;
|
13 | 14 | using Nethermind.Facade.Eth.RpcTransaction;
|
@@ -124,87 +125,63 @@ public override ResultWrapper<IReadOnlyList<SimulateBlockResult>> Execute(
|
124 | 125 |
|
125 | 126 | if (call.BlockStateCalls is not null)
|
126 | 127 | {
|
127 |
| - long lastBlockNumber = -1; |
128 |
| - ulong lastBlockTime = 0; |
| 128 | + long lastBlockNumber = header.Number; |
| 129 | + ulong lastBlockTime = header.Timestamp; |
| 130 | + |
| 131 | + using ArrayPoolList<BlockStateCall<TransactionForRpc>> completeBlockStateCalls = new(call.BlockStateCalls.Count); |
129 | 132 |
|
130 | 133 | foreach (BlockStateCall<TransactionForRpc>? blockToSimulate in call.BlockStateCalls)
|
131 | 134 | {
|
132 |
| - ulong givenNumber = blockToSimulate.BlockOverrides?.Number ?? |
133 |
| - (lastBlockNumber == -1 ? (ulong)header.Number + 1 : (ulong)lastBlockNumber + 1); |
| 135 | + blockToSimulate.BlockOverrides ??= new BlockOverride(); |
| 136 | + ulong givenNumber = blockToSimulate.BlockOverrides.Number ?? (ulong)lastBlockNumber + 1; |
134 | 137 |
|
135 | 138 | if (givenNumber > long.MaxValue)
|
136 | 139 | return ResultWrapper<IReadOnlyList<SimulateBlockResult>>.Fail(
|
137 | 140 | $"Block number too big {givenNumber}!", ErrorCodes.InvalidParams);
|
138 | 141 |
|
139 |
| - if (givenNumber < (ulong)header.Number) |
| 142 | + if (givenNumber <= (ulong)lastBlockNumber) |
140 | 143 | return ResultWrapper<IReadOnlyList<SimulateBlockResult>>.Fail(
|
141 |
| - $"Block number out of order {givenNumber} is < than given base number of {header.Number}!", ErrorCodes.InvalidInputBlocksOutOfOrder); |
| 144 | + $"Block number out of order {givenNumber} is <= than previous block number of {header.Number}!", ErrorCodes.InvalidInputBlocksOutOfOrder); |
142 | 145 |
|
143 |
| - long given = (long)givenNumber; |
144 |
| - if (given > lastBlockNumber) |
145 |
| - { |
146 |
| - lastBlockNumber = given; |
147 |
| - } |
148 |
| - else |
149 |
| - { |
| 146 | + // if the no. of filler blocks are greater than maximum simulate blocks cap |
| 147 | + if (givenNumber - (ulong)lastBlockNumber > (ulong)_blocksLimit) |
150 | 148 | return ResultWrapper<IReadOnlyList<SimulateBlockResult>>.Fail(
|
151 |
| - $"Block number out of order {givenNumber}!", ErrorCodes.InvalidInputBlocksOutOfOrder); |
| 149 | + $"too many blocks", |
| 150 | + ErrorCodes.ClientLimitExceededError); |
| 151 | + |
| 152 | + for (ulong fillBlockNumber = (ulong)lastBlockNumber + 1; fillBlockNumber < givenNumber; fillBlockNumber++) |
| 153 | + { |
| 154 | + ulong fillBlockTime = lastBlockTime + secondsPerSlot ?? new BlocksConfig().SecondsPerSlot; |
| 155 | + completeBlockStateCalls.Add(new BlockStateCall<TransactionForRpc> |
| 156 | + { |
| 157 | + BlockOverrides = new BlockOverride { Number = fillBlockNumber, Time = fillBlockTime }, |
| 158 | + StateOverrides = null, |
| 159 | + Calls = [] |
| 160 | + }); |
| 161 | + lastBlockTime = fillBlockTime; |
152 | 162 | }
|
153 | 163 |
|
154 |
| - blockToSimulate.BlockOverrides ??= new BlockOverride(); |
155 | 164 | blockToSimulate.BlockOverrides.Number = givenNumber;
|
156 | 165 |
|
157 |
| - ulong givenTime = blockToSimulate.BlockOverrides.Time ?? |
158 |
| - (lastBlockTime == 0 |
159 |
| - ? header.Timestamp + secondsPerSlot.Value |
160 |
| - : lastBlockTime + secondsPerSlot.Value); |
161 |
| - |
162 |
| - if (givenTime < header.Timestamp) |
163 |
| - return ResultWrapper<IReadOnlyList<SimulateBlockResult>>.Fail( |
164 |
| - $"Block timestamp out of order {givenTime} is < than given base timestamp of {header.Timestamp}!", ErrorCodes.BlockTimestampNotIncreased); |
165 |
| - |
166 |
| - if (givenTime > lastBlockTime) |
| 166 | + if (blockToSimulate.BlockOverrides.Time is not null) |
167 | 167 | {
|
168 |
| - lastBlockTime = givenTime; |
| 168 | + if (blockToSimulate.BlockOverrides.Time <= lastBlockTime) |
| 169 | + { |
| 170 | + return ResultWrapper<IReadOnlyList<SimulateBlockResult>>.Fail( |
| 171 | + $"Block timestamp out of order {blockToSimulate.BlockOverrides.Time} is <= than given base timestamp of {lastBlockTime}!", ErrorCodes.BlockTimestampNotIncreased); |
| 172 | + } |
| 173 | + lastBlockTime = (ulong)blockToSimulate.BlockOverrides.Time; |
169 | 174 | }
|
170 | 175 | else
|
171 | 176 | {
|
172 |
| - return ResultWrapper<IReadOnlyList<SimulateBlockResult>>.Fail( |
173 |
| - $"Block timestamp out of order {givenTime}!", ErrorCodes.BlockTimestampNotIncreased); |
| 177 | + blockToSimulate.BlockOverrides.Time = lastBlockTime + secondsPerSlot; |
| 178 | + lastBlockTime = (ulong)blockToSimulate.BlockOverrides.Time; |
174 | 179 | }
|
| 180 | + lastBlockNumber = (long)givenNumber; |
175 | 181 |
|
176 |
| - blockToSimulate.BlockOverrides.Time = givenTime; |
| 182 | + completeBlockStateCalls.Add(blockToSimulate); |
177 | 183 | }
|
178 |
| - |
179 |
| - long minBlockNumber = Math.Min( |
180 |
| - call.BlockStateCalls.Min(b => (long)(b.BlockOverrides?.Number ?? ulong.MaxValue)), |
181 |
| - header.Number + 1); |
182 |
| - |
183 |
| - long maxBlockNumber = Math.Max( |
184 |
| - call.BlockStateCalls.Max(b => (long)(b.BlockOverrides?.Number ?? ulong.MinValue)), |
185 |
| - minBlockNumber); |
186 |
| - |
187 |
| - HashSet<long> existingBlockNumbers = |
188 |
| - [ |
189 |
| - .. call.BlockStateCalls.Select(b => (long)(b.BlockOverrides?.Number ?? ulong.MinValue)) |
190 |
| - ]; |
191 |
| - |
192 |
| - List<BlockStateCall<TransactionForRpc>> completeBlockStateCalls = call.BlockStateCalls; |
193 |
| - |
194 |
| - for (long blockNumber = minBlockNumber; blockNumber <= maxBlockNumber; blockNumber++) |
195 |
| - { |
196 |
| - if (!existingBlockNumbers.Contains(blockNumber)) |
197 |
| - { |
198 |
| - completeBlockStateCalls.Add(new BlockStateCall<TransactionForRpc> |
199 |
| - { |
200 |
| - BlockOverrides = new BlockOverride { Number = (ulong)blockNumber }, |
201 |
| - StateOverrides = null, |
202 |
| - Calls = [] |
203 |
| - }); |
204 |
| - } |
205 |
| - } |
206 |
| - |
207 |
| - call.BlockStateCalls.Sort((b1, b2) => b1.BlockOverrides!.Number!.Value.CompareTo(b2.BlockOverrides!.Number!.Value)); |
| 184 | + call.BlockStateCalls = [.. completeBlockStateCalls]; |
208 | 185 | }
|
209 | 186 |
|
210 | 187 | using CancellationTokenSource timeout = _rpcConfig.BuildTimeoutCancellationToken();
|
|
0 commit comments