Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master-n3 #4589 +/- ##
=============================================
- Coverage 81.96% 81.90% -0.07%
=============================================
Files 236 236
Lines 16490 16504 +14
Branches 2402 2406 +4
=============================================
+ Hits 13516 13517 +1
- Misses 2198 2206 +8
- Partials 776 781 +5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@shargon — apologies for the overlap. I opened #4590 with a related implementation that builds on the same goal as this PR (empty-separator I should have coordinated on this branch instead of opening a separate PR. #4590 is meant as an incremental improvement (hardfork-gated rune split, expanded tests, and a small Also, I don't have access to modify or create branches in |
Could you open a pr to this one with the ut only? |
|
@shargon as long as you use my stdlib.stringsplit method changes. Because I updated both |
vncoelho
left a comment
There was a problem hiding this comment.
Another option would be to create a new method that has this behavior.
|
@roman-khimov do you have any tests about how go deal with UTF8, or unicode characteres? |
maybe this can help: |
cschuchardt88
left a comment
There was a problem hiding this comment.
Summary
Hardfork-gates empty-separator StdLib.stringSplit to a UTF-16/rune split ("abc","" → ["a","b","c"]) to match Go strings.Split, closing #4585. Only the 2-arg overload is changed. Tests rewrite the existing "abc","" case to the Huyao result; Codecov patch coverage is 60%.
Empty-string + empty-separator returns [] outside the Huyao check, so genesis replay of stringSplit("", "") changes from [""] to [] before Huyao. The 3-arg overload is untouched, so after Huyao stringSplit(s, "") and stringSplit(s, "", false) disagree. No pre-Huyao, empty+empty, 3-arg, or Unicode coverage.
Also note: using Neo.VM looks unused (ApplicationEngine is Neo.SmartContract). neo-go still returns identity for empty sep (C# compat); Huyao rune split needs a matching neo-go change or mixed nodes fork. PR is mergeable but behind master-n3.
Issues
- bug
src/Neo/SmartContract/Native/StdLib.cs:259— empty+empty[]is not Huyao-gated. Status: open - bug
src/Neo/SmartContract/Native/StdLib.cs:252— 3-argstringSplitstill identity on empty separator. Status: open - suggestion
src/Neo/SmartContract/Native/StdLib.cs:268—ConvertToUtf32vs Go runes; unpaired surrogates FAULT. Status: open - suggestion
tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs:266— tests miss pre-Huyao, empty+empty, 3-arg, Unicode. Status: open
| { | ||
| if (string.IsNullOrEmpty(str)) | ||
| { | ||
| return []; |
There was a problem hiding this comment.
bug: return [] for empty str + empty separator sits outside IsHardforkEnabled(Hardfork.HF_Huyao).
Pre-Huyao (and current mainnet) stringSplit("", "") is .NET "".Split("") → [""]. This path changes that to [] at every height, including genesis replay, as soon as this binary is running. That is an ungated consensus break.
Go strings.Split("", "") is [], which is the right Huyao result — it just has to be inside the Huyao branch:
if (string.IsNullOrEmpty(separator))
{
if (engine.IsHardforkEnabled(Hardfork.HF_Huyao))
return string.IsNullOrEmpty(str) ? [] : /* rune split */;
}
return str.Split(separator, StringSplitOptions.None);Please add a pre-Huyao test that stringSplit("", "") is still [""].
|
|
||
| [ContractMethod(CpuFee = 1 << 8)] | ||
| private static string[] StringSplit([MaxLength(MaxInputLength)] string str, string separator) | ||
| private static string[] StringSplit(ApplicationEngine engine, [MaxLength(MaxInputLength)] string str, string separator) |
There was a problem hiding this comment.
bug: Only this 2-arg overload is Huyao-gated. The 3-arg sibling is unchanged:
private static string[] StringSplit(string str, string separator, bool removeEmptyEntries)
=> str.Split(separator, removeEmptyEntries ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);After Huyao:
stringSplit("abc", "")→["a","b","c"]stringSplit("abc", "", false)→["abc"](still identity)stringSplit("", "")→[](this PR, even pre-Huyao)stringSplit("", "", false)→[""]
Compiler/framework callers often hit the 3-arg method. Both overloads must share the empty-separator path (delegate 2-arg → 3-arg, as in #4590). Please also cover stringSplit(s, "", true/false) in tests.
| var result = new List<string>(str.Length); | ||
| for (var i = 0; i < str.Length; i += char.IsHighSurrogate(str[i]) ? 2 : 1) | ||
| { | ||
| result.Add(char.ConvertFromUtf32(char.ConvertToUtf32(str, i))); |
There was a problem hiding this comment.
suggestion: char.ConvertToUtf32(str, i) throws ArgumentException on an unpaired high/low surrogate (including a trailing high surrogate, because IsHighSurrogate still advances by 2). That FAULTs the VM after Huyao; pre-Huyao Split does not throw.
Go strings.Split(s, "") splits by UTF-8 runes. The C# equivalent is str.EnumerateRunes() (unpaired surrogates become Rune values, no throw):
return [.. str.EnumerateRunes().Select(static r => r.ToString())];If FAULT on invalid UTF-16 is intentional, please document it and add a test. Also add an emoji / surrogate-pair case ("A😀👍🚀" → 4 parts) — asked on this PR, still uncovered.
| arr = engine.ResultStack.Pop<VM.Types.Array>(); | ||
| Assert.HasCount(1, arr); | ||
| Assert.AreEqual("abc", arr[0].GetString()); | ||
| Assert.HasCount(3, arr); |
There was a problem hiding this comment.
suggestion: This only asserts Huyao 2-arg ASCII ("abc","" → 3 parts). TestProtocolSettings.Default enables every hardfork at height 0, so the pre-Huyao identity path, the empty-str branch, and the Huyao-false fallthrough are untested (Codecov patch 60%, 6 lines missing).
Please add:
- Pre-Huyao (omit
HF_HuyaofromProtocolSettings.Hardforks;PersistingBlockis null soIsHardforkEnabledisContainsKey):stringSplit("abc", "")→["abc"],stringSplit("", "")→[""]. - Huyao empty+empty:
stringSplit("", "")→[]. - 3-arg empty separator, both
removeEmptyEntriesvalues. - At least one scalar/emoji split (and a non-empty separator that is itself a surrogate pair).
#4590 already has this layout if you want to fold the tests in.
Description
Close #4585
Checklist: