You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Transaction validation is synchronous, and BatchUtils.Build validates what it assembles (breaking). Validation.Validate and all 86 per-transaction validators behind it were declared async Task without ever awaiting anything - every one of them is straight-line field checking. Nothing in the SDK is measurably faster for it, but one caller paid for the disguise: BatchUtils.Build called Validation.Validate(...) and discarded the task. An async method captures every exception into the task it returns, including the ones thrown before the first await, so a discarded task is a discarded verdict: ValidateBatch ran, decided the batch was malformed, and reported it to nobody. A Batch built around a single inner transaction - which rippled answers with temARRAY_EMPTY - came back from Build looking well formed, and so did one with more than eight inners, with a Vault/Loan inner, with an inner missing tfInnerBatchTxn, or with an inner carrying a non-zero Fee. The compiler had been saying so since the method was written (CS4014).
the validators now return void and throw on the calling thread. await Validation.Validate(tx) no longer compiles: drop the await. This is the whole migration - the exception type, the message and the conditions are unchanged, and a try/catch around the call keeps working as it is.
this is a breaking change released as a patch, deliberately. Semver would call it a major: the return type is part of a method's signature in IL, so an assembly built against 11.5.0.0 meets a MissingMethodException on 11.5.1.0 even where it never wrote await, and its sources need the await dropped before they compile again. It is numbered a patch because the validators are opt-in - nothing inside the SDK calls them, and BatchUtils.Build, the one caller that did, is the method this release fixes. If you call Validation.* or Common.ValidateBaseTransaction directly, treat this upgrade as a major one: rebuild, and drop the await.
making the signature honest is what fixes the defect, rather than adding the missing await: Build is synchronous and public, so awaiting would have meant Task<Batch> BuildAsync, and .GetAwaiter().GetResult() would have left the next caller the same trap. A validator that cannot be forgotten is a validator that has no task to forget.
TestUCredentialsValidator wrapped the already-synchronous CredentialsValidator.ValidateCredentialsList in Task.Run purely to fit the async assertion helper's Func<Task>. The wrapper worked, because the helper awaited the task - but it is exactly the shape that stops working the moment the assertion becomes synchronous, since Action accepts a lambda whose value is discarded. The nine tests call the validator directly now.