-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Add hardfork HF_Echidna #3454
base: master
Are you sure you want to change the base?
Add hardfork HF_Echidna #3454
Changes from all commits
bcc5fd0
e63f10b
9d16c53
f746f8d
8d7f9e8
3fc8077
620d938
7e31d0c
993e3fe
37bf0cb
7dba130
0457ccd
d7a291e
6e780c0
02d6ab9
8fb30df
f9244eb
650c9e9
331541a
eb96d14
74498e5
577c431
1c82ed9
b81b127
a3a6fd5
c086661
0f1507f
f91b680
705f4bb
498ed91
08c3be6
59fe8b5
a784c41
e2acc64
216c39e
548bd05
8470de5
93fc37b
b1a3ea3
f4f1980
7fb5f7a
ec78580
32410be
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 |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright (C) 2015-2024 The Neo Project. | ||
// | ||
// Ed25519.cs file belongs to the neo project and is free | ||
// software distributed under the MIT software license, see the | ||
// accompanying file LICENSE in the main directory of the | ||
// repository or http://www.opensource.org/licenses/mit-license.php | ||
// for more details. | ||
// | ||
// Redistribution and use in source and binary forms with or without | ||
// modifications are permitted. | ||
|
||
using Org.BouncyCastle.Crypto.Generators; | ||
using Org.BouncyCastle.Crypto.Parameters; | ||
using Org.BouncyCastle.Crypto.Signers; | ||
using Org.BouncyCastle.Security; | ||
using System; | ||
|
||
namespace Neo.Cryptography | ||
{ | ||
public class Ed25519 | ||
{ | ||
internal const int PublicKeySize = 32; | ||
private const int PrivateKeySize = 32; | ||
internal const int SignatureSize = 64; | ||
|
||
/// <summary> | ||
/// Generates a new Ed25519 key pair. | ||
/// </summary> | ||
/// <returns>A byte array containing the private key.</returns> | ||
public static byte[] GenerateKeyPair() | ||
{ | ||
var keyPairGenerator = new Ed25519KeyPairGenerator(); | ||
keyPairGenerator.Init(new Ed25519KeyGenerationParameters(new SecureRandom())); | ||
var keyPair = keyPairGenerator.GenerateKeyPair(); | ||
return ((Ed25519PrivateKeyParameters)keyPair.Private).GetEncoded(); | ||
} | ||
|
||
/// <summary> | ||
/// Derives the public key from a given private key. | ||
/// </summary> | ||
/// <param name="privateKey">The private key as a byte array.</param> | ||
/// <returns>The corresponding public key as a byte array.</returns> | ||
/// <exception cref="ArgumentException">Thrown when the private key size is invalid.</exception> | ||
public static byte[] GetPublicKey(byte[] privateKey) | ||
{ | ||
if (privateKey.Length != PrivateKeySize) | ||
throw new ArgumentException("Invalid private key size", nameof(privateKey)); | ||
|
||
var privateKeyParams = new Ed25519PrivateKeyParameters(privateKey, 0); | ||
return privateKeyParams.GeneratePublicKey().GetEncoded(); | ||
} | ||
|
||
/// <summary> | ||
/// Signs a message using the provided private key. | ||
/// Parameters are in the same order as the sample in the Ed25519 specification | ||
/// Ed25519.sign(privkey, pubkey, msg) with pubkey omitted | ||
/// ref. https://datatracker.ietf.org/doc/html/rfc8032. | ||
/// </summary> | ||
/// <param name="privateKey">The private key used for signing.</param> | ||
/// <param name="message">The message to be signed.</param> | ||
/// <returns>The signature as a byte array.</returns> | ||
/// <exception cref="ArgumentException">Thrown when the private key size is invalid.</exception> | ||
public static byte[] Sign(byte[] privateKey, byte[] message) | ||
{ | ||
if (privateKey.Length != PrivateKeySize) | ||
throw new ArgumentException("Invalid private key size", nameof(privateKey)); | ||
|
||
var signer = new Ed25519Signer(); | ||
signer.Init(true, new Ed25519PrivateKeyParameters(privateKey, 0)); | ||
signer.BlockUpdate(message, 0, message.Length); | ||
return signer.GenerateSignature(); | ||
} | ||
|
||
/// <summary> | ||
/// Verifies an Ed25519 signature for a given message using the provided public key. | ||
/// Parameters are in the same order as the sample in the Ed25519 specification | ||
/// Ed25519.verify(public, msg, signature) | ||
/// ref. https://datatracker.ietf.org/doc/html/rfc8032. | ||
/// </summary> | ||
/// <param name="publicKey">The 32-byte public key used for verification.</param> | ||
/// <param name="message">The message that was signed.</param> | ||
/// <param name="signature">The 64-byte signature to verify.</param> | ||
/// <returns>True if the signature is valid for the given message and public key; otherwise, false.</returns> | ||
/// <exception cref="ArgumentException">Thrown when the signature or public key size is invalid.</exception> | ||
public static bool Verify(byte[] publicKey, byte[] message, byte[] signature) | ||
{ | ||
if (signature.Length != SignatureSize) | ||
throw new ArgumentException("Invalid signature size", nameof(signature)); | ||
|
||
if (publicKey.Length != PublicKeySize) | ||
throw new ArgumentException("Invalid public key size", nameof(publicKey)); | ||
|
||
var verifier = new Ed25519Signer(); | ||
verifier.Init(false, new Ed25519PublicKeyParameters(publicKey, 0)); | ||
verifier.BlockUpdate(message, 0, message.Length); | ||
return verifier.VerifySignature(signature); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ public enum Hardfork : byte | |
HF_Aspidochelone, | ||
HF_Basilisk, | ||
HF_Cockatrice, | ||
HF_Domovoi | ||
HF_Domovoi, | ||
HF_Echidna | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.IO; | ||
using System.Linq; | ||
|
||
namespace Neo | ||
|
@@ -123,19 +124,70 @@ public record ProtocolSettings | |
|
||
public static ProtocolSettings Custom { get; set; } | ||
|
||
/// <summary> | ||
/// Searches for a file in the given path. If not found, checks in the executable directory. | ||
/// </summary> | ||
/// <param name="fileName">The name of the file to search for.</param> | ||
/// <param name="path">The primary path to search in.</param> | ||
/// <returns>Full path of the file if found, null otherwise.</returns> | ||
public static string FindFile(string fileName, string path) | ||
{ | ||
|
||
// Check if the given path is relative | ||
if (!Path.IsPathRooted(path)) | ||
{ | ||
// Combine with the executable directory if relative | ||
var executablePath = AppDomain.CurrentDomain.BaseDirectory; | ||
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. This can be set to whatever. Better to use 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. This is a collection branch, no direct change should be made here, please update in a pr. |
||
path = Path.Combine(executablePath, path); | ||
} | ||
|
||
// Check if file exists in the specified (resolved) path | ||
var fullPath = Path.Combine(path, fileName); | ||
if (File.Exists(fullPath)) | ||
{ | ||
return fullPath; | ||
} | ||
|
||
// Check if file exists in the executable directory | ||
var executableDir = AppContext.BaseDirectory; | ||
fullPath = Path.Combine(executableDir, fileName); | ||
if (File.Exists(fullPath)) | ||
{ | ||
return fullPath; | ||
} | ||
|
||
// File not found in either location | ||
return null; | ||
} | ||
|
||
/// <summary> | ||
/// Loads the <see cref="ProtocolSettings"/> from the specified stream. | ||
/// </summary> | ||
/// <param name="stream">The stream of the settings.</param> | ||
/// <returns>The loaded <see cref="ProtocolSettings"/>.</returns> | ||
public static ProtocolSettings Load(Stream stream) | ||
{ | ||
var config = new ConfigurationBuilder().AddJsonStream(stream).Build(); | ||
var section = config.GetSection("ProtocolConfiguration"); | ||
return Load(section); | ||
} | ||
|
||
/// <summary> | ||
/// Loads the <see cref="ProtocolSettings"/> at the specified path. | ||
/// </summary> | ||
/// <param name="path">The path of the settings file.</param> | ||
/// <param name="optional">Indicates whether the file is optional.</param> | ||
/// <returns>The loaded <see cref="ProtocolSettings"/>.</returns> | ||
public static ProtocolSettings Load(string path, bool optional = true) | ||
public static ProtocolSettings Load(string path) | ||
{ | ||
IConfigurationRoot config = new ConfigurationBuilder().AddJsonFile(path, optional).Build(); | ||
IConfigurationSection section = config.GetSection("ProtocolConfiguration"); | ||
var settings = Load(section); | ||
CheckingHardfork(settings); | ||
return settings; | ||
path = FindFile(path, Environment.CurrentDirectory); | ||
|
||
if (path is null) | ||
{ | ||
return Default; | ||
} | ||
|
||
using var stream = File.OpenRead(path); | ||
return Load(stream); | ||
} | ||
|
||
/// <summary> | ||
|
@@ -165,6 +217,7 @@ public static ProtocolSettings Load(IConfigurationSection section) | |
? EnsureOmmitedHardforks(section.GetSection("Hardforks").GetChildren().ToDictionary(p => Enum.Parse<Hardfork>(p.Key, true), p => uint.Parse(p.Value))).ToImmutableDictionary() | ||
: Default.Hardforks | ||
}; | ||
CheckingHardfork(Custom); | ||
return Custom; | ||
} | ||
|
||
|
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.
We shouldn't enable it in this PR. Remove these values; we'll set the proper ones in a separate PR before the release.