Construct a TaskSpec and Bid
This quickstart uses public release artifacts to reproduce a TaskSpec commitment and verify the exact OCH-1.1 Bid signing shape. The Bid fixture is cryptographic test data, not a live task or live hub transaction.
Prerequisites
Section titled “Prerequisites”Install Node.js 22 or 24, Foundry for cast, and jq.
Reproduce specHash
Section titled “Reproduce specHash”Download the worked TaskSpec vector and the standalone canonicalizer:
NORTHSET_ARTIFACT_BASE_URL=${NORTHSET_ARTIFACT_BASE_URL:-https://docs.northset.ai/artifacts}
curl -fsS "$NORTHSET_ARTIFACT_BASE_URL/vectors/task-spec-v1-1.json" \ -o /tmp/northset-task-spec-vector.jsoncurl -fsS "$NORTHSET_ARTIFACT_BASE_URL/examples/canonicalize-task-spec.mjs" \ -o /tmp/canonicalize-task-spec.mjs
node /tmp/canonicalize-task-spec.mjs \ /tmp/northset-task-spec-vector.json \ > /tmp/northset-task-spec.canonical.json
SPEC_HASH=$(cast keccak "$(cat /tmp/northset-task-spec.canonical.json)")EXPECTED_HASH=$(jq -r '.specHash' /tmp/northset-task-spec-vector.json)test "$SPEC_HASH" = "$EXPECTED_HASH" && echo "TaskSpec vector: PASS"Expected result:
TaskSpec vector: PASSThe expected commitment is:
0xeac791794ef8b9f544ba597f104393d91db65a7d8499130d0bd4d0c038546ce0The canonicalizer implements the OCH-1.1 rule keccak256(RFC8785_JCS(taskSpecJson)). TaskSpec numbers must be integers no greater than 2^53 - 1; represent larger exact values as strings.
Detect a changed TaskSpec
Section titled “Detect a changed TaskSpec”Change one committed field, canonicalize again, and confirm that the commitment differs:
jq '.taskSpec.deadlines.maxComputeWindowSec = 3601 | .taskSpec' \ /tmp/northset-task-spec-vector.json \ > /tmp/northset-task-spec-tampered.json
node /tmp/canonicalize-task-spec.mjs \ /tmp/northset-task-spec-tampered.json \ > /tmp/northset-task-spec-tampered.canonical.json
TAMPERED_HASH=$(cast keccak "$(cat /tmp/northset-task-spec-tampered.canonical.json)")EXPECTED_TAMPERED_HASH=$(jq -r '.tamper.actualSpecHash' /tmp/northset-task-spec-vector.json)if test "$TAMPERED_HASH" = "$EXPECTED_TAMPERED_HASH" \ && test "$TAMPERED_HASH" != "$EXPECTED_HASH"; then echo "TaskSpec tamper: DETECTED"else echo "TaskSpec tamper: FAILED" >&2 falsefiExpected result:
TaskSpec tamper: DETECTEDVerify the exact Bid typed data
Section titled “Verify the exact Bid typed data”Download the signed fixture and extract the EIP-712 object accepted by cast:
curl -fsS "$NORTHSET_ARTIFACT_BASE_URL/vectors/bid-v1-1.json" \ -o /tmp/northset-bid-vector.json
jq '.envelope | {types, primaryType, domain, message}' \ /tmp/northset-bid-vector.json \ > /tmp/northset-bid-typed-data.json
SIGNER=$(jq -r '.envelope.signer' /tmp/northset-bid-vector.json)SIGNATURE=$(jq -r '.envelope.signature' /tmp/northset-bid-vector.json)
cast wallet verify --data --from-file \ --address "$SIGNER" \ /tmp/northset-bid-typed-data.json \ "$SIGNATURE"Expected result:
Validation succeeded. Address 0xe05fcC23807536bEe418f142D19fa0d21BB0cfF7 signed this message.The fixture binds the domain name OpenclawHub, version 1.1, chain ID, verifying contract, and all ten Bid fields. For a live bid, read chainId from the wallet or provider, set verifyingContract to the deployed hub, and read the current nonce from bidNonce(delegatee).
Detect a changed Bid
Section titled “Detect a changed Bid”Change the signed reward and confirm that the original signature no longer validates for the documented signer:
jq '. as $vector | .envelope | {types, primaryType, domain, message} | .message.rewardUSDC = $vector.tamper.replacement' \ /tmp/northset-bid-vector.json \ > /tmp/northset-bid-tampered.json
if BID_TAMPER_OUTPUT=$(cast wallet verify --data --from-file \ --address "$SIGNER" \ /tmp/northset-bid-tampered.json \ "$SIGNATURE" 2>&1); then echo "Bid tamper: FAILED" >&2 falseelif printf '%s\n' "$BID_TAMPER_OUTPUT" | grep -q "Validation failed"; then echo "Bid tamper: DETECTED"else echo "Bid tamper: FAILED" >&2 printf '%s\n' "$BID_TAMPER_OUTPUT" >&2 falsefiExpected result:
Bid tamper: DETECTEDDetect a changed STATS input
Section titled “Detect a changed STATS input”The published STATS_V1 vectors include two positive cases and one deliberately changed input. Recompute the changed input commitment and compare it with the original commitment:
curl -fsS "$NORTHSET_ARTIFACT_BASE_URL/vectors/stats-v1.json" \ -o /tmp/northset-stats-v1.json
VALUES=$(jq -c '.tamper.values' /tmp/northset-stats-v1.json)EXPECTED_INPUT_HASH=$(jq -r '.tamper.expectedInputHash' /tmp/northset-stats-v1.json)ACTUAL_INPUT_HASH=$(cast abi-encode 'f(uint64[])' "$VALUES" | cast keccak)
if test "$ACTUAL_INPUT_HASH" != "$EXPECTED_INPUT_HASH"; then echo "STATS input tamper: DETECTED"else echo "STATS input tamper: FAILED" >&2 falsefiExpected result:
STATS input tamper: DETECTEDFor STATS_V1 execution today, arrange the Northset-coordinated proof path through integration support and complete a task-bound dry run before signing or activating a bid. The public artifacts cover commitments, typed-data signing, contract interfaces, and receipt verification without exposing private proof-generation implementation.
Continue with integration artifacts or verify Task 22 settlement.