feat(sdk): submit appData hash-only and retire resolve_app_data - #261
Conversation
502175c to
d8d2622
Compare
066df38 to
6b637de
Compare
d8d2622 to
aab2605
Compare
6b637de to
2a1eef0
Compare
aab2605 to
23d5dde
Compare
2a1eef0 to
5305424
Compare
23d5dde to
f100e81
Compare
5305424 to
4ecf3ab
Compare
f100e81 to
0b8ccac
Compare
4ecf3ab to
326e9a2
Compare
0b8ccac to
7b20447
Compare
326e9a2 to
416847a
Compare
7b20447 to
02558d2
Compare
416847a to
f97a6b6
Compare
02558d2 to
b97c09d
Compare
f97a6b6 to
ac16274
Compare
b97c09d to
bd2df3e
Compare
ac16274 to
2bf2d96
Compare
bd2df3e to
46aeba6
Compare
2bf2d96 to
e8d4dc8
Compare
46aeba6 to
bd6e9e8
Compare
e8d4dc8 to
e33bad0
Compare
bd6e9e8 to
39fe2ee
Compare
e33bad0 to
f6317b9
Compare
39fe2ee to
3ef293a
Compare
f6317b9 to
bb52ae5
Compare
3ef293a to
6f8eee3
Compare
bb52ae5 to
a9fecf3
Compare
6f8eee3 to
9eba535
Compare
a9fecf3 to
e384beb
Compare
866cb96 to
e0d3644
Compare
c4daed6 to
4ccd7ee
Compare
e0d3644 to
911ac0d
Compare
4ccd7ee to
43148e6
Compare
9ea4356 to
7a99595
Compare
43148e6 to
3fef207
Compare
7a99595 to
8492152
Compare
3fef207 to
3da7cc2
Compare
8492152 to
c460137
Compare
3da7cc2 to
4f0e73e
Compare
c460137 to
7b945f0
Compare
4f0e73e to
2ad1455
Compare
7b945f0 to
0d65afb
Compare
2ad1455 to
a7f18ac
Compare
0d65afb to
9986684
Compare
a7f18ac to
388a0cf
Compare
9986684 to
45fea52
Compare
388a0cf to
2f0f0ff
Compare
45fea52 to
76376ec
Compare
2f0f0ff to
11bd146
Compare
76376ec to
9e503f7
Compare
11bd146 to
05db954
Compare
05db954 to
0359b40
Compare
lgahdl
left a comment
There was a problem hiding this comment.
Reviewed the full diff. Solid simplification — hash-only submission with watch-tower parity is clearly the right shape, and −546 lines including the whole resolve_app_data module plus its mock route is a real maintenance win. The test rewrite is careful (the appDataHash-absence assertion being load-bearing is a nice catch). Three non-blocking observations:
-
stop-loss asymmetry: twap-monitor moves to
OrderCreation::new_app_data_hash_only, but stop-loss stays on the document-shapeOrderCreation::new. If that's deliberate (stop-loss authors its own doc so the digest always matches), a one-line comment at the stop-loss call site would stop the next reader from "fixing" it into hash-only; if it's not deliberate, hash-only would let stop-loss drop its remainingserde_jsonusage too. -
Replacement coverage for the deleted 404 test:
poll_ready_skips_submit_when_app_data_hash_not_mirroredcovered the unmirrored-digest path; its post-change equivalent (orderbook rejectsINVALID_APP_DATA→classify_api_errordispatches backoff rather than tight-looping) doesn't have a strategy-level test in this diff. If that lives upstack in #242/#259's sweep, a pointer in the PR body would close the loop; if not, it's worth one test since this is the exact path the old code handled specially. -
Horizon check vs manual clocks: the 0.2.0 constructor's one-year
valid_tohorizon reads the wall clock, which in guest builds is the WASI clock — under the harnessManualClockoverride, guest time can sit arbitrarily far from realisticvalidTovalues, so harness-driven submit paths could spuriously classify orders as beyond-horizon (or never). Tests here handle it viavalid_to_in(), which is right; flagging the interaction mostly as a cross-ref to #169/#172 where the horizon-check consequences are being tracked, in case the manual-clock angle isn't on the radar there.
(The [patch.crates-io] documentation in Cargo.toml is exactly what our docs sweep in #311 points at — nice that the comment names the drop condition.)
The orderbook rejection envelope has an optional structured data field (e.g. a minimum-fee quote) that the retired host-error envelope round-tripped in full but the typed order-rejection dropped. Add data: option<string> to the record, populate it host-side from the parsed envelope, and thread it through the SDK mirror and the wit-bindgen conversion so no rejection information is lost end to end.
Nothing guest-side decodes the orderbook ApiError JSON any more: the host parses the envelope once into the typed order-rejection and the classifier dispatches on that. The re-export and its comment described the retired flow, so remove them from the prelude surface.
…_app_data
The orderbook accepts OrderCreation appData as the bare signed digest
and joins the pre-registered document on its side, so the pre-submit
GET /api/v1/app_data/{hash} was a redundant round-trip against the
same database that validates the submission, plus a 404 dead end
watch-tower does not have.
Bump cowprotocol to 0.2.0, patched to the cow-rs rev that exposes
OrderCreation::new_app_data_hash_only (the OrderCreationAppData::Hash
wire shape, which omits appDataHash - the orderbook's untagged decoder
would otherwise read the body as the full-document shape and reject
it) and scopes the js_sys clock fallback to browser wasm32 so the
constructor's valid_to horizon check reads WASI SystemTime instead of
emitting a wasm-bindgen import no wasmtime host can satisfy.
twap-monitor now submits order.appData verbatim; an unregistered
digest rejects as InvalidAppData and classify_api_error dispatches the
backoff, matching watch-tower exactly. Delete shepherd-sdk's
resolve_app_data module and the orderbook-mock's now-unused appData
GET route, and drop the sdk's serde_json dependency that existed only
for that lookup.
Summary
appDataas the 32-byte on-chain hash and retire theresolve_app_dataround-trip, so the module no longer fetches the full appData document before submission.cowprotocol0.1 -> 0.2 to pick up the hash-onlyOrderCreationAppDataconstructor, patched via[patch.crates-io]to thenullislabs/cow-rsfork rev17fc0c5until a release with the constructor ships.Changes
crates/shepherd-sdk/src/cow/app_data.rs(269 lines) and itsmod.rs/lib.rs/README references.modules/twap-monitor/src/strategy.rsto submitorder.appDataverbatim (the hex digest,appDataHashabsent) with no preceding appData GET.GET /api/v1/app_data/{hash}route fromtools/orderbook-mockand the matching 404 branch in twap-monitor.stop-lossand ashepherd-cow-hosttest off the deprecatedfrom_signed_order_data; drop theserde_jsondependency from the SDK.Test plan
cargo fmt --all -- --checkcargo clippy(scoped: shepherd-sdk, shepherd-cow-host, orderbook-mock, load-gen)-D warnings, cleancargo testscoped to touched crates (twap-monitor 21/21 native; SDK/host/mock suites green)wasm-tools component witontwap_monitor.wasm: only nexum/shepherd/wasi imports (no wasm-bindgen)just cibattery green via the sdk: extract the venue-generic strategy chassis #135 red-team sweep (PR fix(keeper): drop stale watches and idle duplicate rejections #242)Notes for reviewer
fix/fault-train-hardening(the in-flight fault-train tip); merges bottom-up after that train lands, retarget todevelopthen.cowprotocol0.2 bump introduces a client-side one-yearvalid_tomax-horizon check. Beyond-horizon Eip1271 tranches are dropped through the retry ledger (watch-tower parity) rather than looped on; this was hardened and tested in the sdk: extract the venue-generic strategy chassis #135 sweep (PR fix(keeper): drop stale watches and idle duplicate rejections #242).[patch.crates-io]points at thenullislabs/cow-rsfork; drop the patch once acowprotocolrelease carries the hash-only constructor.Closes #133