@rootzero/contracts 1.14.0 → 1.16.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 +100 -0
- package/Codec.sol +1 -1
- package/Commands.sol +1 -1
- package/Core.sol +8 -5
- package/Endpoints.sol +6 -6
- package/Events.sol +1 -3
- package/README.md +118 -35
- package/annotations/Action.sol +17 -0
- package/annotations/Label.sol +23 -0
- package/annotations/Schema.sol +53 -0
- package/codec/Blocks.sol +127 -32
- package/codec/Buffers.sol +3 -3
- package/codec/Decoders.sol +46 -13
- package/codec/Descriptors.sol +0 -1
- package/codec/Keys.sol +8 -4
- package/codec/Readers.sol +13 -0
- package/codec/Schema.sol +12 -3
- package/codec/Specs.sol +28 -4
- package/codec/Writers.sol +21 -6
- package/commands/Base.sol +39 -44
- package/commands/Burn.sol +8 -4
- package/commands/Credit.sol +35 -3
- package/commands/Debit.sol +46 -13
- package/commands/Deposit.sol +14 -8
- package/commands/Payout.sol +6 -2
- package/commands/Provision.sol +4 -4
- package/commands/Recover.sol +15 -8
- package/commands/Relay.sol +37 -12
- package/commands/Settle.sol +77 -0
- package/commands/Withdraw.sol +8 -4
- package/commands/admin/AllowAssets.sol +2 -2
- package/commands/admin/Allowance.sol +2 -2
- package/commands/admin/Annotate.sol +36 -0
- package/commands/admin/Appoint.sol +6 -5
- package/commands/admin/Authorize.sol +2 -2
- package/commands/admin/Base.sol +8 -1
- package/commands/admin/DenyAssets.sol +2 -2
- package/commands/admin/Dismiss.sol +6 -5
- package/commands/admin/Execute.sol +5 -4
- package/commands/admin/Unauthorize.sol +2 -2
- package/core/Access.sol +91 -49
- package/core/Calls.sol +27 -22
- package/core/Endpoint.sol +36 -46
- package/core/Host.sol +63 -21
- package/core/Pipeline.sol +6 -6
- package/core/Settlement.sol +37 -8
- package/core/Types.sol +13 -1
- package/docs/Schema.md +68 -7
- package/events/Annotation.sol +24 -0
- package/events/Guardian.sol +2 -2
- package/events/Introduction.sol +3 -2
- package/execution/Budget.sol +12 -4
- package/execution/Execution.sol +113 -18
- package/guards/Base.sol +4 -4
- package/package.json +1 -1
- package/ports/Base.sol +19 -7
- package/ports/Dispatch.sol +6 -6
- package/ports/{Settle.sol → Post.sol} +13 -9
- package/queries/Base.sol +18 -3
- package/utils/Accounts.sol +0 -23
- package/utils/Actions.sol +1 -0
- package/utils/Cursors.sol +79 -34
- package/utils/Layout.sol +0 -2
- package/commands/admin/Label.sol +0 -36
- package/commands/admin/Schemas.sol +0 -36
- package/events/Labeled.sol +0 -21
- package/events/Position.sol +0 -22
- package/events/Schema.sol +0 -23
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,106 @@
|
|
|
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.16.0
|
|
7
|
+
|
|
8
|
+
### Breaking Changes
|
|
9
|
+
|
|
10
|
+
- Removed the unused generic `Position` event and `PositionEvent` base contract.
|
|
11
|
+
- Renamed transaction handling from settlement to posting: the transaction
|
|
12
|
+
helper is now `post(...)`, and `portSettle(bytes)` is now `portPost(bytes)`.
|
|
13
|
+
The port selector and node ID change, and its action is now `Actions.Post`
|
|
14
|
+
(`14`) instead of `Actions.Settle` (`3`). The `Settlement` convenience base
|
|
15
|
+
implements both the transaction `PostHook` and position `SettleHook`.
|
|
16
|
+
- Removed `openInput` from `EndpointBase`. Port, query, and guard bases expose
|
|
17
|
+
`openInput` through the input-only `InputEndpointBase`, while custom commands
|
|
18
|
+
must pass both state and input through `openCommand`.
|
|
19
|
+
- Removed the wildcard `Specs.Any` state type. The stateful relay is now
|
|
20
|
+
`relayBalancePayable` and accepts `BALANCE` state blocks; `relayPayable`
|
|
21
|
+
explicitly accepts empty state.
|
|
22
|
+
- Renamed the numeric `Position` fields from `assets` and `liabilities` to
|
|
23
|
+
`amount` and `debt`.
|
|
24
|
+
- Renamed `Budget.use` to `useResourceValue` and split execution spending into
|
|
25
|
+
exact `useValue` and packed-resource `useResourceValue` helpers.
|
|
26
|
+
- Renamed `RoutePayableHook.route` to `RelayPayableHook.relayTo`. Recovery hooks
|
|
27
|
+
are now `RecoverPayableHook` implementations that receive the complete
|
|
28
|
+
resource word and mutable execution budget.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Added the hostless `#position` state block for threading asset-liability pairs
|
|
33
|
+
between pipeline commands.
|
|
34
|
+
- Added the `settle` command, the position `SettleHook`, and the transaction
|
|
35
|
+
`PostHook`. The `Settlement` convenience base provides default implementations
|
|
36
|
+
of both through the debit and credit account hooks.
|
|
37
|
+
- Added `relayBalancePayable` for relaying required `BALANCE` state while
|
|
38
|
+
`relayPayable` now explicitly relays with empty state.
|
|
39
|
+
- Added memory-backed `InternalDebitAccount`, `InternalCreditAccount`, and
|
|
40
|
+
`InternalSettle` adapters for hosts that execute canonical commands directly
|
|
41
|
+
from their pipeline dispatcher.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- Documented the command state-safety invariant: every command must handle the
|
|
46
|
+
complete supplied state stream or revert, and commands with empty state lanes
|
|
47
|
+
must reject non-empty state.
|
|
48
|
+
- Endpoint decoder opening now requires the complete supplied lane to be one
|
|
49
|
+
homogeneous run of the descriptor's declared key; trailing block types are
|
|
50
|
+
rejected instead of silently left outside the decoder cursor.
|
|
51
|
+
- Block runs and cursors now retain raw block counts only. Descriptor stride
|
|
52
|
+
conversion and state/input group reconciliation happen once in execution
|
|
53
|
+
opening rather than in `Blocks` or `Cursors`.
|
|
54
|
+
- Pipeline transaction streams are posted before the next step, and position
|
|
55
|
+
state is settled separately through the scalar asset, amount, liability, and
|
|
56
|
+
debt hook.
|
|
57
|
+
|
|
58
|
+
### Upgrade Compatibility
|
|
59
|
+
|
|
60
|
+
- Command and port selectors, block schemas, and hook signatures changed in
|
|
61
|
+
this release. Deploy fresh hosts and update pipeline builders and peer
|
|
62
|
+
integrations together.
|
|
63
|
+
|
|
64
|
+
## 1.15.0
|
|
65
|
+
|
|
66
|
+
### Breaking Changes
|
|
67
|
+
|
|
68
|
+
- Replaced the monolithic `AccessControl` base with the composable
|
|
69
|
+
`CommanderAccess`, `AdminAccess`, `NodeAccess`, `GuardianAccess`,
|
|
70
|
+
`CallerAccess`, and `TrustAccess` capabilities. `CommandBase` now requires a
|
|
71
|
+
concrete caller policy and no longer inherits outbound `NodeCalls`.
|
|
72
|
+
- Split host composition into the commander-only `CommandHost`, the advanced
|
|
73
|
+
`Host`, and the optional `Admins` and `Guardians` feature bundles. Commands
|
|
74
|
+
that use trusted outbound calls must now inherit `NodeCalls` directly and
|
|
75
|
+
compose a `TrustAccess` implementation.
|
|
76
|
+
- Removed the guardian account subtype. Guardians are now ordinary user
|
|
77
|
+
accounts assigned a host-local role, so previously encoded guardian account
|
|
78
|
+
IDs are not compatible.
|
|
79
|
+
- Replaced the `Labeled` and `Schema` discovery events and their dedicated admin
|
|
80
|
+
commands with typed blocks in the generic `Annotation` event and the
|
|
81
|
+
`annotate` admin command.
|
|
82
|
+
- Added the origin user account to `Introduction`, changing its event signature
|
|
83
|
+
to `Introduction(uint indexed host, uint peer, bytes32 origin, uint blocknum)`.
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- Added opt-in `Label`, `Schema`, and `Action` annotation mixins together with
|
|
88
|
+
canonical `#label`, `#schema`, `#annotation`, and `#action` codec support.
|
|
89
|
+
- Added semantic action annotations to deposit, payable deposit, withdrawal,
|
|
90
|
+
burn, payout, and port settlement endpoints.
|
|
91
|
+
|
|
92
|
+
### Changed
|
|
93
|
+
|
|
94
|
+
- Enabled the Solidity optimizer with 200 runs and pinned release testing to
|
|
95
|
+
the Cancun EVM target, the minimum target supporting the codec's `MCOPY` use.
|
|
96
|
+
- Guardians can revoke node access but remain unable to grant it; admin
|
|
97
|
+
commands continue to require both the immutable commander caller and its
|
|
98
|
+
derived admin account.
|
|
99
|
+
|
|
100
|
+
### Upgrade Compatibility
|
|
101
|
+
|
|
102
|
+
- Existing deployments are not upgradeable and this release does not preserve
|
|
103
|
+
storage layout or guardian mapping keys for proxy upgrades. Deploy fresh host
|
|
104
|
+
contracts when adopting this version.
|
|
105
|
+
|
|
6
106
|
## 1.14.0
|
|
7
107
|
|
|
8
108
|
### Breaking Changes
|
package/Codec.sol
CHANGED
|
@@ -4,7 +4,7 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
// Aggregator: re-exports the complete block encoding and decoding surface.
|
|
5
5
|
// Import this file for low-level codec extensions and direct stream processing.
|
|
6
6
|
|
|
7
|
-
import { AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Tx } from "./core/Types.sol";
|
|
7
|
+
import { AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Position, Tx } from "./core/Types.sol";
|
|
8
8
|
import { Keys } from "./codec/Keys.sol";
|
|
9
9
|
import { Sizes, Specs } from "./codec/Specs.sol";
|
|
10
10
|
import { Descriptors } from "./codec/Descriptors.sol";
|
package/Commands.sol
CHANGED
|
@@ -11,4 +11,4 @@ import {Blocks} from "./codec/Blocks.sol";
|
|
|
11
11
|
import {Sizes, Specs} from "./codec/Specs.sol";
|
|
12
12
|
import {Decoders} from "./codec/Decoders.sol";
|
|
13
13
|
import {Cursors, Cur} from "./utils/Cursors.sol";
|
|
14
|
-
import {AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Tx} from "./core/Types.sol";
|
|
14
|
+
import {AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Position, Tx} from "./core/Types.sol";
|
package/Core.sol
CHANGED
|
@@ -4,18 +4,21 @@ 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";
|
|
14
|
+
import { Admins, CommandHost, Guardians, Host, HostIntroduction, IHostIntroduction } from "./core/Host.sol";
|
|
15
|
+
import { CommandCalls, FailedCall, NodeCalls, PortCalls, RawNodeCalls } from "./core/Calls.sol";
|
|
13
16
|
import { EndpointBase } from "./core/Endpoint.sol";
|
|
14
17
|
import { Pipeline } from "./core/Pipeline.sol";
|
|
15
18
|
import { Budget, Budgets } from "./execution/Budget.sol";
|
|
16
|
-
import { CreditAccountHook, DebitAccountHook, Settlement } from "./core/Settlement.sol";
|
|
19
|
+
import { CreditAccountHook, DebitAccountHook, PostHook, SettleHook, Settlement } from "./core/Settlement.sol";
|
|
17
20
|
import { Portal } from "./core/Portal.sol";
|
|
18
|
-
import { AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Tx } from "./core/Types.sol";
|
|
21
|
+
import { AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Position, Tx } from "./core/Types.sol";
|
|
19
22
|
import { Validator } from "./core/Validator.sol";
|
|
20
23
|
|
|
21
24
|
|
package/Endpoints.sol
CHANGED
|
@@ -5,7 +5,7 @@ pragma solidity ^0.8.33;
|
|
|
5
5
|
// Import this file to inherit from the full rootzero callable host surface without managing individual paths.
|
|
6
6
|
|
|
7
7
|
// Shared endpoint hooks
|
|
8
|
-
import { CreditAccountHook, DebitAccountHook } from "./core/Settlement.sol";
|
|
8
|
+
import { CreditAccountHook, DebitAccountHook, PostHook, SettleHook } from "./core/Settlement.sol";
|
|
9
9
|
|
|
10
10
|
// Commands
|
|
11
11
|
import { Allocate, AllocateHook } from "./commands/Allocate.sol";
|
|
@@ -15,21 +15,21 @@ import { DebitAccount } from "./commands/Debit.sol";
|
|
|
15
15
|
import { Deposit, DepositHook, DepositPayable, DepositPayableHook } from "./commands/Deposit.sol";
|
|
16
16
|
import { Payout, PayoutHook } from "./commands/Payout.sol";
|
|
17
17
|
import { Provision, ProvisionHook, ProvisionPayable, ProvisionPayableHook } from "./commands/Provision.sol";
|
|
18
|
-
import {
|
|
19
|
-
import { RelayPayable,
|
|
18
|
+
import { RecoverPayable, RecoverPayableHook } from "./commands/Recover.sol";
|
|
19
|
+
import { RelayPayable, RelayBalancePayable, RelayPayableHook } from "./commands/Relay.sol";
|
|
20
|
+
import { Settle } from "./commands/Settle.sol";
|
|
20
21
|
import { Withdraw, WithdrawHook } from "./commands/Withdraw.sol";
|
|
21
22
|
|
|
22
23
|
// Admin commands
|
|
23
24
|
import { AdminBase } from "./commands/admin/Base.sol";
|
|
24
25
|
import { AllowAssets, AllowAssetsHook } from "./commands/admin/AllowAssets.sol";
|
|
25
26
|
import { Allowance, AllowanceHook } from "./commands/admin/Allowance.sol";
|
|
27
|
+
import { Annotate } from "./commands/admin/Annotate.sol";
|
|
26
28
|
import { Appoint } from "./commands/admin/Appoint.sol";
|
|
27
29
|
import { Authorize } from "./commands/admin/Authorize.sol";
|
|
28
30
|
import { DenyAssets, DenyAssetsHook } from "./commands/admin/DenyAssets.sol";
|
|
29
31
|
import { Dismiss } from "./commands/admin/Dismiss.sol";
|
|
30
32
|
import { ExecutePayable } from "./commands/admin/Execute.sol";
|
|
31
|
-
import { Label } from "./commands/admin/Label.sol";
|
|
32
|
-
import { PublishSchema } from "./commands/admin/Schemas.sol";
|
|
33
33
|
import { Unauthorize } from "./commands/admin/Unauthorize.sol";
|
|
34
34
|
|
|
35
35
|
// Port endpoints
|
|
@@ -42,7 +42,7 @@ import { PortDebitAccount } from "./ports/Debit.sol";
|
|
|
42
42
|
import { PortDenyAssets } from "./ports/DenyAssets.sol";
|
|
43
43
|
import { PortPipePayable } from "./ports/Pipe.sol";
|
|
44
44
|
import { PortDispatchPayable } from "./ports/Dispatch.sol";
|
|
45
|
-
import {
|
|
45
|
+
import { PortPost } from "./ports/Post.sol";
|
|
46
46
|
|
|
47
47
|
// Guard endpoints
|
|
48
48
|
import { GuardBase } from "./guards/Base.sol";
|
package/Events.sol
CHANGED
|
@@ -4,24 +4,22 @@ 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";
|
|
10
11
|
import { CommanderEvent } from "./events/Commander.sol";
|
|
11
12
|
import { DispatchEvent } from "./events/Dispatch.sol";
|
|
12
13
|
import { EndpointEvent } from "./events/Endpoint.sol";
|
|
13
|
-
import { PositionEvent } from "./events/Position.sol";
|
|
14
14
|
import { ReceivedEvent } from "./events/Received.sol";
|
|
15
15
|
import { RecoveredEvent } from "./events/Recovered.sol";
|
|
16
16
|
import { EventEmitter } from "./events/Emitter.sol";
|
|
17
17
|
import { GuardianEvent } from "./events/Guardian.sol";
|
|
18
18
|
import { IntroductionEvent } from "./events/Introduction.sol";
|
|
19
|
-
import { LabeledEvent } from "./events/Labeled.sol";
|
|
20
19
|
import { LockedEvent } from "./events/Locked.sol";
|
|
21
20
|
import { NodeEvent } from "./events/Node.sol";
|
|
22
21
|
import { RootedEvent } from "./events/Rooted.sol";
|
|
23
22
|
import { RouteEvent } from "./events/Route.sol";
|
|
24
|
-
import { SchemaEvent } from "./events/Schema.sol";
|
|
25
23
|
import { SpentEvent } from "./events/Spent.sol";
|
|
26
24
|
import { UndeliveredEvent } from "./events/Undelivered.sol";
|
|
27
25
|
import { UnlockedEvent } from "./events/Unlocked.sol";
|
package/README.md
CHANGED
|
@@ -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,6 +47,29 @@ 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
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
|
|
@@ -126,7 +149,7 @@ const input = concat([
|
|
|
126
149
|
```
|
|
127
150
|
|
|
128
151
|
Everything downstream keeps this shape: commands loop over input blocks,
|
|
129
|
-
|
|
152
|
+
posting loops over transactions, pipelines loop over steps. Batching is
|
|
130
153
|
never a special case.
|
|
131
154
|
|
|
132
155
|
## IDs, Accounts, Assets, and Nodes
|
|
@@ -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
|
|
@@ -219,30 +248,51 @@ struct CommandContext {
|
|
|
219
248
|
|
|
220
249
|
Every command returns two block streams: `state`, which is threaded into the
|
|
221
250
|
next pipeline step, and `transactions`, which contains `#transaction` blocks
|
|
222
|
-
for the pipeline host to
|
|
251
|
+
for the pipeline host to post outside the state lane. Either stream may be
|
|
223
252
|
empty.
|
|
224
253
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
254
|
+
State is linear, not optional ambient context. A command is responsible for
|
|
255
|
+
the entire state stream it receives: it must validate and consume it, transform
|
|
256
|
+
and return it, forward it intact, or revert. A command must never succeed while
|
|
257
|
+
silently ignoring or dropping supplied state. Commands that declare
|
|
258
|
+
`Specs.Empty` state therefore reject any non-empty state, while commands that
|
|
259
|
+
accept state validate the complete stream against their declared state schema.
|
|
260
|
+
This is especially important for `#position`, because dropping a position could
|
|
261
|
+
silently discard both live value and an outstanding debt requirement.
|
|
228
262
|
|
|
229
|
-
The
|
|
230
|
-
|
|
263
|
+
The input carries instructions; the state carries live value. While a
|
|
264
|
+
sequence of commands executes, `#balance`, `#custody`, and `#position` blocks
|
|
265
|
+
in the state are the value being moved — produced by one command, consumed by
|
|
266
|
+
the next. A position carries an asset-liability pair as
|
|
267
|
+
`{ asset, amount, liability, debt }`.
|
|
268
|
+
|
|
269
|
+
`#position` is general live state rather than a lending-specific debt record.
|
|
270
|
+
It pairs value acquired or controlled with value owed or required. A command
|
|
271
|
+
may preserve or replace either side and return the resulting position for the
|
|
272
|
+
next step; `settle` terminally consumes the pair. This supports swaps,
|
|
273
|
+
borrowing, refinancing, collateral changes, callback obligations, cross-host
|
|
274
|
+
claims, fees, netting, and other multi-step operations. A position is a
|
|
275
|
+
transient representation and does not itself create or erase an obligation
|
|
276
|
+
recorded by an external system.
|
|
277
|
+
|
|
278
|
+
The standard `Deposit` mixin shows the canonical shape: open and validate both
|
|
279
|
+
command lanes, loop the batch, call the hook, and write the output run:
|
|
231
280
|
|
|
232
281
|
```solidity
|
|
233
282
|
function deposit(
|
|
234
|
-
|
|
283
|
+
bytes32 account,
|
|
284
|
+
bytes calldata state,
|
|
285
|
+
bytes calldata input
|
|
235
286
|
) external onlyCommand returns (bytes memory, bytes memory) {
|
|
236
|
-
|
|
237
|
-
Writer memory output = Writers.allocBalances(outputs);
|
|
287
|
+
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
238
288
|
|
|
239
|
-
while (
|
|
240
|
-
(bytes32 asset, uint amount) =
|
|
241
|
-
deposit(
|
|
242
|
-
|
|
289
|
+
while (exec.more()) {
|
|
290
|
+
(bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
|
|
291
|
+
deposit(account, asset, amount); // host policy hook
|
|
292
|
+
exec.outputBalance(asset, amount);
|
|
243
293
|
}
|
|
244
294
|
|
|
245
|
-
return (
|
|
295
|
+
return close(exec, account);
|
|
246
296
|
}
|
|
247
297
|
```
|
|
248
298
|
|
|
@@ -263,7 +313,13 @@ abstract contract MyCommand is CommandBase {
|
|
|
263
313
|
bytes calldata state,
|
|
264
314
|
bytes calldata input
|
|
265
315
|
) external onlyCommand returns (bytes memory, bytes memory) {
|
|
266
|
-
|
|
316
|
+
Execution memory exec = openCommand(state, input, descriptor, 0);
|
|
317
|
+
while (exec.more()) {
|
|
318
|
+
(bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
|
|
319
|
+
// Apply command-specific behavior for this group.
|
|
320
|
+
exec.outputBalance(asset, amount);
|
|
321
|
+
}
|
|
322
|
+
return close(exec, account);
|
|
267
323
|
}
|
|
268
324
|
}
|
|
269
325
|
```
|
|
@@ -272,8 +328,10 @@ The standard commands cover the common ledger movements: `deposit` and
|
|
|
272
328
|
`depositPayable` (external funds in), `withdraw` and `burn` (funds out),
|
|
273
329
|
`debitAccount` and `creditAccount` (internal movements), `payout` (deliver
|
|
274
330
|
state to other accounts), `allocate` (turn balance state into custody),
|
|
275
|
-
`provision` (provision custody from an external allocation),
|
|
276
|
-
(
|
|
331
|
+
`provision` (provision custody from an external allocation), `settle` (consume
|
|
332
|
+
asset-liability position state), `relayPayable` (relay a pipeline without
|
|
333
|
+
state), and `relayBalancePayable` (relay balance state and a pipeline to another
|
|
334
|
+
portal).
|
|
277
335
|
|
|
278
336
|
## Pipelines
|
|
279
337
|
|
|
@@ -287,7 +345,7 @@ step { uint cmd, uint resources, #bytes as input }
|
|
|
287
345
|
Each step names a command, the resources it may spend, and its input.
|
|
288
346
|
The returned state threads into the next command and the final state must be
|
|
289
347
|
empty. Returned transactions do not enter the state lane; the pipeline passes
|
|
290
|
-
each decoded transaction to the shared
|
|
348
|
+
each decoded transaction to the shared posting implementation before
|
|
291
349
|
running the next step. This is the core of `Pipeline.pipe`:
|
|
292
350
|
|
|
293
351
|
```solidity
|
|
@@ -299,11 +357,11 @@ while (cur.more()) {
|
|
|
299
357
|
account,
|
|
300
358
|
state,
|
|
301
359
|
input,
|
|
302
|
-
budget.
|
|
360
|
+
budget.useResourceValue(resources)
|
|
303
361
|
);
|
|
304
362
|
while (transactions.more()) {
|
|
305
363
|
(bytes32 from, bytes32 to, bytes32 asset, uint amount) = transactions.unpackTransaction();
|
|
306
|
-
|
|
364
|
+
post(from, to, asset, amount);
|
|
307
365
|
}
|
|
308
366
|
}
|
|
309
367
|
if (state.length != 0) revert UnexpectedState();
|
|
@@ -316,6 +374,31 @@ command batching — and `resources` is a chain-specific word interpreted by the
|
|
|
316
374
|
portal adapter (on EVM, the low 128 bits are native value in wei, drawn from a
|
|
317
375
|
shared budget), so the same pipeline bytes are meaningful to every port.
|
|
318
376
|
|
|
377
|
+
Hosts that implement a pipeline locally can inherit `InternalDebitAccount`,
|
|
378
|
+
`InternalCreditAccount`, and `InternalSettle` to advertise the canonical command
|
|
379
|
+
endpoints while routing their local command IDs through `executeDebitAccount`,
|
|
380
|
+
`executeCreditAccount`, and `executeSettle`. These adapters consume the
|
|
381
|
+
memory-backed pipeline state directly and avoid an external self-call. The host
|
|
382
|
+
dispatcher must reject nonzero step value before invoking them because all three
|
|
383
|
+
commands are non-funded.
|
|
384
|
+
|
|
385
|
+
Positions also support backward-composed pipelines. In an exact-output route,
|
|
386
|
+
the asset side can represent the desired result while the liability side
|
|
387
|
+
represents the value currently required upstream. Each hop consumes one
|
|
388
|
+
position, fulfills or transforms its current requirement, and returns the next
|
|
389
|
+
position:
|
|
390
|
+
|
|
391
|
+
```txt
|
|
392
|
+
position(C, 100, C, 100)
|
|
393
|
+
→ position(C, 100, B, 50)
|
|
394
|
+
→ position(C, 100, A, 25)
|
|
395
|
+
→ settle
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
This is backward composition, not backward execution: `#step` blocks still
|
|
399
|
+
execute forward in their encoded order. Exact-output routing is only one use;
|
|
400
|
+
other commands may transform the asset side, the liability side, or both.
|
|
401
|
+
|
|
319
402
|
## Queries
|
|
320
403
|
|
|
321
404
|
Queries are the read endpoints: view functions that take a block-stream input
|
|
@@ -336,15 +419,15 @@ the descriptor's lanes through the published block schemas.
|
|
|
336
419
|
Ports are the host-to-host surfaces, callable only by trusted peer hosts. The two
|
|
337
420
|
central ones are batches all the way down:
|
|
338
421
|
|
|
339
|
-
- `
|
|
422
|
+
- `portPost` consumes `transaction { bytes32 from, bytes32 to, bytes32 asset,
|
|
340
423
|
uint amount }` blocks, debiting `from` and crediting `to` per
|
|
341
|
-
block — how two hosts
|
|
424
|
+
block — how two hosts post transactions between their ledgers.
|
|
342
425
|
- `portPipePayable` consumes `context` blocks, each carrying an account, an
|
|
343
426
|
initial state, and a run of steps — a complete pipeline delivered by another
|
|
344
427
|
host, executed locally against the port call's shared value budget.
|
|
345
428
|
|
|
346
|
-
This is also the cross-portal mechanism. `relayPayable
|
|
347
|
-
wraps a pipe and addresses it to a portal, commonly the destination host ID;
|
|
429
|
+
This is also the cross-portal mechanism. `relayPayable`, `relayBalancePayable`,
|
|
430
|
+
or `portDispatchPayable` wraps a pipe and addresses it to a portal, commonly the destination host ID;
|
|
348
431
|
a bridge adapter moves the **raw
|
|
349
432
|
bytes**; the destination host parses them with the same cursor rules and runs
|
|
350
433
|
the same pipeline loop. Nothing in the payload is EVM-specific — step commands
|
|
@@ -357,9 +440,9 @@ bytes and produce the same output bytes for every endpoint.
|
|
|
357
440
|
|
|
358
441
|
Admin commands use the regular command shape but are gated to the host's admin
|
|
359
442
|
account: trust management (`authorize`, `unauthorize`), guardian management
|
|
360
|
-
(`appoint`, `dismiss`), metadata (`
|
|
361
|
-
`
|
|
362
|
-
|
|
443
|
+
(`appoint`, `dismiss`), metadata (`annotate`), optional asset gating
|
|
444
|
+
(`allowAssets`, `denyAssets`, `allowance`), and raw calls (`executePayable`).
|
|
445
|
+
Guards go the other way: direct actions guardians can take
|
|
363
446
|
without any command context — the default is `revoke`, which lets a guardian
|
|
364
447
|
drop a trusted node immediately.
|
|
365
448
|
|
|
@@ -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
|
+
}
|