Skip to content

Reject transaction signers without verification contracts - #121

Open
Jim8y wants to merge 1 commit into
neoorder:masterfrom
Jim8y:fix/audit-p2-14
Open

Reject transaction signers without verification contracts#121
Jim8y wants to merge 1 commit into
neoorder:masterfrom
Jim8y:fix/audit-p2-14

Conversation

@Jim8y

@Jim8y Jim8y commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix audit P2-14: fail explicitly when unsigned transaction construction cannot obtain a verification script for every signer, instead of dereferencing a missing wallet account or contract.

  • Return NOT_FOUND (10003) for a missing wallet or absent implicit payer.
  • Skip watch-only entries when selecting an implicit payer.
  • Reject external/deployed/watch-only signer hashes without known verification contracts as UNSUPPORTED (10001), before script simulation or fee calculation.
  • Preserve known local verification contracts, multisig scripts, and signer ordering/scopes. Do not remove a requested signer or invent a witness script.

This changes the existing transaction-construction path only. It does not add a dAPI method, address-read permission prompt, external multisig coordination, or deployment-contract witness support.

Validation

  • Publication rerun: 13/13 cases passed in the production-linked harness, dotnet run --project tests/p2-14/P2-14.Tests.csproj --no-restore. The test project is registered in OneGateApp.slnx and has a non-build/non-output reference to the app project.
  • iPhone 17 / iOS 26.5 simulator: 8/8 assertions passed using the actual native RpcClient, Neo wallet models and serializers. Only the upstream HTTP transport was controlled. Missing witnesses failed before any RPC; local known-contract construction, implicit payer selection, and multisig signer order remained valid.
  • The iOS fixture was removed before a full product rebuild with zero errors, install and Home/four-tab launch smoke.
  • Android API 36 arm64 emulator: the same 8/8 native assertions passed using the actual production transaction builder with controlled HTTP. Both the fixture and fixture-free product fully rebuilt with zero warnings/errors; the normal product installed and displayed Home with no OneGate crash observed.
  • Reviewed complete patch SHA-256: 6a3336c0c633579eeddc42a70200697435c59955546df24f8f74ad4aa31fd0a9, independently based on master@623603d634f07eaead14745da87920a356159be0. Both platform evidence sets match this hash.

Scope and limits

The native fixture called the real transaction builder with in-memory HTTP responses; it was not a live-node transaction, JavaScript-provider round trip, wallet authorization, signature or broadcast test. No real private key or funded wallet was used. Unsupported external/deployed witnesses remain unsupported, now with an explicit error.

Screenshots, fixture code and result JSON stay outside the repository; no GitHub asset upload or hosted CI pass is claimed. Before publication, recheck the current master, current feedback, duplicate PRs and the complete diff. Related independently scoped transaction/NFT changes share RpcClient; preserve their source and linked-test dependencies if later integrated, without treating these isolated tests as combined validation.

Copilot AI lite review requested due to automatic review settings September 5, 2026 08:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The functional change is narrowly scoped, matches the stated audit goals (early explicit failures), and is backed by a focused harness validating the new behavior paths.

Pull request overview

This PR addresses audit item P2-14 by making unsigned transaction construction fail explicitly (with dAPI error codes) when the wallet is missing, no implicit payer can be selected, or any requested signer lacks a known local verification contract—preventing null dereferences and preventing unsupported signer hashes from reaching simulation/fee calculation.

Changes:

  • Update RpcClient.MakeTransactionAsync to throw DapiException for missing wallets/implicit payers (10003) and for signers without known local verification scripts (10001), before any RPC is sent.
  • Add a standalone console-based test harness (tests/p2-14) that exercises the unsupported-signer and implicit-payer paths against the real RpcClient sources with an in-memory HTTP handler.
  • Register the new harness project in OneGateApp.slnx.
File summaries
File Description
tests/p2-14/README.md Documents the P2-14 harness purpose, how to run it, and expected error-code behavior.
tests/p2-14/Program.cs Implements 13-case harness validating early rejection and witness/script handling via a fake HTTP transport.
tests/p2-14/PlatformStubs.cs Stubs MAUI filesystem + unused diagnostics type needed to compile linked production sources in the harness.
tests/p2-14/P2-14.Tests.csproj Adds an executable harness project compiling/linking the production RpcClient and related models.
OneGateApp/Services/RPC/RpcClient.cs Adds explicit error handling and pre-RPC signer verification-script enforcement during transaction construction.
OneGateApp.slnx Includes the new P2-14 harness project in the solution.
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/p2-14/Program.cs
Comment on lines +137 to +142
var client = new RpcClient(new WalletProvider(wallet), ProtocolSettings.Default);
// Test-only replacement of the private transport: no real node requests, signatures or wallet saves.
var transport = typeof(RpcClient).GetField("http", BindingFlags.Instance | BindingFlags.NonPublic)!;
((HttpClient)transport.GetValue(client)!).Dispose();
transport.SetValue(client, new HttpClient(rpc));
return client;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants