From 78046615a085a7e1213efeaa70322e3e4eb44bfa Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Thu, 22 Jun 2023 15:50:38 +0100 Subject: [PATCH] Prefer code from code cache for Create (#5854) * Prefer code from code cache for Create * Filter code inserts * Add Note --- .../Nethermind.Evm/VirtualMachine.cs | 12 ++++++- .../Nethermind.State/StateProvider.cs | 33 +++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 3342381621c..cb07fdbfa0b 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -2444,6 +2444,16 @@ private bool InstructionSelfDestruct(EvmState vmState, ref EvmStack(EvmState vmState, ref EvmStack> _intraBlockCache = new(); private readonly ResettableHashSet
_committedThisRound = new(); + // Only guarding against hot duplicates so filter doesn't need to be too big + // Note: + // False negatives are fine as they will just result in a overwrite set + // False positives would be problematic as the code _must_ be persisted + private readonly LruKeyCache _codeInsertFilter = new(2048, "Code Insert Filter"); private readonly List _keptInCache = new(); private readonly ILogger _logger; @@ -141,7 +148,29 @@ public void InsertCode(Address address, ReadOnlyMemory code, IReleaseSpec { _needsStateRootUpdate = true; Keccak codeHash = code.Length == 0 ? Keccak.OfAnEmptyString : Keccak.Compute(code.Span); - _codeDb[codeHash.Bytes] = code.ToArray(); + + // Don't reinsert if already inserted. This can be the case when the same + // code is used by multiple deployments. Either from factory contracts (e.g. LPs) + // or people copy and pasting popular contracts + if (!_codeInsertFilter.Get(codeHash)) + { + if (_codeDb is IDbWithSpan dbWithSpan) + { + dbWithSpan.PutSpan(codeHash.Bytes, code.Span); + } + else if (MemoryMarshal.TryGetArray(code, out ArraySegment codeArray) + && codeArray.Offset == 0 + && codeArray.Count == code.Length) + { + _codeDb[codeHash.Bytes] = codeArray.Array; + } + else + { + _codeDb[codeHash.Bytes] = code.ToArray(); + } + + _codeInsertFilter.Set(codeHash); + } Account? account = GetThroughCache(address); if (account is null)