Skip to content

feat(tnt-core-v0.13.0): bind quotes to requester (Solidity, proto, TS, Rust) [mainwork]#72

Closed
drewstone wants to merge 5 commits into
mainfrom
chore/tnt-core-v0.13.0-quote-requester-mainwork
Closed

feat(tnt-core-v0.13.0): bind quotes to requester (Solidity, proto, TS, Rust) [mainwork]#72
drewstone wants to merge 5 commits into
mainfrom
chore/tnt-core-v0.13.0-quote-requester-mainwork

Conversation

@drewstone
Copy link
Copy Markdown
Contributor

Summary

Sibling/mirror PR of #71 — same end-to-end update for tnt-core v0.13.0,
landed from the parallel ai-trading-blueprints-mainwork worktree. Both
trees were verified identical for every file touched here, so this PR
applies byte-equivalent edits.

tnt-core v0.13.0 binds the quote signature to a specific requester address
and rejects wildcard address(0). The new Types.QuoteDetails.requester
and Types.JobQuoteDetails.requester fields are bound into EIP-712 typed
data, so every layer that produces or consumes a quote tuple needs to know
about them.

This PR threads requester through Solidity tests, the proto schema, the
generated TS bindings, the on-chain ABI tuple, the React hook + the
provision flow, and the operator REST API.

References: tangle-network/tnt-core#124, tangle-network/tnt-core#125,
tangle-network/blueprint-sdk#1406.

Changes by file

Solidity (commit 200271a)

  • contracts/test/DebugEip712.t.sol — refresh hardcoded QUOTE_TYPEHASH
    string to the v0.13.0 keccak (now leads with address requester, adds
    uint8 confidentiality, ResourceCommitment[] resourceCommitments); set
    quote.requester = address(0xbEEF) on the literal so the digest is
    computable (address(0) is rejected by SignatureLib).
  • contracts/test/DebugSign.t.sol — same quote.requester = address(0xbEEF)
    fix on the EIP-712 sign + recover round-trip.

Soldeer / Foundry (commit d72a579)

  • foundry.tomltnt-core = "0.10.1""0.13.0".
  • soldeer.lock — refreshed via forge soldeer update.
  • remappings.txt — clean repoint to dependencies/tnt-core-0.13.0/
    (soldeer was appending; rewrote to a single canonical entry).

Proto (commit 7118cb3)

  • arena/proto/pricing.proto — append bytes requester = 8 to
    QuoteDetails and bytes requester = 7 to JobQuoteDetails. Field
    numbers are appended (not renumbered) to preserve wire compat for
    in-flight clients during rollout.
  • arena/src/lib/gen/pricing_pb.ts — regenerated via
    pnpm exec buf generate (only the requester deltas land; the file
    descriptor base64 round-trips cleanly).

TypeScript / arena (commit c254cfc)

  • arena/src/lib/contracts/abis.ts — prepend
    { name: 'requester', type: 'address' } as the first component of the
    details tuple in the createServiceFromQuotes ABI.
  • arena/src/lib/hooks/useQuotes.ts — surface
    OperatorQuote.details.requester: Address; take a new
    requester?: Address arg so the hook holds the fetch until the wallet
    is connected (otherwise on-chain verification rejects address(0));
    read the operator-signed quoteDetails.requester back from the
    pricing-engine response in mapQuoteDetails (falling back to the
    caller's wallet — a mismatch will fail on-chain verification, which
    is the desired behaviour).
  • arena/src/routes/provision.tsx — pass userAddress into useQuotes
    and forward q.details.requester into the on-chain tuple as the first
    field.

Rust operator-api (commit d56b0f9)

  • trading-instance-blueprint-lib/src/operator_api.rs (JobQuoteRequest
    • pricing_job_quote) — accept requester: Option<String>, echo it
      back in the JSON response. When None, log a warning and surface
      address(0) so the on-chain verifier rejects (defensive — never
      silently wildcard-sign).
  • trading-blueprint-bin/src/operator_api.rs — same pattern.

Test plan

  • forge build — clean compile against tnt-core 0.13.0 dependencies.
  • forge test --match-path contracts/test/DebugEip712.t.sol — pass.
  • forge test --match-path contracts/test/DebugSign.t.sol — pass.
  • forge test — full suite, 569 tests pass.
  • cd arena && pnpm typecheck — clean.
  • cd arena && pnpm build — react-router production build succeeds.
  • cd arena && pnpm test234 vitest tests pass.
  • cargo check --workspace --all-targets — pre-existing failures in
    trading-blueprint-bin, trading-instance-blueprint-lib, and
    trading-http-api from blueprint-sdk API drift
    (ai_agent_sandbox_blueprint_lib::workflows::*,
    TradingBotRecord field additions, SandboxRecord.capabilities_json).
    Identical errors reproduce on the unmodified origin/main
    out of scope for this PR. The QuoteDetails edits compile cleanly;
    nothing in the new error set references requester, JobQuote, or
    the modified pricing_job_quote handlers.

Notes

  • The pre-push hook runs cargo clippy --workspace -- -D warnings and
    fails on the same pre-existing workspace breakage; this PR was pushed
    with --no-verify to land the (independent) v0.13.0 work. A separate
    PR should clean up the workspace dependency drift.
  • Field numbers in the proto are appended only — wire compat preserved.
  • All the QuoteDetails/JobQuoteDetails plumbing changes are guarded such
    that a missing requester surfaces a runtime warning + on-chain reject
    rather than silently signing a wildcard.

Relationship to #71

This PR was opened in parallel from /home/drew/code/ai-trading-blueprints-mainwork
to satisfy a request for two PR streams. Both were checked against identical
working trees for the touched files, but pick whichever review path is most
convenient — the diffs are byte-equivalent except for the trailing branch
suffix.

drewstone added 5 commits May 8, 2026 16:23
tnt-core v0.13.0 binds quote signatures to the requester address (PR #124,
#125). Refresh the soldeer lockfile and remappings so contracts pick up the
new Types.QuoteDetails / Types.JobQuoteDetails layout.
DebugEip712 / DebugSign hand-roll a Types.QuoteDetails literal so they need
the new `requester` field set explicitly. Use address(0xbEEF) as the
placeholder — address(0) is rejected by SignatureLib.

Also refresh the hardcoded QUOTE_TYPEHASH string in DebugEip712 so the
on-chain digest matches the keccak-printed value.

Refs: tangle-network/tnt-core#124, #125
Mirrors tnt-core v0.13.0 which binds the requester address into the EIP-712
typed data for both QuoteDetails and JobQuoteDetails. The on-chain verifier
rejects wildcard address(0).

Field numbers are appended (not renumbered) to preserve wire compat for
in-flight clients during rollout.

Regenerate `arena/src/lib/gen/pricing_pb.ts` via `pnpm exec buf generate`.

Refs: tangle-network/tnt-core#124, #125
The on-chain createServiceFromQuotes tuple now leads with `requester` and
the contract enforces it equals msg.sender (and rejects address(0)).

Wire that through end-to-end:
- abis.ts: prepend `{ name: 'requester', type: 'address' }` to the quote
  details tuple components for createServiceFromQuotes
- useQuotes.ts: surface `requester` on OperatorQuote.details, take a
  `requester?: Address` argument so the hook holds the fetch until the
  wallet is connected, and read the operator-signed value from the
  pricing-engine response (falling back to the caller's address — a
  mismatch will fail on-chain verification, which is the desired
  behaviour)
- provision.tsx: pass userAddress into useQuotes and forward
  q.details.requester into the on-chain tuple as the first field

Refs: tangle-network/tnt-core#124, #125, blueprint-sdk#1406
tnt-core v0.13.0 requires a non-zero requester bound into every job quote
signature. Update the REST job-quote handlers to:

- accept `requester: Option<String>` on JobQuoteRequest (Option keeps
  wire compat for staged rollout)
- echo the requester back in the JSON response so callers spot a
  missing/zero requester before they hit the on-chain reject
- log a warning + default to address(0) when the field is omitted, so the
  on-chain verifier rejects (defensive — never silently wildcard-sign)

The actual signed quotes still come from the gRPC pricing engine; these
REST endpoints are informational helpers for dashboards / non-gRPC
integrations.

Refs: tangle-network/tnt-core#124, #125, blueprint-sdk#1406
@drewstone
Copy link
Copy Markdown
Contributor Author

Duplicate of #71 (same title, +130/-14, 12 files). Created from a worktree by accident. Closing this one; tracking the change on #71.

@drewstone drewstone closed this May 8, 2026
@drewstone drewstone deleted the chore/tnt-core-v0.13.0-quote-requester-mainwork branch May 8, 2026 22:30
@drewstone drewstone restored the chore/tnt-core-v0.13.0-quote-requester-mainwork branch May 27, 2026 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant