-
Notifications
You must be signed in to change notification settings - Fork 434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP]Make chainspec extendable by plugins #7540
base: master
Are you sure you want to change the base?
Changes from 4 commits
2ada5d8
d9d4f2a
d61acc3
6ea1a10
33f8a6c
f7b8e32
32cbfa4
70d2227
da4313b
3c39505
c44f8e8
7f8ae03
be56036
b6f1a53
bed5240
4b5d291
777c49a
4261b1e
2946160
6d0ece3
ddbcc2d
15cb899
a9dd55e
c3d296f
67d89e1
7705a5c
0a7f661
dde5690
18ce8a2
931b4ac
8e9ab40
300dd01
d488037
5c40e24
24c91c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,13 +8,21 @@ | |
using Nethermind.Int256; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using Nethermind.Core; | ||
using Nethermind.Core.Crypto; | ||
|
||
namespace Nethermind.Config | ||
{ | ||
internal static class ConfigSourceHelper | ||
public static class ConfigSourceHelper | ||
{ | ||
public static object ParseValue(Type valueType, string valueString, string category, string name) | ||
{ | ||
if (Nullable.GetUnderlyingType(valueType) is { } nullableType) | ||
{ | ||
return !string.IsNullOrEmpty(valueString) && !valueString.Equals("null", StringComparison.InvariantCultureIgnoreCase) | ||
? ParseValue(nullableType, valueString, category, name) | ||
: null; | ||
} | ||
try | ||
{ | ||
object value; | ||
|
@@ -23,8 +31,17 @@ public static object ParseValue(Type valueType, string valueString, string categ | |
//supports Arrays, e.g int[] and generic IEnumerable<T>, IList<T> | ||
var itemType = valueType.IsGenericType ? valueType.GetGenericArguments()[0] : valueType.GetElementType(); | ||
|
||
if (itemType == typeof(byte) && !valueString.AsSpan().TrimStart().StartsWith("[")) | ||
{ | ||
// hex encoded byte array | ||
string hex = valueString.Trim().RemoveStart('0').RemoveStart('x').TrimEnd(); | ||
value = Enumerable.Range(0, hex.Length) | ||
.Where(x => x % 2 == 0) | ||
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) | ||
.ToArray(); | ||
} | ||
//In case of collection of objects (more complex config models) we parse entire collection | ||
if (itemType.IsClass && typeof(IConfigModel).IsAssignableFrom(itemType)) | ||
else if (itemType.IsClass && typeof(IConfigModel).IsAssignableFrom(itemType)) | ||
{ | ||
var objCollection = JsonSerializer.Deserialize(valueString, valueType); | ||
value = objCollection; | ||
|
@@ -86,13 +103,76 @@ public static object GetDefault(Type type) | |
return type.IsValueType ? (false, Activator.CreateInstance(type)) : (false, null); | ||
} | ||
|
||
public static bool TryFromHex(Type type, string itemValue, out object value) | ||
{ | ||
if (!itemValue.StartsWith("0x")) | ||
{ | ||
value = null; | ||
return false; | ||
} | ||
switch (Type.GetTypeCode(type)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Convert.ChangeType? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dont understand what you mean |
||
{ | ||
case TypeCode.Byte: | ||
value = Convert.ToByte(itemValue, 16); | ||
return true; | ||
case TypeCode.SByte: | ||
value = Convert.ToSByte(itemValue, 16); | ||
return true; | ||
case TypeCode.UInt16: | ||
value = Convert.ToUInt16(itemValue, 16); | ||
return true; | ||
case TypeCode.UInt32: | ||
value = Convert.ToUInt32(itemValue, 16); | ||
return true; | ||
case TypeCode.UInt64: | ||
value = Convert.ToUInt64(itemValue, 16); | ||
return true; | ||
case TypeCode.Int16: | ||
value = Convert.ToInt16(itemValue, 16); | ||
return true; | ||
case TypeCode.Int32: | ||
value = Convert.ToInt32(itemValue, 16); | ||
return true; | ||
case TypeCode.Int64: | ||
value = Convert.ToInt64(itemValue, 16); | ||
return true; | ||
default: | ||
value = null; | ||
return false; | ||
} | ||
} | ||
|
||
private static object GetValue(Type valueType, string itemValue) | ||
{ | ||
if (Nullable.GetUnderlyingType(valueType) is var nullableType && nullableType is not null) | ||
{ | ||
if (string.IsNullOrEmpty(itemValue) || itemValue.Equals("null", StringComparison.InvariantCultureIgnoreCase)) | ||
{ | ||
return null; | ||
} | ||
|
||
return GetValue(nullableType, itemValue); | ||
} | ||
deffrian marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (valueType == typeof(UInt256)) | ||
{ | ||
return UInt256.Parse(itemValue); | ||
} | ||
|
||
if (valueType == typeof(Address)) | ||
{ | ||
if (Address.TryParse(itemValue, out var address)) | ||
{ | ||
return address; | ||
} | ||
throw new FormatException($"Could not parse {itemValue} to {typeof(Address)}"); | ||
} | ||
|
||
if (valueType == typeof(Hash256)) | ||
{ | ||
return new Hash256(itemValue); | ||
} | ||
|
||
if (valueType.IsEnum) | ||
{ | ||
if (Enum.TryParse(valueType, itemValue, true, out var enumValue)) | ||
|
@@ -103,13 +183,12 @@ private static object GetValue(Type valueType, string itemValue) | |
throw new FormatException($"Cannot parse enum value: {itemValue}, type: {valueType.Name}"); | ||
} | ||
|
||
var nullableType = Nullable.GetUnderlyingType(valueType); | ||
if (TryFromHex(valueType, itemValue, out object value)) | ||
{ | ||
return value; | ||
} | ||
|
||
return nullableType is null | ||
? Convert.ChangeType(itemValue, valueType) | ||
: !string.IsNullOrEmpty(itemValue) && !itemValue.Equals("null", StringComparison.InvariantCultureIgnoreCase) | ||
? Convert.ChangeType(itemValue, nullableType) | ||
: null; | ||
return Convert.ChangeType(itemValue, valueType); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,16 +6,16 @@ | |
|
||
namespace Nethermind.Optimism; | ||
|
||
public class OptimismSpecHelper(OptimismParameters parameters) : IOptimismSpecHelper | ||
public class OptimismSpecHelper(OptimismChainSpecEngineParameters parameters) : IOptimismSpecHelper | ||
{ | ||
private readonly long _bedrockBlockNumber = parameters.BedrockBlockNumber; | ||
private readonly ulong _regolithTimestamp = parameters.RegolithTimestamp; | ||
private readonly long? _bedrockBlockNumber = parameters.BedrockBlockNumber; | ||
private readonly ulong? _regolithTimestamp = parameters.RegolithTimestamp; | ||
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we have to make stuff nullable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There might be no value in config, so better to make it nullable imo There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @deffrian shouldn't we always have a value for these hardforks? |
||
private readonly ulong? _canyonTimestamp = parameters.CanyonTimestamp; | ||
private readonly ulong? _ecotoneTimestamp = parameters.EcotoneTimestamp; | ||
private readonly ulong? _fjordTimestamp = parameters.FjordTimestamp; | ||
private readonly ulong? _graniteTimestamp = parameters.GraniteTimestamp; | ||
|
||
public Address L1FeeReceiver { get; init; } = parameters.L1FeeRecipient; | ||
public Address? L1FeeReceiver { get; init; } = parameters.L1FeeRecipient; | ||
|
||
public bool IsRegolith(BlockHeader header) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using Nethermind.Core; | ||
using Nethermind.Int256; | ||
using Nethermind.Specs; | ||
using Nethermind.Specs.ChainSpecStyle; | ||
|
||
namespace Nethermind.Optimism; | ||
|
||
public class OptimismChainSpecEngineParameters : IChainSpecEngineParameters | ||
{ | ||
public string? SealEngineType => "Optimism"; | ||
|
||
public ulong? RegolithTimestamp { get; set; } | ||
|
||
public long? BedrockBlockNumber { get; set; } | ||
|
||
public ulong? CanyonTimestamp { get; set; } | ||
|
||
public ulong? EcotoneTimestamp { get; set; } | ||
|
||
public ulong? FjordTimestamp { get; set; } | ||
|
||
public ulong? GraniteTimestamp { get; set; } | ||
|
||
public Address? L1FeeRecipient { get; set; } | ||
|
||
public Address? L1BlockAddress { get; set; } | ||
|
||
public UInt256? CanyonBaseFeeChangeDenominator { get; set; } | ||
|
||
public Address? Create2DeployerAddress { get; set; } | ||
|
||
public byte[]? Create2DeployerCode { get; set; } | ||
|
||
public void AddTransitions(SortedSet<long> blockNumbers, SortedSet<ulong> timestamps) | ||
{ | ||
ArgumentNullException.ThrowIfNull(RegolithTimestamp); | ||
ArgumentNullException.ThrowIfNull(BedrockBlockNumber); | ||
ArgumentNullException.ThrowIfNull(CanyonTimestamp); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some of these fields (like |
||
ArgumentNullException.ThrowIfNull(EcotoneTimestamp); | ||
ArgumentNullException.ThrowIfNull(FjordTimestamp); | ||
ArgumentNullException.ThrowIfNull(GraniteTimestamp); | ||
ArgumentNullException.ThrowIfNull(L1FeeRecipient); | ||
ArgumentNullException.ThrowIfNull(L1BlockAddress); | ||
ArgumentNullException.ThrowIfNull(CanyonBaseFeeChangeDenominator); | ||
ArgumentNullException.ThrowIfNull(Create2DeployerAddress); | ||
ArgumentNullException.ThrowIfNull(Create2DeployerCode); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it have some sort of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forgot to remove. Was for debug purposes |
||
} | ||
|
||
public void AdjustReleaseSpec(ReleaseSpec spec, long startBlock, ulong? startTimestamp) | ||
{ | ||
if (CanyonTimestamp <= startTimestamp) | ||
{ | ||
// TODO: check | ||
spec.BaseFeeMaxChangeDenominator = CanyonBaseFeeChangeDenominator!.Value; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bytes.FromHexString
AsSpan().Trim() if needed