diff --git a/README.md b/README.md index 8253401..86126c7 100644 --- a/README.md +++ b/README.md @@ -119,4 +119,5 @@ pnpm demo:private-witness ## License -代码使用 Apache-2.0。ERC 草案文本按 EIP 流程使用 CC0。 +产品代码使用 Apache-2.0。ERC 草案文本与 `erc/assets/erc-8350/` 下的官方提交资产使用 +[CC0](erc/LICENSE.md);该例外不改变 `contracts/src/` 和 TypeScript 包的现有许可证。 diff --git a/contracts/foundry.toml b/contracts/foundry.toml index ff204c5..9b35e2c 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -3,6 +3,8 @@ src = "src" test = "test" out = "out" libs = ["lib"] +remappings = ["erc8350-assets/=../erc/assets/erc-8350/"] +allow_paths = ["../erc/assets/erc-8350"] solc = "0.8.24" optimizer = true optimizer_runs = 200 diff --git a/contracts/src/interfaces/IAgentMemoryState.sol b/contracts/src/interfaces/IAgentMemoryState.sol index e4faeea..5e2de35 100644 --- a/contracts/src/interfaces/IAgentMemoryState.sol +++ b/contracts/src/interfaces/IAgentMemoryState.sol @@ -72,21 +72,25 @@ interface IAgentMemoryState { view returns (address controller, address authorizer, uint64 configNonce); + /// @dev Optional, non-normative convenience; not required for ERC-8350 conformance. function transition(bytes32 transitionId) external view returns (bytes32 spaceId, bytes32 nextStateRoot, uint64 sequence, uint64 committedAt); + /// @dev Optional, non-normative convenience; not required for ERC-8350 conformance. function hashExperienceDelta(ExperienceDelta calldata delta) external pure returns (bytes32 transitionId); + /// @dev Optional, non-normative convenience; not required for ERC-8350 conformance. function computeNextStateRoot(bytes32 prevStateRoot, bytes32 transitionId) external pure returns (bytes32 nextStateRoot); + /// @dev Optional, non-normative convenience; not required for ERC-8350 conformance. function signingDigest(bytes32 structHash) external view returns (bytes32 digest); function deriveSpaceId(address initialController, bytes32 salt) diff --git a/contracts/test/unit/GoldenVector.t.sol b/contracts/test/unit/GoldenVector.t.sol index f0bdfce..9a3bcac 100644 --- a/contracts/test/unit/GoldenVector.t.sol +++ b/contracts/test/unit/GoldenVector.t.sol @@ -5,12 +5,15 @@ import {Test} from "forge-std/Test.sol"; import {AgentMemoryStateRegistry} from "../../src/reference/AgentMemoryStateRegistry.sol"; import {PrivateCommitment} from "../../src/reference/PrivateCommitment.sol"; import {IAgentMemoryState} from "../../src/interfaces/IAgentMemoryState.sol"; +import { + AgentMemoryStateRegistry as OfficialAssetRegistry +} from "erc8350-assets/AgentMemoryStateRegistry.sol"; contract GoldenVectorTest is Test { AgentMemoryStateRegistry internal registry; string internal vector; - function setUp() public { + function setUp() public virtual { registry = new AgentMemoryStateRegistry(); vector = vm.readFile(string.concat(vm.projectRoot(), "/../test-vectors/v1.json")); } @@ -22,6 +25,7 @@ contract GoldenVectorTest is Test { bytes32 transitionId = registry.hashExperienceDelta(delta); _assertPrivateCommitments(delta); + _assertTypeStrings(); _assertTransitionHashes(delta, transitionId); _assertSpaceAuthorization(delta); _assertEip712(transitionId); @@ -39,6 +43,23 @@ contract GoldenVectorTest is Test { }); } + function _assertTypeStrings() private view { + assertEq( + keccak256(bytes(_string(".types.experienceDelta"))), + registry.EXPERIENCE_DELTA_TYPEHASH() + ); + assertEq(keccak256(bytes(_string(".types.memoryState"))), registry.MEMORY_STATE_TYPEHASH()); + assertEq(keccak256(bytes(_string(".types.memorySpace"))), registry.MEMORY_SPACE_TYPEHASH()); + assertEq( + keccak256(bytes(_string(".types.spaceRegistration"))), + registry.SPACE_REGISTRATION_TYPEHASH() + ); + assertEq( + keccak256(bytes(_string(".types.spaceAuthorization"))), + registry.SPACE_AUTHORIZATION_TYPEHASH() + ); + } + function _assertPrivateCommitments(IAgentMemoryState.ExperienceDelta memory delta) private view @@ -98,8 +119,8 @@ contract GoldenVectorTest is Test { assertEq( registry.hashSpaceAuthorization( delta.spaceId, - controller, - authorizer, + vm.parseJsonAddress(vector, ".spaceAuthorization.newController"), + vm.parseJsonAddress(vector, ".spaceAuthorization.newAuthorizer"), uint64(vm.parseUint(_string(".spaceAuthorization.updateNonce"))) ), _bytes32(".spaceAuthorization.authorizationId") @@ -127,3 +148,11 @@ contract GoldenVectorTest is Test { return vm.parseJsonString(vector, path); } } + +contract OfficialAssetGoldenVectorTest is GoldenVectorTest { + function setUp() public override { + // Exercise the submitted asset through the shared reference ABI. + registry = AgentMemoryStateRegistry(address(new OfficialAssetRegistry())); + vector = vm.readFile(string.concat(vm.projectRoot(), "/../test-vectors/v1.json")); + } +} diff --git a/docs/conformance.md b/docs/conformance.md index 41cd478..0a11946 100644 --- a/docs/conformance.md +++ b/docs/conformance.md @@ -18,7 +18,7 @@ A run passes only when: 3. `packages/core` reads `test-vectors/v1.json` and matches every expected byte; 4. `implementations/minimal-ts` independently reads the same file and matches it; 5. `contracts/test/unit/GoldenVector.t.sol` reads the same file through Foundry and - matches it; and + matches it against both the product registry and the submitted Solidity asset; and 6. the gate writes a JSON record, a Markdown summary, and the command logs. The three vector suites cover: @@ -29,6 +29,11 @@ The three vector suites cover: - Transition ID and next state root; and - EIP-712 domain separator and signing digest. +All suites also check the five explicit type strings. Authorization-update hashes +use `newController` and `newAuthorizer` from the JSON rather than assuming that +the replacement accounts equal the registration accounts. These additional v1 +inputs do not change the published expected hashes. + “Byte-for-byte” means each computed `bytes32` value is compared directly with the corresponding lowercase `0x` value decoded from the canonical JSON file. The Solidity suite does not contain a second hard-coded copy of those expected values. diff --git a/docs/reviews/office-hour-113.md b/docs/reviews/office-hour-113.md new file mode 100644 index 0000000..d9c12fa --- /dev/null +++ b/docs/reviews/office-hour-113.md @@ -0,0 +1,60 @@ +# Office Hour 113 revision + +## Scope + +This revision addresses Jochem Brouwer's September 15, 2026 reviews on +[ethereum/ERCs#1910](https://github.com/ethereum/ERCs/pull/1910), based on upstream +commit `708e8130a32a525ed001225925aeed04905cb98f`. The product baseline is +`8bef6e77db895ec47220715fc73acf0e6a18954e`. + +The editor confirmed that Sam's earlier six comments were addressed. The +licensing issue is an explicit merge blocker. The supplementary review is +LLM-assisted feedback, not an independent security audit or reproduction report. + +## Changes + +| Review item | Resolution | +| --- | --- | +| [Asset licensing](https://github.com/ethereum/ERCs/pull/1910#discussion_r4018175652) | The three submitted Solidity assets declare CC0-1.0. Product sources retain Apache-2.0. | +| [Reference implementation](https://github.com/ethereum/ERCs/pull/1910#discussion_r4018243131) | Describe only the Solidity registry and interface included in the official assets; omit product names and implementations not included there. | +| [RFC links](https://github.com/ethereum/ERCs/pull/1910#discussion_r4018243138) | Link RFC 2119 and RFC 8174 to rfc-editor.org. | +| [Complete vector inputs](https://github.com/ethereum/ERCs/pull/1910#discussion_r4018243147) | Add both authorization type strings and explicit replacement accounts. All three suites read these inputs. | +| [Optional helpers](https://github.com/ethereum/ERCs/pull/1910#discussion_r4018243155) | Mark each of the four extra helpers as optional and non-normative; keep deriveSpaceId normative and preserve the ABI. | + +The earlier Sam revision is also synchronized into the product's ERC mirror, +including removal of the duplicated IERC1271 asset. No published deployment is +replaced or relabeled by this source revision. + +## Licensing boundary + +The CC0 change is limited to the three submitted Solidity assets and their copies +in `erc/assets/erc-8350/`, following the project representative's instruction for +this revision. The product LICENSE and package licenses are unchanged. Existing +source-attribution comments are retained. Git history identifies the original +ECDSA source submission as Everest's commit `a57bed8`; that history alone is not +an independent legal provenance assessment. + +## Verification boundary + +- ExperienceDelta field order, signing-domain values and hash algorithms are unchanged. +- No existing v1 input or expected output is changed; four explicit inputs are added. +- Core TS, minimal TS and Foundry validate the five type strings and replacement accounts. +- Foundry runs the same golden assertions against the actual submitted Solidity registry. +- The official vector and product canonical vector remain byte-for-byte copies. +- Source hashes and compiler metadata can change with comments or license headers. + Do not claim that deployment bytecode is unchanged on the basis of these tests. +- Frozen G4 source/evidence tags, manifests and existing reproduction records are + historical evidence and are not rewritten. They do not certify this revision. + +## Reproduce + +From a committed clean checkout with the documented toolchain: + +```bash +pnpm conformance:clean +``` + +The command produces the source commit/tree, vector SHA-256, tool versions, +per-suite logs and pass/fail results under `artifacts/conformance//`. +Run the official repository's document checks before upstream submission as well. +Editor approval, GitHub CI on the updated PR and merge are separate steps. diff --git a/erc/SUBMISSION.md b/erc/SUBMISSION.md index 0f1895a..3774325 100644 --- a/erc/SUBMISSION.md +++ b/erc/SUBMISSION.md @@ -36,11 +36,25 @@ pnpm check:erc-assets ``` `erc/assets/erc-8350/` mirrors upstream `assets/erc-8350/` (golden vector + the -dependency-free Solidity reference: registry, interface, ERC-1271 interface, ECDSA). +dependency-free Solidity reference: registry, interface, ECDSA). The duplicate +ERC-1271 interface was removed during the first editor review. + +## Office Hour 113 revision + +Jochem confirmed that Sam's six comments were addressed and requested CC0 +licensing for the submitted Solidity assets. This revision also clarifies the +reference-implementation scope, links the RFCs, completes the v1 vector inputs, +and labels optional interface helpers. See [the revision record](../docs/reviews/office-hour-113.md). + +The ERC text and submitted files under `erc/assets/erc-8350/` use +[CC0](./LICENSE.md). The product implementation under `contracts/src/` and the +TypeScript packages retain their existing licenses. This is not a repository-wide +license change. ## Remaining to Draft-merge and beyond -- [ ] ERC editor review on PR #1910 (number assignment applied 2026-07-29; awaiting one more editor review for Draft merge) +- [ ] Editor acceptance on PR #1910 after the Office Hour 113 revision (a local + revision or passing test run is not approval or merge) - [x] Magicians topic retitled with the assigned number (done by the editor, 2026-07-29) - [x] Sepolia deployment — registry `0xDdf21937ba80b5fF973610877A0955b320C91241`, see `docs/deployment.md` (2026-07-26) - [x] Independent reproduction evidence — two external, commit-pinned executable suites pass; see `docs/interop/external-reproduction.md` (2026-07-31) diff --git a/erc/assets/erc-8350/AgentMemoryStateRegistry.sol b/erc/assets/erc-8350/AgentMemoryStateRegistry.sol index 34f389f..3d5a9a8 100644 --- a/erc/assets/erc-8350/AgentMemoryStateRegistry.sol +++ b/erc/assets/erc-8350/AgentMemoryStateRegistry.sol @@ -1,9 +1,8 @@ -// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.24; import {ECDSA} from "./ECDSA.sol"; import {IAgentMemoryState} from "./IAgentMemoryState.sol"; -import {IERC1271} from "./IERC1271.sol"; /// @title AgentMemoryStateRegistry /// @notice Reference implementation of ExperienceDelta v1 and its linear state machine. @@ -39,7 +38,7 @@ contract AgentMemoryStateRegistry is IAgentMemoryState { "SpaceAuthorization(bytes32 spaceId,address newController,address newAuthorizer,uint64 nonce)" ); - bytes4 private constant _ERC1271_MAGIC_VALUE = IERC1271.isValidSignature.selector; + bytes4 private constant _ERC1271_MAGIC_VALUE = 0x1626ba7e; struct SpaceRecord { address controller; @@ -325,10 +324,11 @@ contract AgentMemoryStateRegistry is IAgentMemoryState { view returns (bool) { - (bool success, bytes memory result) = - signer.staticcall(abi.encodeCall(IERC1271.isValidSignature, (digest, signature))); - return - success && result.length >= 32 && abi.decode(result, (bytes4)) == _ERC1271_MAGIC_VALUE; + (bool success, bytes memory result) = signer.staticcall( + abi.encodeWithSelector(_ERC1271_MAGIC_VALUE, digest, signature) + ); + return success && result.length >= 32 + && abi.decode(result, (bytes4)) == _ERC1271_MAGIC_VALUE; } function _digest(bytes32 structHash) private view returns (bytes32) { diff --git a/erc/assets/erc-8350/ECDSA.sol b/erc/assets/erc-8350/ECDSA.sol index 03a22fe..6939a01 100644 --- a/erc/assets/erc-8350/ECDSA.sol +++ b/erc/assets/erc-8350/ECDSA.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.24; /// @notice Minimal, dependency-free ECDSA recovery with malleability guard. diff --git a/erc/assets/erc-8350/IAgentMemoryState.sol b/erc/assets/erc-8350/IAgentMemoryState.sol index e4faeea..db207a9 100644 --- a/erc/assets/erc-8350/IAgentMemoryState.sol +++ b/erc/assets/erc-8350/IAgentMemoryState.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.24; /// @title Agent Memory State @@ -72,21 +72,25 @@ interface IAgentMemoryState { view returns (address controller, address authorizer, uint64 configNonce); + /// @dev Optional, non-normative convenience; not required for ERC-8350 conformance. function transition(bytes32 transitionId) external view returns (bytes32 spaceId, bytes32 nextStateRoot, uint64 sequence, uint64 committedAt); + /// @dev Optional, non-normative convenience; not required for ERC-8350 conformance. function hashExperienceDelta(ExperienceDelta calldata delta) external pure returns (bytes32 transitionId); + /// @dev Optional, non-normative convenience; not required for ERC-8350 conformance. function computeNextStateRoot(bytes32 prevStateRoot, bytes32 transitionId) external pure returns (bytes32 nextStateRoot); + /// @dev Optional, non-normative convenience; not required for ERC-8350 conformance. function signingDigest(bytes32 structHash) external view returns (bytes32 digest); function deriveSpaceId(address initialController, bytes32 salt) diff --git a/erc/assets/erc-8350/IERC1271.sol b/erc/assets/erc-8350/IERC1271.sol deleted file mode 100644 index e5f2352..0000000 --- a/erc/assets/erc-8350/IERC1271.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.24; - -/// @notice Standard signature validation interface implemented by contract wallets. -interface IERC1271 { - function isValidSignature(bytes32 hash, bytes calldata signature) - external - view - returns (bytes4 magicValue); -} diff --git a/erc/assets/erc-8350/test-vectors-v1.json b/erc/assets/erc-8350/test-vectors-v1.json index fd67bca..7d0fe74 100644 --- a/erc/assets/erc-8350/test-vectors-v1.json +++ b/erc/assets/erc-8350/test-vectors-v1.json @@ -3,7 +3,9 @@ "types": { "experienceDelta": "ExperienceDelta(bytes32 spaceId,uint64 sequence,bytes32 prevStateRoot,bytes32 deltaCommitment,bytes32 provenanceCommitment,bytes32 profileId,bytes32 locatorCommitment)", "memoryState": "MemoryState(bytes32 prevStateRoot,bytes32 transitionId)", - "memorySpace": "MemorySpace(address initialController,bytes32 salt)" + "memorySpace": "MemorySpace(address initialController,bytes32 salt)", + "spaceRegistration": "SpaceRegistration(bytes32 spaceId,address controller,address authorizer)", + "spaceAuthorization": "SpaceAuthorization(bytes32 spaceId,address newController,address newAuthorizer,uint64 nonce)" }, "commitment": { "payload": "{\"op\":\"upsert\",\"resourceId\":\"memory-42\",\"value\":\"prefers dark mode\"}", @@ -47,6 +49,8 @@ "authorizer": "0x3333333333333333333333333333333333333333", "spaceSalt": "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "registrationId": "0x7bea30aa6018c9c8a3e66bd9573377af482dc791994af8c50698e3fc9d4e5d64", + "newController": "0x2222222222222222222222222222222222222222", + "newAuthorizer": "0x3333333333333333333333333333333333333333", "updateNonce": "1", "authorizationId": "0xa1fef7a8e52a533f7839f51962fa6e3ef9f8a8081efbac1eb13651801f4d1a92" } diff --git a/erc/erc-8350.md b/erc/erc-8350.md index bbba19f..e67dfac 100644 --- a/erc/erc-8350.md +++ b/erc/erc-8350.md @@ -8,15 +8,15 @@ status: Draft type: Standards Track category: ERC created: 2026-07-14 -requires: 712, 1271 +requires: 712, 1271, 7702 --- ## Abstract This ERC defines a minimal registry interface for committing authorized state transitions of autonomous-agent memory without placing raw memory in calldata. -Each transition is represented by a seven-field `ExperienceDelta`, identified by -an [EIP-712](./eip-712.md) struct hash, and applied to a linear per-space state +Each transition is represented by an `ExperienceDelta`, identified by an +[EIP-712](./eip-712.md) struct hash, and applied to a linear per-space state machine. A memory space has a controller and a replaceable authorizer. Both externally owned accounts and [ERC-1271](./eip-1271.md) contract accounts are supported. Payload semantics, storage, memory taxonomies, inference proofs, @@ -40,11 +40,26 @@ only to a private delta, optional provenance, an interpretation profile, and an optional private locator. The registry verifies authorization and state-machine continuity while remaining agnostic to the underlying memory engine. +Agent operators, wallet and application developers, auditors, and counterparties +need a shared way to refer to an agent's memory history across implementations +without disclosing the memory itself. They can verify that a declared state +advanced through an authorized, gapless sequence while prompts, embeddings, +policies, and other private witness data remain off-chain. + +Example uses include carrying a continuity checkpoint when an agent moves between +providers, selectively opening evidence to an auditor against a committed +transition, and detecting rollback or substitution relative to a known on-chain +head. This ERC does not prove that an agent actually used the committed memory, +that the private witness is true or available, or that an agent's decisions were +correct. It makes the declared state history tamper-evident and attributable. + ## Specification The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this -document are to be interpreted as described in RFC 2119 and RFC 8174. +document are to be interpreted as described in +[RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and +[RFC 8174](https://www.rfc-editor.org/rfc/rfc8174). ### Definitions @@ -80,6 +95,12 @@ controller. The salt MAY remain private until registration. ### Experience Delta v1 +`v1` names the wire format fixed by the `ExperienceDelta` and `MemoryState` +type strings, the EIP-712 signing-domain version, and the baseline commitment +domain tags defined below. Changing any of these values changes transition +identifiers, state roots, signing digests, or baseline commitments and is +therefore not wire-compatible with v1. + The following struct and field order are normative: ```solidity @@ -395,8 +416,8 @@ Transition ID, or state root without becoming a dependency of the core. ### One fixed-width Delta -A seven-field struct is small enough for independent implementations and broad -enough to bind state, private change, provenance, interpretation, and location. +A fixed-width struct is straightforward for independent implementations while +binding state, private change, provenance, interpretation, and location. Removing authors and timestamps from the Delta avoids confusing self-asserted metadata with registry authorization or chain observation. @@ -467,9 +488,7 @@ digest, registration hash, and authorization-update hash are provided in The reference implementation contains a Solidity registry ([`AgentMemoryStateRegistry.sol`](../assets/eip-8350/AgentMemoryStateRegistry.sol), implementing [`IAgentMemoryState.sol`](../assets/eip-8350/IAgentMemoryState.sol)), -a TypeScript SDK, an Awareness adapter, and a dependency-isolated second TypeScript -implementation. All three hashing implementations consume the same golden vector -linked above. +which reproduces the golden vector linked above. ## Security Considerations @@ -543,11 +562,10 @@ property rather than a deployment preference. It is stated normatively under "Immutability of the enforcing logic" in the Specification, and repeated here because a requirement stated only in this section is read as informative. -Verifiers assessing a deployment SHOULD confirm that no upgrade authority exists -over the registry — for example that the [ERC-1967](./eip-1967.md) implementation -and admin slots are empty and that the deployed source exposes no owner, admin, -initializer, or proxy — rather than inferring immutability from vector conformance -alone. +Evidence that no upgrade authority exists can include empty +[ERC-1967](./eip-1967.md) implementation and admin slots, plus deployed source +that exposes no owner, admin, initializer, or proxy. These checks assess +deployment immutability; vector conformance alone does not establish it. ## Copyright diff --git a/implementations/minimal-ts/test/golden-vector.test.ts b/implementations/minimal-ts/test/golden-vector.test.ts index 1d27e1e..e3948f5 100644 --- a/implementations/minimal-ts/test/golden-vector.test.ts +++ b/implementations/minimal-ts/test/golden-vector.test.ts @@ -1,4 +1,5 @@ import { readFileSync } from "node:fs"; +import { keccak_256 } from "@noble/hashes/sha3"; import { describe, expect, it } from "vitest"; import { EXPERIENCE_DELTA_TYPEHASH, @@ -24,6 +25,20 @@ const vector = JSON.parse( describe("dependency-isolated v1 implementation", () => { const delta = { ...vector.delta, sequence: BigInt(vector.delta.sequence) }; + it("checks every published type string independently", () => { + const typehash = (value: string) => + "0x" + Buffer.from(keccak_256(new TextEncoder().encode(value))).toString("hex"); + expect(typehash(vector.types.experienceDelta)).toBe(EXPERIENCE_DELTA_TYPEHASH); + expect(typehash(vector.types.memoryState)).toBe(MEMORY_STATE_TYPEHASH); + expect(typehash(vector.types.memorySpace)).toBe(MEMORY_SPACE_TYPEHASH); + expect(vector.types.spaceRegistration).toBe( + "SpaceRegistration(bytes32 spaceId,address controller,address authorizer)", + ); + expect(vector.types.spaceAuthorization).toBe( + "SpaceAuthorization(bytes32 spaceId,address newController,address newAuthorizer,uint64 nonce)", + ); + }); + it("matches private commitments without importing the core SDK", () => { expect( privateDeltaCommitment( @@ -66,8 +81,8 @@ describe("dependency-isolated v1 implementation", () => { expect( spaceAuthorizationId( delta.spaceId, - authorization.controller, - authorization.authorizer, + authorization.newController, + authorization.newAuthorizer, BigInt(authorization.updateNonce), ), ).toBe(authorization.authorizationId); diff --git a/packages/core/test/golden-vector.test.ts b/packages/core/test/golden-vector.test.ts index 4581605..cfa4a3f 100644 --- a/packages/core/test/golden-vector.test.ts +++ b/packages/core/test/golden-vector.test.ts @@ -1,9 +1,14 @@ import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; import { + EXPERIENCE_DELTA_TYPE, EXPERIENCE_DELTA_TYPEHASH, + MEMORY_SPACE_TYPE, MEMORY_SPACE_TYPEHASH, + MEMORY_STATE_TYPE, MEMORY_STATE_TYPEHASH, + SPACE_REGISTRATION_TYPE, + SPACE_AUTHORIZATION_TYPE, computeDomainSeparator, computeLocatorCommitment, computeNextStateRoot, @@ -23,6 +28,16 @@ const vector = JSON.parse( const delta: ExperienceDelta = { ...vector.delta, sequence: BigInt(vector.delta.sequence) }; describe("v1 golden vector", () => { + it("publishes every type string used by the vector", () => { + expect(vector.types).toEqual({ + experienceDelta: EXPERIENCE_DELTA_TYPE, + memoryState: MEMORY_STATE_TYPE, + memorySpace: MEMORY_SPACE_TYPE, + spaceRegistration: SPACE_REGISTRATION_TYPE, + spaceAuthorization: SPACE_AUTHORIZATION_TYPE, + }); + }); + it("matches commitments, transition id, and state root", () => { const encoder = new TextEncoder(); expect( @@ -76,8 +91,8 @@ describe("v1 golden vector", () => { expect( computeSpaceAuthorizationId( delta.spaceId, - authorization.controller, - authorization.authorizer, + authorization.newController, + authorization.newAuthorizer, authorization.updateNonce, ), ).toBe(authorization.authorizationId); diff --git a/scripts/check-erc-assets.mjs b/scripts/check-erc-assets.mjs index 51a409d..8139637 100644 --- a/scripts/check-erc-assets.mjs +++ b/scripts/check-erc-assets.mjs @@ -38,4 +38,20 @@ for (const [source, copy] of PAIRS) { console.log(`in sync: ${copy}`); } +for (const file of ['AgentMemoryStateRegistry.sol', 'ECDSA.sol', 'IAgentMemoryState.sol']) { + const asset = `erc/assets/erc-8350/${file}`; + try { + const source = readFileSync(asset, 'utf8'); + if (source.split(/\r?\n/u, 1)[0] !== '// SPDX-License-Identifier: CC0-1.0') { + console.error(`official reference asset must declare CC0-1.0: ${asset}`); + failed = true; + } else { + console.log(`CC0 asset: ${asset}`); + } + } catch (error) { + console.error(`missing official reference asset: ${asset} (${error.code})`); + failed = true; + } +} + process.exit(failed ? 1 : 0); diff --git a/test-vectors/v1.json b/test-vectors/v1.json index fd67bca..7d0fe74 100644 --- a/test-vectors/v1.json +++ b/test-vectors/v1.json @@ -3,7 +3,9 @@ "types": { "experienceDelta": "ExperienceDelta(bytes32 spaceId,uint64 sequence,bytes32 prevStateRoot,bytes32 deltaCommitment,bytes32 provenanceCommitment,bytes32 profileId,bytes32 locatorCommitment)", "memoryState": "MemoryState(bytes32 prevStateRoot,bytes32 transitionId)", - "memorySpace": "MemorySpace(address initialController,bytes32 salt)" + "memorySpace": "MemorySpace(address initialController,bytes32 salt)", + "spaceRegistration": "SpaceRegistration(bytes32 spaceId,address controller,address authorizer)", + "spaceAuthorization": "SpaceAuthorization(bytes32 spaceId,address newController,address newAuthorizer,uint64 nonce)" }, "commitment": { "payload": "{\"op\":\"upsert\",\"resourceId\":\"memory-42\",\"value\":\"prefers dark mode\"}", @@ -47,6 +49,8 @@ "authorizer": "0x3333333333333333333333333333333333333333", "spaceSalt": "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "registrationId": "0x7bea30aa6018c9c8a3e66bd9573377af482dc791994af8c50698e3fc9d4e5d64", + "newController": "0x2222222222222222222222222222222222222222", + "newAuthorizer": "0x3333333333333333333333333333333333333333", "updateNonce": "1", "authorizationId": "0xa1fef7a8e52a533f7839f51962fa6e3ef9f8a8081efbac1eb13651801f4d1a92" }