-
Notifications
You must be signed in to change notification settings - Fork 223
port message sign to master-n3 #924
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
Open
ajara87
wants to merge
38
commits into
neo-project:master-n3
Choose a base branch
from
ajara87:message-sign
base: master-n3
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 13 commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
cd219c6
port message sign to master-n3
ajara87 c57e6e7
reordering using due to format
ajara87 f050e7a
fix format using
ajara87 5bfdbff
add trycatch
ajara87 9520277
Use of GetSignData
ajara87 18bf56a
modify consoleservicebase
ajara87 62d9cc3
UT for OnSignMessageCommand
ajara87 995577f
format review
ajara87 87b6864
update using
ajara87 d178f20
Merge branch 'master-n3' into message-sign
ajara87 78b9598
Merge branch 'master-n3' into message-sign
ajara87 295ccd8
add UT
ajara87 58836bb
remove comments
ajara87 5fdeeec
Apply suggestion from @superboyiii
ajara87 cd98183
Add UT for quotes and normalize message
ajara87 f7e9137
Merge branch 'master-n3' into message-sign
ajara87 d6babdb
Merge branch 'master-n3' into message-sign
ajara87 3358226
Merge branch 'master-n3' into message-sign
ajara87 eec7794
Merge branch 'master-n3' into message-sign
ajara87 105c3cc
Update TestUtils.cs
ajara87 156dd25
Update UT_MainService_Wallet.cs
ajara87 4c7fb8d
add superboiii suggestion OnVerifyMessageCommand
ajara87 b004143
Update UT_MainService_Wallet.cs
ajara87 5ab8d72
chris suggestion
ajara87 51190c8
Merge branch 'master-n3' into message-sign
shargon 53643e4
Merge branch 'master-n3' into message-sign
ajara87 929a81b
Merge branch 'master-n3' into message-sign
ajara87 6abda71
Merge branch 'master-n3' into message-sign
shargon 205211d
add normalize message to verify message
ajara87 0b66999
Merge branch 'master-n3' into message-sign
superboyiii e35806c
Merge branch 'master-n3' into message-sign
ajara87 beefb8b
Merge branch 'master-n3' into message-sign
superboyiii 91c7449
Merge branch 'master-n3' into message-sign
shargon 0045632
Merge branch 'master-n3' into message-sign
ajara87 708d8aa
add parameter to choose
ajara87 d8ad5df
modify parameter name
ajara87 8f1c586
modify verify signature
ajara87 5f66021
add UTs
ajara87 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // Copyright (C) 2015-2025 The Neo Project. | ||
| // | ||
| // TestUtils.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 Neo.Json; | ||
| using Neo.Wallets.NEP6; | ||
|
|
||
| namespace Neo.CLI.Tests; | ||
|
|
||
| public static partial class TestUtils | ||
| { | ||
| public static NEP6Wallet GenerateTestWallet(string password) | ||
| { | ||
| var wallet = new JObject() | ||
| { | ||
| ["name"] = "noname", | ||
| ["version"] = new Version("1.0").ToString(), | ||
| ["scrypt"] = new ScryptParameters(2, 1, 1).ToJson(), | ||
| ["accounts"] = new JArray(), | ||
| ["extra"] = null | ||
| }; | ||
| Assert.AreEqual("{\"name\":\"noname\",\"version\":\"1.0\",\"scrypt\":{\"n\":2,\"r\":1,\"p\":1},\"accounts\":[],\"extra\":null}", wallet.ToString()); | ||
| return new NEP6Wallet(null, password, TestProtocolSettings.Default, wallet); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| // Copyright (C) 2015-2025 The Neo Project. | ||
| // | ||
| // UT_MainService_Wallet.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 System.Reflection; | ||
|
|
||
| namespace Neo.CLI.Tests; | ||
|
|
||
| [TestClass] | ||
| public class UT_MainService_Wallet | ||
| { | ||
| private NeoSystem _neoSystem; | ||
|
|
||
| [TestInitialize] | ||
| public void TestSetup() | ||
| { | ||
| _neoSystem = TestBlockchain.GetSystem(); | ||
| } | ||
|
|
||
| [TestMethod] | ||
| public void TestOnSignMessageCommand() | ||
| { | ||
| var walletPassword = "test_pwd"; | ||
| var output = CreateWalletAngSignMessage(walletPassword); | ||
|
|
||
| // Basic headers | ||
| Assert.IsFalse(string.IsNullOrWhiteSpace(output), "Output from sign message command should not be empty"); | ||
| Assert.Contains("Signed Payload", output, "Output should containt the signed payload"); | ||
| Assert.Contains("Algorithm", output, "Output should describe the algorithm used"); | ||
| Assert.Contains("Generated signatures", output, "Output should contain signatures header"); | ||
|
|
||
| // Sign block | ||
| Assert.Contains("Address", output, "Output should contain at least one address"); | ||
| Assert.Contains("PublicKey", output, "Output should contain the public key"); | ||
| Assert.Contains("Signature", output, "Output should contain the signature"); | ||
| Assert.Contains("Salt", output, "Output should contain the salt used"); | ||
|
|
||
| // Check Salt | ||
| var salt = ExtractHexValue(output, "Salt:"); | ||
| Assert.IsNotNull(salt, "Salt hex should be present in the output"); | ||
| Assert.AreEqual(32, salt!.Length, "Salt should be 16 bytes (32 hex chars)"); | ||
| Assert.IsTrue(IsHexString(salt!), "Salt should be valid hex"); | ||
| } | ||
| [TestMethod] | ||
| public void TestOnSignMessageCommandWithoutPassword() | ||
| { | ||
| var output = CreateWalletAngSignMessage(string.Empty); | ||
|
|
||
| Assert.IsFalse(string.IsNullOrWhiteSpace(output), "Output should not be empty"); | ||
| Assert.Contains("Cancelled", output, "Output should contain cancellation message"); | ||
| } | ||
| [TestMethod] | ||
| public void TestOnSignMessageCommandWrongPassword() | ||
| { | ||
| var walletPassword = "invalid_pwd"; | ||
| var output = CreateWalletAngSignMessage(walletPassword); | ||
|
|
||
| Assert.IsFalse(string.IsNullOrWhiteSpace(output), "Output should not be empty"); | ||
| Assert.Contains("Incorrect password", output, "Output should contain incorrect password"); | ||
| Assert.DoesNotContain("Signed Payload", output, "Output should not containt signed payload"); | ||
| Assert.DoesNotContain("Generated signatures", output, "Output should not containt signatures"); | ||
| } | ||
| [TestMethod] | ||
| public void TestOnSignMessageCommandWithoutAccount() | ||
| { | ||
| var walletPassword = "test_pwd"; | ||
| var output = CreateWalletAngSignMessage(walletPassword, false); | ||
|
|
||
| Assert.IsFalse(string.IsNullOrWhiteSpace(output), "Output should not be empty"); | ||
| Assert.Contains("Signed Payload", output, "Output should containt signed payload"); | ||
| Assert.Contains("Generated signatures", output, "Output should containt signatures"); | ||
| Assert.DoesNotContain("Address:", output, "Output should not containt Address"); | ||
| Assert.DoesNotContain("PublicKey:", output, "Output should not containt PublicKey"); | ||
| Assert.DoesNotContain("Signature:", output, "Output should not containt Signature"); | ||
| Assert.DoesNotContain("Salt:", output, "Output should not containt Salt"); | ||
| } | ||
| private string CreateWalletAngSignMessage(string userPassword, bool withAccount = true) | ||
| { | ||
| var walletPassword = "test_pwd"; | ||
| var message = "this is a test to sign"; | ||
|
|
||
| var wallet = TestUtils.GenerateTestWallet(walletPassword); | ||
| if (withAccount) | ||
| { | ||
| var account = wallet.CreateAccount(); | ||
| Assert.IsNotNull(account, "Wallet.CreateAccount() should create an account"); | ||
| } | ||
|
|
||
| var service = new MainService(); | ||
|
|
||
| TrySet(service, "NeoSystem", _neoSystem); | ||
| TrySetField(service, "_neoSystem", _neoSystem); | ||
| TrySet(service, "CurrentWallet", wallet); | ||
| TrySetField(service, "_currentWallet", wallet); | ||
|
|
||
| var readInputProp = service.GetType().GetProperty( | ||
| "ReadUserInput", | ||
| BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); | ||
|
|
||
| Assert.IsNotNull(readInputProp, "ReadUserInput property not found on MainService"); | ||
|
|
||
| Func<string, bool, string> fakeReadInput = (label, isPassword) => | ||
| { | ||
| Assert.AreEqual("password", label); | ||
| Assert.IsTrue(isPassword); | ||
| return userPassword; | ||
| }; | ||
|
|
||
| readInputProp!.SetValue(service, fakeReadInput); | ||
|
|
||
| var originalOut = Console.Out; | ||
| using var outputWriter = new StringWriter(); | ||
| Console.SetOut(outputWriter); | ||
|
|
||
| try | ||
| { | ||
| InvokeNonPublic(service, "OnSignMessageCommand", message); | ||
| } | ||
| finally | ||
| { | ||
| Console.SetOut(originalOut); | ||
| } | ||
|
|
||
| return outputWriter.ToString(); | ||
| } | ||
| private static string ExtractHexValue(string output, string label) | ||
| { | ||
| var index = output.IndexOf(label, StringComparison.OrdinalIgnoreCase); | ||
| if (index < 0) | ||
| return null; | ||
|
|
||
| var start = index + label.Length; | ||
| var endOfLine = output.IndexOfAny(new[] { '\r', '\n' }, start); | ||
| if (endOfLine < 0) | ||
| endOfLine = output.Length; | ||
|
|
||
| var value = output[start..endOfLine].Trim(); | ||
| return string.IsNullOrEmpty(value) ? null : value; | ||
| } | ||
| private static bool IsHexString(string value) | ||
| { | ||
| foreach (var c in value) | ||
| { | ||
| var isHex = | ||
| (c >= '0' && c <= '9') || | ||
| (c >= 'a' && c <= 'f') || | ||
| (c >= 'A' && c <= 'F'); | ||
|
|
||
| if (!isHex) return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
| private static void TrySet(object target, string propertyName, object value) | ||
| { | ||
| var prop = target.GetType().GetProperty( | ||
| propertyName, | ||
| BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | ||
| ); | ||
|
|
||
| prop?.SetValue(target, value); | ||
| } | ||
| private static void TrySetField(object target, string fieldName, object value) | ||
| { | ||
| var field = target.GetType().GetField( | ||
| fieldName, | ||
| BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | ||
| ); | ||
|
|
||
| field?.SetValue(target, value); | ||
| } | ||
| private static void InvokeNonPublic(object target, string methodName, params object[] args) | ||
| { | ||
| var method = target.GetType().GetMethod( | ||
| methodName, | ||
| BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | ||
| ); | ||
|
|
||
| Assert.IsNotNull(method, $"Method '{methodName}' not found on type '{target.GetType().FullName}'."); | ||
| method.Invoke(target, args); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.