forked from NethermindEth/nethermind
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCachedCodeInfoRepository.cs
More file actions
94 lines (80 loc) · 3.71 KB
/
Copy pathCachedCodeInfoRepository.cs
File metadata and controls
94 lines (80 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
using System;
using System.Collections.Concurrent;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Core.Specs;
using Nethermind.Evm;
using Nethermind.Evm.CodeAnalysis;
using Nethermind.Evm.Precompiles;
using Nethermind.State;
namespace Nethermind.Blockchain;
public class CachedCodeInfoRepository(
IPrecompileProvider precompileProvider,
ICodeInfoRepository baseCodeInfoRepository,
ConcurrentDictionary<PreBlockCaches.PrecompileCacheKey, Result<byte[]>>? precompileCache) : ICodeInfoRepository
{
private readonly FrozenDictionary<AddressAsKey, CodeInfo> _cachedPrecompile = precompileCache is null
? precompileProvider.GetPrecompiles()
: precompileProvider.GetPrecompiles().ToFrozenDictionary(kvp => kvp.Key, kvp => CreateCachedPrecompile(kvp, precompileCache));
public CodeInfo GetCachedCodeInfo(Address codeSource, bool followDelegation, IReleaseSpec vmSpec,
out Address? delegationAddress)
{
if (vmSpec.IsPrecompile(codeSource) && _cachedPrecompile.TryGetValue(codeSource, out var cachedCodeInfo))
{
delegationAddress = null;
return cachedCodeInfo;
}
return baseCodeInfoRepository.GetCachedCodeInfo(codeSource, followDelegation, vmSpec, out delegationAddress);
}
public ValueHash256 GetExecutableCodeHash(Address address, IReleaseSpec spec)
{
return baseCodeInfoRepository.GetExecutableCodeHash(address, spec);
}
public void InsertCode(ReadOnlyMemory<byte> code, Address codeOwner, IReleaseSpec spec)
{
baseCodeInfoRepository.InsertCode(code, codeOwner, spec);
}
public void SetDelegation(Address codeSource, Address authority, IReleaseSpec spec)
{
baseCodeInfoRepository.SetDelegation(codeSource, authority, spec);
}
public bool TryGetDelegation(Address address, IReleaseSpec spec,
[NotNullWhen(true)] out Address? delegatedAddress)
{
return baseCodeInfoRepository.TryGetDelegation(address, spec, out delegatedAddress);
}
private static CodeInfo CreateCachedPrecompile(
in KeyValuePair<AddressAsKey, CodeInfo> originalPrecompile,
ConcurrentDictionary<PreBlockCaches.PrecompileCacheKey, Result<byte[]>> cache)
{
IPrecompile precompile = originalPrecompile.Value.Precompile!;
return !precompile.SupportsCaching
? originalPrecompile.Value
: new CodeInfo(new CachedPrecompile(originalPrecompile.Key.Value, precompile, cache));
}
private class CachedPrecompile(
Address address,
IPrecompile precompile,
ConcurrentDictionary<PreBlockCaches.PrecompileCacheKey, Result<byte[]>> cache) : IPrecompile
{
public long BaseGasCost(IReleaseSpec releaseSpec) => precompile.BaseGasCost(releaseSpec);
public long DataGasCost(ReadOnlyMemory<byte> inputData, IReleaseSpec releaseSpec) => precompile.DataGasCost(inputData, releaseSpec);
public Result<byte[]> Run(ReadOnlyMemory<byte> inputData, IReleaseSpec releaseSpec)
{
PreBlockCaches.PrecompileCacheKey key = new(address, inputData);
if (!cache.TryGetValue(key, out Result<byte[]> result))
{
result = precompile.Run(inputData, releaseSpec);
// we need to rebuild the key with data copy as the data can be changed by VM processing
key = new PreBlockCaches.PrecompileCacheKey(address, inputData.ToArray());
cache.TryAdd(key, result);
}
return result;
}
}
}