@rootzero/contracts 1.13.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -3
- package/Codec.sol +21 -0
- package/Commands.sol +14 -0
- package/Core.sol +8 -6
- package/Endpoints.sol +2 -7
- package/Events.sol +1 -2
- package/README.md +70 -37
- package/Utils.sol +2 -4
- package/annotations/Action.sol +17 -0
- package/annotations/Label.sol +23 -0
- package/annotations/Schema.sol +53 -0
- package/codec/Blocks.sol +1643 -0
- package/codec/Buffers.sol +165 -0
- package/codec/Decoders.sol +570 -0
- package/codec/Descriptors.sol +124 -0
- package/{blocks → codec}/Keys.sol +10 -18
- package/codec/Readers.sol +114 -0
- package/{blocks → codec}/Schema.sol +43 -80
- package/codec/Specs.sol +240 -0
- package/codec/Writers.sol +485 -0
- package/commands/Allocate.sol +21 -20
- package/commands/Base.sol +83 -45
- package/commands/Burn.sol +23 -14
- package/commands/Credit.sol +21 -20
- package/commands/Debit.sol +25 -28
- package/commands/Deposit.sol +41 -36
- package/commands/Payout.sol +26 -16
- package/commands/Provision.sol +37 -38
- package/commands/Recover.sol +20 -19
- package/commands/Relay.sol +24 -22
- package/commands/Withdraw.sol +20 -19
- package/commands/admin/AllowAssets.sol +19 -16
- package/commands/admin/Allowance.sol +18 -13
- package/commands/admin/Annotate.sol +36 -0
- package/commands/admin/Appoint.sol +19 -16
- package/commands/admin/Authorize.sol +23 -14
- package/commands/admin/Base.sol +9 -2
- package/commands/admin/DenyAssets.sol +19 -16
- package/commands/admin/Dismiss.sol +19 -16
- package/commands/admin/Execute.sol +21 -19
- package/commands/admin/Unauthorize.sol +23 -14
- package/core/Access.sol +91 -49
- package/core/Calls.sol +30 -33
- package/core/Endpoint.sol +46 -143
- package/core/Host.sol +63 -21
- package/core/Pipeline.sol +16 -15
- package/core/Types.sol +1 -1
- package/docs/Schema.md +48 -31
- package/events/Annotation.sol +24 -0
- package/events/Endpoint.sol +2 -2
- package/events/Guardian.sol +2 -2
- package/events/Introduction.sol +3 -2
- package/execution/Budget.sol +40 -0
- package/execution/Execution.sol +1104 -0
- package/guards/Base.sol +11 -12
- package/guards/Revoke.sol +11 -9
- package/package.json +1 -1
- package/ports/AllowAssets.sol +12 -15
- package/ports/Allowance.sol +11 -9
- package/ports/Base.sol +35 -16
- package/ports/Credit.sol +11 -9
- package/ports/Debit.sol +11 -9
- package/ports/DenyAssets.sol +10 -13
- package/ports/Dispatch.sol +13 -15
- package/ports/Pipe.sol +14 -12
- package/ports/Redeem.sol +12 -9
- package/ports/Settle.sol +16 -10
- package/queries/Assets.sol +15 -15
- package/queries/Balances.sol +17 -17
- package/queries/Base.sol +26 -12
- package/utils/Accounts.sol +0 -23
- package/utils/Actions.sol +1 -0
- package/utils/Cursors.sol +367 -0
- package/utils/Lanes.sol +14 -0
- package/utils/Layout.sol +0 -2
- package/utils/Selectors.sol +2 -2
- package/utils/Utils.sol +46 -0
- package/Cursors.sol +0 -16
- package/blocks/Cursors.sol +0 -1529
- package/blocks/Writers.sol +0 -1036
- package/commands/admin/Label.sol +0 -32
- package/commands/admin/Schemas.sol +0 -32
- package/core/Payable.sol +0 -53
- package/events/Labeled.sol +0 -21
- package/events/Schema.sol +0 -23
- package/utils/Value.sol +0 -43
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,90 @@
|
|
|
3
3
|
Until the protocol reaches integration-stable status, minor versions may include
|
|
4
4
|
breaking API changes. Breaking changes are called out explicitly.
|
|
5
5
|
|
|
6
|
+
## 1.15.0
|
|
7
|
+
|
|
8
|
+
### Breaking Changes
|
|
9
|
+
|
|
10
|
+
- Replaced the monolithic `AccessControl` base with the composable
|
|
11
|
+
`CommanderAccess`, `AdminAccess`, `NodeAccess`, `GuardianAccess`,
|
|
12
|
+
`CallerAccess`, and `TrustAccess` capabilities. `CommandBase` now requires a
|
|
13
|
+
concrete caller policy and no longer inherits outbound `NodeCalls`.
|
|
14
|
+
- Split host composition into the commander-only `CommandHost`, the advanced
|
|
15
|
+
`Host`, and the optional `Admins` and `Guardians` feature bundles. Commands
|
|
16
|
+
that use trusted outbound calls must now inherit `NodeCalls` directly and
|
|
17
|
+
compose a `TrustAccess` implementation.
|
|
18
|
+
- Removed the guardian account subtype. Guardians are now ordinary user
|
|
19
|
+
accounts assigned a host-local role, so previously encoded guardian account
|
|
20
|
+
IDs are not compatible.
|
|
21
|
+
- Replaced the `Labeled` and `Schema` discovery events and their dedicated admin
|
|
22
|
+
commands with typed blocks in the generic `Annotation` event and the
|
|
23
|
+
`annotate` admin command.
|
|
24
|
+
- Added the origin user account to `Introduction`, changing its event signature
|
|
25
|
+
to `Introduction(uint indexed host, uint peer, bytes32 origin, uint blocknum)`.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Added opt-in `Label`, `Schema`, and `Action` annotation mixins together with
|
|
30
|
+
canonical `#label`, `#schema`, `#annotation`, and `#action` codec support.
|
|
31
|
+
- Added semantic action annotations to deposit, payable deposit, withdrawal,
|
|
32
|
+
burn, payout, and port settlement endpoints.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- Enabled the Solidity optimizer with 200 runs and pinned release testing to
|
|
37
|
+
the Cancun EVM target, the minimum target supporting the codec's `MCOPY` use.
|
|
38
|
+
- Guardians can revoke node access but remain unable to grant it; admin
|
|
39
|
+
commands continue to require both the immutable commander caller and its
|
|
40
|
+
derived admin account.
|
|
41
|
+
|
|
42
|
+
### Upgrade Compatibility
|
|
43
|
+
|
|
44
|
+
- Existing deployments are not upgradeable and this release does not preserve
|
|
45
|
+
storage layout or guardian mapping keys for proxy upgrades. Deploy fresh host
|
|
46
|
+
contracts when adopting this version.
|
|
47
|
+
|
|
48
|
+
## 1.14.0
|
|
49
|
+
|
|
50
|
+
### Breaking Changes
|
|
51
|
+
|
|
52
|
+
- Replaced `CommandContext` and the separate payable value lifecycle with the
|
|
53
|
+
unified `Execution` context. Endpoint and command implementations now open an
|
|
54
|
+
execution directly from calldata, use its packed decoder and writer lanes,
|
|
55
|
+
and finish through the shared `close` helpers.
|
|
56
|
+
- Reworked the block codec around absolute-position `Blocks` primitives,
|
|
57
|
+
packed `Cursors`, cursor-backed `Decoders`, lazy `Buffers`, and thin
|
|
58
|
+
`Writers`. Several low-level cursor and writer APIs were renamed or removed.
|
|
59
|
+
- Redefined block specs and endpoint descriptors. Specs now encode key, minimum,
|
|
60
|
+
maximum, allocation hint, stride, and optional LIST container metadata;
|
|
61
|
+
descriptors use normalized lane specs and include a transaction stride.
|
|
62
|
+
- Replaced the `Cursors.sol` package entry point with `Codec.sol`, added the
|
|
63
|
+
command-authoring `Commands.sol` entry point, and reorganized exports across
|
|
64
|
+
the package barrels.
|
|
65
|
+
- Endpoint selectors are now derived from endpoint names. The configured name
|
|
66
|
+
must match the implementing function name, and descriptor values are
|
|
67
|
+
represented as `uint` throughout.
|
|
68
|
+
- Removed the AUTH and BOUNTY codec blocks, the obsolete `Payable`/`Values`
|
|
69
|
+
helpers, and superseded decoder, writer, schema, and descriptor overloads.
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
|
|
73
|
+
- Added packed output and transaction writer lanes to `Execution`, including
|
|
74
|
+
semantic output helpers, queued credit/debit transactions, budget refunds,
|
|
75
|
+
and direct transaction finalization.
|
|
76
|
+
- Added detachable `Budget` values for pipeline-style consumers, shared lane
|
|
77
|
+
identifiers, spec-driven writer allocation, and optimized semantic block
|
|
78
|
+
readers, writers, and composite unpackers.
|
|
79
|
+
- Added a transaction-output example, command and codec barrel import examples,
|
|
80
|
+
and expanded coverage for packed cursors, buffers, descriptors, budgets,
|
|
81
|
+
execution output, and command flows.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- Standardized command, query, guard, and port implementations on the same
|
|
86
|
+
execution open/close lifecycle and renamed request terminology to input.
|
|
87
|
+
- Expanded NatSpec across the new execution and codec APIs and refreshed the
|
|
88
|
+
protocol, schema, indexing, and multi-chain documentation.
|
|
89
|
+
|
|
6
90
|
## 1.13.0
|
|
7
91
|
|
|
8
92
|
### Breaking Changes
|
|
@@ -88,7 +172,7 @@ breaking API changes. Breaking changes are called out explicitly.
|
|
|
88
172
|
- Portal no longer emits `Recovered` when retrying an undelivered witness.
|
|
89
173
|
- Renamed `Cursors.exit` to `ensureAt` and renamed its position argument to
|
|
90
174
|
`pos`.
|
|
91
|
-
- Removed the redundant `next` return value from both `
|
|
175
|
+
- Removed the redundant `next` return value from both `Decoders.init` overloads;
|
|
92
176
|
callers should use the returned cursor's `len` as the run boundary.
|
|
93
177
|
- Changed `Cursors.list` to require the expected current cursor position as
|
|
94
178
|
`pos` before entering the LIST block.
|
|
@@ -163,7 +247,7 @@ breaking API changes. Breaking changes are called out explicitly.
|
|
|
163
247
|
as the discovery/event surface for dispatch tracking.
|
|
164
248
|
- Added `ContextRecovery` schema/cursor support and context schema aliases for
|
|
165
249
|
reusable nested block schemas.
|
|
166
|
-
- Added `Values.drain`, `Payable.openValue`, and `Payable.
|
|
250
|
+
- Added `Values.drain`, `Payable.openValue`, and `Payable.end` to make
|
|
167
251
|
payable command budget lifecycles explicit.
|
|
168
252
|
|
|
169
253
|
## 1.6.0
|
|
@@ -223,7 +307,7 @@ breaking API changes. Breaking changes are called out explicitly.
|
|
|
223
307
|
|
|
224
308
|
### Breaking Changes
|
|
225
309
|
|
|
226
|
-
- Simplified `
|
|
310
|
+
- Simplified `Decoders.init` to parse a single run from the start of a calldata slice. Callers that previously passed an offset must slice first or use `Decoders.open(source, i)`.
|
|
227
311
|
- Tightened command, query, and peer request parsing around the single-run convention used by current protocol endpoints.
|
|
228
312
|
|
|
229
313
|
### Added
|
package/Codec.sol
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
// Aggregator: re-exports the complete block encoding and decoding surface.
|
|
5
|
+
// Import this file for low-level codec extensions and direct stream processing.
|
|
6
|
+
|
|
7
|
+
import { AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Tx } from "./core/Types.sol";
|
|
8
|
+
import { Keys } from "./codec/Keys.sol";
|
|
9
|
+
import { Sizes, Specs } from "./codec/Specs.sol";
|
|
10
|
+
import { Descriptors } from "./codec/Descriptors.sol";
|
|
11
|
+
import { Schemas } from "./codec/Schema.sol";
|
|
12
|
+
import { Decoders } from "./codec/Decoders.sol";
|
|
13
|
+
import { Cursors, Cur } from "./utils/Cursors.sol";
|
|
14
|
+
import { Readers, Reader } from "./codec/Readers.sol";
|
|
15
|
+
import { Blocks } from "./codec/Blocks.sol";
|
|
16
|
+
import { Buffers } from "./codec/Buffers.sol";
|
|
17
|
+
import { Writer, Writers } from "./codec/Writers.sol";
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
package/Commands.sol
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
// Aggregator: re-exports the types and helpers needed to author commands.
|
|
5
|
+
// Import this file for both standard Execution-based commands and custom decoders.
|
|
6
|
+
|
|
7
|
+
import {CommandBase} from "./commands/Base.sol";
|
|
8
|
+
import {Execution, Executions} from "./execution/Execution.sol";
|
|
9
|
+
import {Lanes} from "./utils/Lanes.sol";
|
|
10
|
+
import {Blocks} from "./codec/Blocks.sol";
|
|
11
|
+
import {Sizes, Specs} from "./codec/Specs.sol";
|
|
12
|
+
import {Decoders} from "./codec/Decoders.sol";
|
|
13
|
+
import {Cursors, Cur} from "./utils/Cursors.sol";
|
|
14
|
+
import {AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Tx} from "./core/Types.sol";
|
package/Core.sol
CHANGED
|
@@ -4,18 +4,20 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
// Aggregator: re-exports the core host, runtime, access, ledger, settlement, pipeline, node-call, and validation layer.
|
|
5
5
|
// Import this file to bring the full rootzero host base layer into scope.
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { Action } from "./annotations/Action.sol";
|
|
8
|
+
import { Label } from "./annotations/Label.sol";
|
|
9
|
+
import { Schema } from "./annotations/Schema.sol";
|
|
10
|
+
import { AdminAccess, CallerAccess, CommanderAccess, GuardianAccess, NodeAccess, TrustAccess } from "./core/Access.sol";
|
|
8
11
|
import { Balances, InsufficientFunds } from "./core/Balances.sol";
|
|
9
12
|
import { Escrows, InsufficientEscrow } from "./core/Escrows.sol";
|
|
10
13
|
import { NativeAsset, Runtime } from "./core/Runtime.sol";
|
|
11
|
-
import { Host, IHostIntroduction } from "./core/Host.sol";
|
|
12
|
-
import { CommandCalls, FailedCall, NodeCalls, PortCalls } from "./core/Calls.sol";
|
|
13
|
-
import { EndpointBase
|
|
14
|
-
import { Payable } from "./core/Payable.sol";
|
|
14
|
+
import { Admins, CommandHost, Guardians, Host, HostIntroduction, IHostIntroduction } from "./core/Host.sol";
|
|
15
|
+
import { CommandCalls, FailedCall, NodeCalls, PortCalls, RawNodeCalls } from "./core/Calls.sol";
|
|
16
|
+
import { EndpointBase } from "./core/Endpoint.sol";
|
|
15
17
|
import { Pipeline } from "./core/Pipeline.sol";
|
|
18
|
+
import { Budget, Budgets } from "./execution/Budget.sol";
|
|
16
19
|
import { CreditAccountHook, DebitAccountHook, Settlement } from "./core/Settlement.sol";
|
|
17
20
|
import { Portal } from "./core/Portal.sol";
|
|
18
|
-
import { RecoverHook } from "./commands/Recover.sol";
|
|
19
21
|
import { AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Tx } from "./core/Types.sol";
|
|
20
22
|
import { Validator } from "./core/Validator.sol";
|
|
21
23
|
|
package/Endpoints.sol
CHANGED
|
@@ -4,11 +4,7 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
// Aggregator: re-exports command, admin, port, guard, and query endpoint abstractions.
|
|
5
5
|
// Import this file to inherit from the full rootzero callable host surface without managing individual paths.
|
|
6
6
|
|
|
7
|
-
// Shared
|
|
8
|
-
import { Keys } from "./blocks/Keys.sol";
|
|
9
|
-
import { CommandBase, CommandContext } from "./commands/Base.sol";
|
|
10
|
-
import { EndpointBase, Lane } from "./core/Endpoint.sol";
|
|
11
|
-
import { Payable } from "./core/Payable.sol";
|
|
7
|
+
// Shared endpoint hooks
|
|
12
8
|
import { CreditAccountHook, DebitAccountHook } from "./core/Settlement.sol";
|
|
13
9
|
|
|
14
10
|
// Commands
|
|
@@ -27,13 +23,12 @@ import { Withdraw, WithdrawHook } from "./commands/Withdraw.sol";
|
|
|
27
23
|
import { AdminBase } from "./commands/admin/Base.sol";
|
|
28
24
|
import { AllowAssets, AllowAssetsHook } from "./commands/admin/AllowAssets.sol";
|
|
29
25
|
import { Allowance, AllowanceHook } from "./commands/admin/Allowance.sol";
|
|
26
|
+
import { Annotate } from "./commands/admin/Annotate.sol";
|
|
30
27
|
import { Appoint } from "./commands/admin/Appoint.sol";
|
|
31
28
|
import { Authorize } from "./commands/admin/Authorize.sol";
|
|
32
29
|
import { DenyAssets, DenyAssetsHook } from "./commands/admin/DenyAssets.sol";
|
|
33
30
|
import { Dismiss } from "./commands/admin/Dismiss.sol";
|
|
34
31
|
import { ExecutePayable } from "./commands/admin/Execute.sol";
|
|
35
|
-
import { Label } from "./commands/admin/Label.sol";
|
|
36
|
-
import { PublishSchema } from "./commands/admin/Schemas.sol";
|
|
37
32
|
import { Unauthorize } from "./commands/admin/Unauthorize.sol";
|
|
38
33
|
|
|
39
34
|
// Port endpoints
|
package/Events.sol
CHANGED
|
@@ -4,6 +4,7 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
// Aggregator: re-exports all event contracts.
|
|
5
5
|
// Import this file to get access to every event emitter in one import.
|
|
6
6
|
|
|
7
|
+
import { AnnotationEvent } from "./events/Annotation.sol";
|
|
7
8
|
import { AssetEvent, AssetStatusEvent } from "./events/Asset.sol";
|
|
8
9
|
import { Actions } from "./utils/Actions.sol";
|
|
9
10
|
import { BalanceEvent } from "./events/Balance.sol";
|
|
@@ -16,12 +17,10 @@ import { RecoveredEvent } from "./events/Recovered.sol";
|
|
|
16
17
|
import { EventEmitter } from "./events/Emitter.sol";
|
|
17
18
|
import { GuardianEvent } from "./events/Guardian.sol";
|
|
18
19
|
import { IntroductionEvent } from "./events/Introduction.sol";
|
|
19
|
-
import { LabeledEvent } from "./events/Labeled.sol";
|
|
20
20
|
import { LockedEvent } from "./events/Locked.sol";
|
|
21
21
|
import { NodeEvent } from "./events/Node.sol";
|
|
22
22
|
import { RootedEvent } from "./events/Rooted.sol";
|
|
23
23
|
import { RouteEvent } from "./events/Route.sol";
|
|
24
|
-
import { SchemaEvent } from "./events/Schema.sol";
|
|
25
24
|
import { SpentEvent } from "./events/Spent.sol";
|
|
26
25
|
import { UndeliveredEvent } from "./events/Undelivered.sol";
|
|
27
26
|
import { UnlockedEvent } from "./events/Unlocked.sol";
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ of the protocol: the base contracts, block codecs, and helpers that rootzero
|
|
|
10
10
|
applications compose.
|
|
11
11
|
|
|
12
12
|
Two decisions shape everything below. First, all data that crosses a host
|
|
13
|
-
boundary is encoded in one binary block format, so a
|
|
13
|
+
boundary is encoded in one binary block format, so a input means the same
|
|
14
14
|
bytes on every chain. Second, every surface operates on *runs* of blocks rather
|
|
15
15
|
than single values, so batching is the default, not a feature added later. This
|
|
16
16
|
guide introduces the protocol bottom-up: blocks, then identities, then hosts
|
|
@@ -27,18 +27,18 @@ npx create-rootzero@latest my-app
|
|
|
27
27
|
npm install @rootzero/contracts
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
A minimal host composes
|
|
31
|
-
implements their policy hooks:
|
|
30
|
+
A minimal commander-only host composes `CommandHost` with the endpoints it
|
|
31
|
+
needs and implements their policy hooks:
|
|
32
32
|
|
|
33
33
|
```solidity
|
|
34
34
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
35
35
|
pragma solidity ^0.8.33;
|
|
36
36
|
|
|
37
|
-
import {
|
|
37
|
+
import { CommandHost, Balances } from "@rootzero/contracts/Core.sol";
|
|
38
38
|
import { Deposit } from "@rootzero/contracts/Endpoints.sol";
|
|
39
39
|
|
|
40
|
-
contract ExampleHost is
|
|
41
|
-
constructor(address
|
|
40
|
+
contract ExampleHost is CommandHost, Balances, Deposit {
|
|
41
|
+
constructor(address commander) CommandHost(commander) {}
|
|
42
42
|
|
|
43
43
|
function deposit(bytes32 account, bytes32 asset, uint amount) internal override {
|
|
44
44
|
uint balance = creditTo(account, asset, amount);
|
|
@@ -47,8 +47,31 @@ contract ExampleHost is Host, Balances, Deposit {
|
|
|
47
47
|
}
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
`CommandHost` requires a nonzero commander and accepts command calls only from
|
|
51
|
+
that address. It has no built-in admin commands, peer registry, guardians,
|
|
52
|
+
inbound introduction endpoint, generic execution command, or native-token
|
|
53
|
+
receive function. Use `Host` instead when the application needs those advanced
|
|
54
|
+
facilities; its commands accept the commander, the host itself, and explicitly
|
|
55
|
+
authorized host callers.
|
|
56
|
+
|
|
57
|
+
Both host types introduce themselves during deployment when the commander is a
|
|
58
|
+
contract. That commander must implement `introduce(uint,uint)` and accept the
|
|
59
|
+
call, otherwise deployment reverts. EOA commanders do not receive an
|
|
60
|
+
introduction call.
|
|
61
|
+
|
|
62
|
+
Host contracts are designed for fresh deployment rather than proxy upgrades.
|
|
63
|
+
Releases may change inheritance storage layout, immutable configuration, and
|
|
64
|
+
encoded identity formats; storage compatibility across versions is not
|
|
65
|
+
supported.
|
|
66
|
+
|
|
67
|
+
Commands using trusted outbound `NodeCalls` also require a `TrustAccess`
|
|
68
|
+
implementation. The advanced `Host` supplies one through its composed node access, while
|
|
69
|
+
`CommandHost` deliberately does not. A minimal host can explicitly compose a
|
|
70
|
+
custom trust policy, or a command that intentionally targets arbitrary nodes
|
|
71
|
+
can inherit `RawNodeCalls` instead.
|
|
72
|
+
|
|
50
73
|
Deploy it with your own address as commander and you can call its commands
|
|
51
|
-
directly. A
|
|
74
|
+
directly. A input is a run of binary blocks — here, a single `#amount` block
|
|
52
75
|
asking to deposit an asset (the encoders are a few lines each; see
|
|
53
76
|
[`test/helpers/blocks.ts`](test/helpers/blocks.ts) for reference
|
|
54
77
|
implementations):
|
|
@@ -57,8 +80,8 @@ implementations):
|
|
|
57
80
|
const host = await ethers.deployContract("ExampleHost", [deployer.address]);
|
|
58
81
|
|
|
59
82
|
const account = encodeUserAccount(user.address); // receiving account
|
|
60
|
-
const
|
|
61
|
-
await host.deposit({ account, state: "0x", input:
|
|
83
|
+
const input = encodeAmountBlock(asset, 100n); // what to deposit
|
|
84
|
+
await host.deposit({ account, state: "0x", input: input }); // emits Balance
|
|
62
85
|
```
|
|
63
86
|
|
|
64
87
|
The rest of this guide explains the ideas this example leans on — blocks, IDs,
|
|
@@ -66,7 +89,7 @@ hosts, commands — and the surfaces built on top of them.
|
|
|
66
89
|
|
|
67
90
|
## Blocks
|
|
68
91
|
|
|
69
|
-
Every
|
|
92
|
+
Every input, response, and piece of in-flight state is a stream of typed
|
|
70
93
|
blocks. A block is a four-byte key, a four-byte big-endian length, and a
|
|
71
94
|
payload:
|
|
72
95
|
|
|
@@ -85,7 +108,7 @@ amount { bytes32 asset, uint amount }
|
|
|
85
108
|
is 72 bytes on the wire: an 8-byte header followed by two big-endian 32-byte
|
|
86
109
|
fields. There is no ABI encoding and no chain-specific type anywhere in the
|
|
87
110
|
format — field types are chain-neutral integers, bytes, and booleans. A deposit
|
|
88
|
-
|
|
111
|
+
input built for an EVM host is byte-for-byte the input a CosmWasm or Solana
|
|
89
112
|
port would parse; what differs per chain is how a host *resolves* the
|
|
90
113
|
identifiers inside, never how the bytes are laid out.
|
|
91
114
|
|
|
@@ -96,11 +119,11 @@ paths give off-chain tooling presentation names without changing a single byte
|
|
|
96
119
|
on the wire. The full schema language is specified in
|
|
97
120
|
[`docs/Schema.md`](docs/Schema.md). The standard block schemas live in
|
|
98
121
|
`Schemas` and their runtime keys in `Keys` (both via
|
|
99
|
-
`@rootzero/contracts/
|
|
122
|
+
`@rootzero/contracts/Codec.sol`).
|
|
100
123
|
|
|
101
124
|
## Batches
|
|
102
125
|
|
|
103
|
-
A
|
|
126
|
+
A input is not a single struct; it is a run of blocks. One `#amount` block
|
|
104
127
|
asks for one deposit, five blocks ask for five, and the code path is identical
|
|
105
128
|
— every endpoint parses with a cursor and loops until the stream is exhausted.
|
|
106
129
|
The descriptor lane key is the prime item: it is the block type that may repeat
|
|
@@ -117,15 +140,15 @@ Off-chain, building a batch is concatenation. Using the reference encoders from
|
|
|
117
140
|
import { concat } from "ethers";
|
|
118
141
|
import { encodeAmountBlock } from "./helpers/blocks";
|
|
119
142
|
|
|
120
|
-
const
|
|
143
|
+
const input = concat([
|
|
121
144
|
encodeAmountBlock(usdc, 250_000_000n),
|
|
122
145
|
encodeAmountBlock(dai, 250n * 10n ** 18n),
|
|
123
146
|
]);
|
|
124
|
-
// deposit(
|
|
147
|
+
// deposit(input) returns two #balance blocks in its state output and an
|
|
125
148
|
// empty transaction output
|
|
126
149
|
```
|
|
127
150
|
|
|
128
|
-
Everything downstream keeps this shape: commands loop over
|
|
151
|
+
Everything downstream keeps this shape: commands loop over input blocks,
|
|
129
152
|
settlement loops over transactions, pipelines loop over steps. Batching is
|
|
130
153
|
never a special case.
|
|
131
154
|
|
|
@@ -164,7 +187,8 @@ Structured EVM IDs use:
|
|
|
164
187
|
where `type` packs `[uint16 representation][uint8 category][uint8 subtype]`. A
|
|
165
188
|
structured ID announces what it is (an account, an asset, a node) and which
|
|
166
189
|
chain it lives on, and the payload usually embeds the underlying address. User
|
|
167
|
-
accounts are chain-agnostic
|
|
190
|
+
accounts are chain-agnostic, while admin accounts are chain-local. Guardians
|
|
191
|
+
are normal user accounts assigned a host-specific role.
|
|
168
192
|
Assets are unique IDs in the same single-word form as accounts and nodes.
|
|
169
193
|
Nodes are hosts, commands, ports, queries, and guards.
|
|
170
194
|
|
|
@@ -186,13 +210,18 @@ bytes32 opaque = Ids.toKeccak(preimage); // 0x00-prefixed opaque ID
|
|
|
186
210
|
|
|
187
211
|
A host is one contract assembled from mixins. The base `Host` brings access
|
|
188
212
|
control and the admin surface (authorize, unauthorize, appoint, dismiss,
|
|
189
|
-
|
|
213
|
+
annotate, executePayable) plus the guardian `revoke` action; you add the
|
|
190
214
|
endpoints you need and the policy hooks they require. Keeping a ledger is
|
|
191
215
|
optional: the `Balances` mixin provides one, but a host can just as well
|
|
192
216
|
implement commands that hold no persistent state in the host at all —
|
|
193
217
|
forwarding funds elsewhere, or operating only on the state threaded through a
|
|
194
218
|
pipeline.
|
|
195
219
|
|
|
220
|
+
The built-in surface is also available as two independent feature bundles:
|
|
221
|
+
`Admins` provides annotate, authorize, unauthorize, and executePayable;
|
|
222
|
+
`Guardians` provides appoint, dismiss, and revoke. The full `Host` composes
|
|
223
|
+
both, while smaller hosts can inherit either bundle separately.
|
|
224
|
+
|
|
196
225
|
Trust is explicit and minimal. Each host has an immutable **commander**
|
|
197
226
|
address fixed at construction, from which its **admin account** is derived.
|
|
198
227
|
Other contracts become callers only when their node ID is authorized into the
|
|
@@ -242,7 +271,7 @@ function deposit(
|
|
|
242
271
|
output.appendBalance(asset, amount);
|
|
243
272
|
}
|
|
244
273
|
|
|
245
|
-
return (output
|
|
274
|
+
return (end(output), "");
|
|
246
275
|
}
|
|
247
276
|
```
|
|
248
277
|
|
|
@@ -252,16 +281,18 @@ lanes, derived group sizes, and flags, plus a human-readable label:
|
|
|
252
281
|
|
|
253
282
|
```solidity
|
|
254
283
|
abstract contract MyCommand is CommandBase {
|
|
255
|
-
|
|
284
|
+
uint private immutable descriptor;
|
|
256
285
|
|
|
257
286
|
constructor() {
|
|
258
|
-
(, descriptor) = command("myCommand",
|
|
287
|
+
(, descriptor) = command("myCommand", Specs.Empty, Specs.Amount, Specs.Balance, 0, false, false);
|
|
259
288
|
}
|
|
260
289
|
|
|
261
290
|
function myCommand(
|
|
262
|
-
|
|
291
|
+
bytes32 account,
|
|
292
|
+
bytes calldata state,
|
|
293
|
+
bytes calldata input
|
|
263
294
|
) external onlyCommand returns (bytes memory, bytes memory) {
|
|
264
|
-
// parse
|
|
295
|
+
// parse input, loop, return the output state run and any transactions
|
|
265
296
|
}
|
|
266
297
|
}
|
|
267
298
|
```
|
|
@@ -279,25 +310,25 @@ A single command is rarely the whole story. A pipeline is a run of `#step`
|
|
|
279
310
|
blocks executed in order within one transaction:
|
|
280
311
|
|
|
281
312
|
```txt
|
|
282
|
-
step { uint
|
|
313
|
+
step { uint cmd, uint resources, #bytes as input }
|
|
283
314
|
```
|
|
284
315
|
|
|
285
|
-
Each step names a
|
|
316
|
+
Each step names a command, the resources it may spend, and its input.
|
|
286
317
|
The returned state threads into the next command and the final state must be
|
|
287
318
|
empty. Returned transactions do not enter the state lane; the pipeline passes
|
|
288
319
|
each decoded transaction to the shared settlement implementation before
|
|
289
320
|
running the next step. This is the core of `Pipeline.pipe`:
|
|
290
321
|
|
|
291
322
|
```solidity
|
|
292
|
-
while (
|
|
293
|
-
(uint
|
|
323
|
+
while (cur.more()) {
|
|
324
|
+
(uint cmd, uint resources, bytes calldata input) = cur.unpackStep();
|
|
294
325
|
Reader memory transactions;
|
|
295
326
|
(state, transactions.source) = dispatch(
|
|
296
|
-
|
|
327
|
+
cmd,
|
|
297
328
|
account,
|
|
298
329
|
state,
|
|
299
|
-
|
|
300
|
-
|
|
330
|
+
input,
|
|
331
|
+
budget.use(resources)
|
|
301
332
|
);
|
|
302
333
|
while (transactions.more()) {
|
|
303
334
|
(bytes32 from, bytes32 to, bytes32 asset, uint amount) = transactions.unpackTransaction();
|
|
@@ -308,7 +339,7 @@ if (state.length != 0) revert UnexpectedState();
|
|
|
308
339
|
```
|
|
309
340
|
|
|
310
341
|
A transfer, for instance, is a two-step pipeline: `debitAccount` turns an
|
|
311
|
-
`#amount`
|
|
342
|
+
`#amount` input into `#balance` state, and `payout` consumes that state
|
|
312
343
|
toward a recipient. Because a pipeline is just blocks, it is also the unit of
|
|
313
344
|
command batching — and `resources` is a chain-specific word interpreted by the
|
|
314
345
|
portal adapter (on EVM, the low 128 bits are native value in wei, drawn from a
|
|
@@ -316,13 +347,13 @@ shared budget), so the same pipeline bytes are meaningful to every port.
|
|
|
316
347
|
|
|
317
348
|
## Queries
|
|
318
349
|
|
|
319
|
-
Queries are the read endpoints: view functions that take a block-stream
|
|
350
|
+
Queries are the read endpoints: view functions that take a block-stream input
|
|
320
351
|
and return a block-stream response, with the same batch shape as commands. The
|
|
321
352
|
standard `getBalances` query takes a run of positions and answers each one in
|
|
322
353
|
order:
|
|
323
354
|
|
|
324
355
|
```txt
|
|
325
|
-
|
|
356
|
+
input: accountAsset { bytes32 account, bytes32 asset }
|
|
326
357
|
response: accountAmount { bytes32 account, bytes32 asset, uint amount }
|
|
327
358
|
```
|
|
328
359
|
|
|
@@ -345,8 +376,8 @@ This is also the cross-portal mechanism. `relayPayable` (or `portDispatchPayable
|
|
|
345
376
|
wraps a pipe and addresses it to a portal, commonly the destination host ID;
|
|
346
377
|
a bridge adapter moves the **raw
|
|
347
378
|
bytes**; the destination host parses them with the same cursor rules and runs
|
|
348
|
-
the same pipeline loop. Nothing in the payload is EVM-specific — step
|
|
349
|
-
are destination-local
|
|
379
|
+
the same pipeline loop. Nothing in the payload is EVM-specific — step commands
|
|
380
|
+
are destination-local command IDs, and only the adapter boundary (native
|
|
350
381
|
transfers, address resolution, signatures) is chain-specific. The parity rule
|
|
351
382
|
for ports is strict: every chain's implementation must parse the same input
|
|
352
383
|
bytes and produce the same output bytes for every endpoint.
|
|
@@ -377,10 +408,12 @@ Import from the package entry points rather than deep paths:
|
|
|
377
408
|
|
|
378
409
|
- `@rootzero/contracts/Core.sol` — `Host`, access control, `Balances`,
|
|
379
410
|
`Settlement`, `Pipeline`, `Portal`, validator
|
|
411
|
+
- `@rootzero/contracts/Commands.sol` — `CommandBase`, `Execution`, codec
|
|
412
|
+
helpers, and shared value types for authoring custom commands
|
|
380
413
|
- `@rootzero/contracts/Endpoints.sol` — command, admin, port, guard, and query
|
|
381
414
|
mixins and their hooks
|
|
382
|
-
- `@rootzero/contracts/
|
|
383
|
-
`Reader`/`Readers`, `Writers`, `Schemas`, `Keys`
|
|
415
|
+
- `@rootzero/contracts/Codec.sol` — `Blocks`, calldata `Cur`/`Cursors`, memory
|
|
416
|
+
`Reader`/`Readers`, `Writers`, `Schemas`, `Keys`, and `Specs`
|
|
384
417
|
- `@rootzero/contracts/Utils.sol` — `Ids`, `Nodes`, `Assets`, `Accounts`,
|
|
385
418
|
layout and value helpers
|
|
386
419
|
- `@rootzero/contracts/Events.sol` — protocol event contracts
|
package/Utils.sol
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
// Aggregator: re-exports
|
|
4
|
+
// Aggregator: re-exports protocol identifier, asset, account, cryptographic,
|
|
5
|
+
// layout, and general-purpose utility helpers.
|
|
5
6
|
// Import this file to access the full utility surface without managing individual paths.
|
|
6
7
|
|
|
7
|
-
import { Keys } from "./blocks/Keys.sol";
|
|
8
8
|
import { Accounts } from "./utils/Accounts.sol";
|
|
9
9
|
import { Actions } from "./utils/Actions.sol";
|
|
10
10
|
import { Amounts, Assets } from "./utils/Assets.sol";
|
|
@@ -13,9 +13,7 @@ import { Ids } from "./utils/Ids.sol";
|
|
|
13
13
|
import { Nodes } from "./utils/Nodes.sol";
|
|
14
14
|
import { Selectors } from "./utils/Selectors.sol";
|
|
15
15
|
import { Layout } from "./utils/Layout.sol";
|
|
16
|
-
import { Schemas } from "./blocks/Schema.sol";
|
|
17
16
|
import { addrOr, applyBps, beforeBps, bytes32ToInt, bytes32ToString, divisible, hash32, intToBytes32, isFamily, matchesBase, MAX_BPS, max8, max16, max24, max32, max40, max64, max96, max128, max160, NotDivisible, retryTicket, toLocalBase, toUnspecifiedBase, ValueOverflow } from "./utils/Utils.sol";
|
|
18
|
-
import { Budget, Values } from "./utils/Value.sol";
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {AnnotationEvent} from "../events/Annotation.sol";
|
|
5
|
+
import {Blocks} from "../codec/Blocks.sol";
|
|
6
|
+
|
|
7
|
+
/// @title Action
|
|
8
|
+
/// @notice Emits a primary semantic action annotation for an entity.
|
|
9
|
+
/// @dev For a trusted emitter, the latest action replaces the earlier value.
|
|
10
|
+
abstract contract Action is AnnotationEvent {
|
|
11
|
+
/// @notice Attach a primary semantic action to `entity`.
|
|
12
|
+
/// @param entity Entity receiving the action annotation.
|
|
13
|
+
/// @param value Canonical action identifier, such as a value from `Actions`.
|
|
14
|
+
function action(uint entity, uint value) internal virtual {
|
|
15
|
+
emit Annotation(entity, Blocks.action(value));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {AnnotationEvent} from "../events/Annotation.sol";
|
|
5
|
+
import {Blocks} from "../codec/Blocks.sol";
|
|
6
|
+
|
|
7
|
+
/// @title Label
|
|
8
|
+
/// @notice Emits standard label annotation blocks for entities.
|
|
9
|
+
/// @dev A label is identified by its entity and namespace. For a trusted
|
|
10
|
+
/// emitter, the latest label in a namespace replaces the earlier value.
|
|
11
|
+
abstract contract Label is AnnotationEvent {
|
|
12
|
+
/// @notice Attach a human-readable namespaced label to `entity`.
|
|
13
|
+
/// @param entity Entity receiving the label annotation.
|
|
14
|
+
/// @param namespace Label namespace.
|
|
15
|
+
/// @param name Human-readable name within the namespace.
|
|
16
|
+
function label(
|
|
17
|
+
uint entity,
|
|
18
|
+
bytes32 namespace,
|
|
19
|
+
string memory name
|
|
20
|
+
) internal virtual {
|
|
21
|
+
emit Annotation(entity, Blocks.label(namespace, name));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {Blocks} from "../codec/Blocks.sol";
|
|
5
|
+
import {Specs} from "../codec/Specs.sol";
|
|
6
|
+
import {AnnotationEvent} from "../events/Annotation.sol";
|
|
7
|
+
import {Runtime} from "../core/Runtime.sol";
|
|
8
|
+
|
|
9
|
+
/// @title Schema
|
|
10
|
+
/// @notice Emits standard block-schema annotations for the current host.
|
|
11
|
+
/// @dev Schema annotations accumulate for distinct block keys. For a trusted
|
|
12
|
+
/// emitter, the latest schema for the same block key replaces the earlier claim.
|
|
13
|
+
abstract contract Schema is Runtime, AnnotationEvent {
|
|
14
|
+
/// @notice Construct and publish a context-local block specification.
|
|
15
|
+
/// @param key Context-local key value.
|
|
16
|
+
/// @param min Minimum accepted payload length.
|
|
17
|
+
/// @param max Maximum accepted payload length; zero means unbounded.
|
|
18
|
+
/// @param hint Initial per-block payload capacity.
|
|
19
|
+
/// @param body Schema DSL string describing the block payload body.
|
|
20
|
+
/// @param name Schema alias name, or zero for unnamed schemas.
|
|
21
|
+
/// @return spec The context-local block specification.
|
|
22
|
+
function schema(
|
|
23
|
+
uint32 key,
|
|
24
|
+
uint32 min,
|
|
25
|
+
uint32 max,
|
|
26
|
+
uint32 hint,
|
|
27
|
+
string memory body,
|
|
28
|
+
bytes32 name
|
|
29
|
+
) internal returns (uint spec) {
|
|
30
|
+
spec = Specs.create(key, min, max, hint);
|
|
31
|
+
return schema(spec, body, name);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// @notice Construct and publish an exact-size context-local block specification.
|
|
35
|
+
/// @param key Context-local key value.
|
|
36
|
+
/// @param size Exact payload length and initial per-block payload capacity.
|
|
37
|
+
/// @param body Schema DSL string describing the block payload body.
|
|
38
|
+
/// @param name Schema alias name, or zero for unnamed schemas.
|
|
39
|
+
/// @return spec The context-local block specification.
|
|
40
|
+
function schema(uint32 key, uint32 size, string memory body, bytes32 name) internal returns (uint spec) {
|
|
41
|
+
return schema(Specs.create(key, size), body, name);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// @notice Publish an already constructed block specification for the current host.
|
|
45
|
+
/// @param spec Packed block specification.
|
|
46
|
+
/// @param body Schema DSL string describing the block payload body.
|
|
47
|
+
/// @param name Schema alias name, or zero for unnamed schemas.
|
|
48
|
+
/// @return The published block specification.
|
|
49
|
+
function schema(uint spec, string memory body, bytes32 name) internal returns (uint) {
|
|
50
|
+
emit Annotation(host, Blocks.schema(spec, body, name));
|
|
51
|
+
return spec;
|
|
52
|
+
}
|
|
53
|
+
}
|