@rootzero/contracts 1.12.0 → 1.14.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 +76 -8
- package/Codec.sol +21 -0
- package/Commands.sol +14 -0
- package/Core.sol +4 -4
- package/Endpoints.sol +5 -7
- package/README.md +62 -35
- package/Utils.sol +2 -4
- package/codec/Blocks.sol +1606 -0
- package/codec/Buffers.sol +165 -0
- package/codec/Decoders.sol +558 -0
- package/codec/Descriptors.sol +124 -0
- package/{blocks → codec}/Keys.sol +4 -28
- package/codec/Readers.sol +114 -0
- package/{blocks → codec}/Schema.sol +38 -80
- package/codec/Specs.sol +218 -0
- package/codec/Writers.sol +487 -0
- package/commands/Allocate.sol +50 -0
- package/commands/Base.sol +71 -37
- package/commands/Burn.sol +19 -13
- package/commands/Credit.sol +25 -31
- package/commands/Debit.sol +28 -38
- package/commands/Deposit.sol +39 -39
- package/commands/Payout.sol +22 -15
- package/commands/Provision.sol +40 -40
- package/commands/Recover.sol +21 -20
- package/commands/Relay.sol +25 -23
- package/commands/Withdraw.sol +18 -20
- package/commands/admin/AllowAssets.sol +20 -16
- package/commands/admin/Allowance.sol +19 -13
- package/commands/admin/Appoint.sol +18 -15
- package/commands/admin/Authorize.sol +24 -14
- package/commands/admin/Base.sol +1 -1
- package/commands/admin/DenyAssets.sol +20 -16
- package/commands/admin/Dismiss.sol +18 -15
- package/commands/admin/Execute.sol +20 -18
- package/commands/admin/Label.sol +18 -13
- package/commands/admin/Schemas.sol +19 -14
- package/commands/admin/Unauthorize.sol +24 -14
- package/core/Calls.sol +7 -14
- package/core/Endpoint.sol +43 -126
- package/core/Host.sol +10 -2
- package/core/Pipeline.sol +29 -25
- package/core/Settlement.sol +39 -0
- package/core/Types.sol +1 -1
- package/docs/Schema.md +38 -32
- package/events/Endpoint.sol +2 -2
- package/events/Introduction.sol +4 -3
- package/events/Schema.sol +5 -5
- package/execution/Budget.sol +40 -0
- package/execution/Execution.sol +1083 -0
- package/guards/Base.sol +8 -9
- 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 +18 -11
- 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 +13 -13
- package/queries/Assets.sol +15 -15
- package/queries/Balances.sol +17 -17
- package/queries/Base.sol +11 -12
- package/utils/Actions.sol +1 -0
- package/utils/Cursors.sol +308 -0
- package/utils/Lanes.sol +14 -0
- package/utils/Selectors.sol +2 -2
- package/utils/Utils.sol +46 -0
- package/Cursors.sol +0 -16
- package/blocks/Cursors.sol +0 -1400
- package/blocks/Writers.sol +0 -1028
- package/core/Payable.sol +0 -53
- package/utils/Value.sol +0 -43
|
@@ -1,33 +1,36 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import { AdminBase,
|
|
5
|
-
|
|
6
|
-
using Cursors for Cur;
|
|
4
|
+
import { AdminBase, Execution, Executions, Lanes, Specs } from "./Base.sol";
|
|
5
|
+
using Executions for Execution;
|
|
7
6
|
|
|
8
7
|
/// @title Dismiss
|
|
9
8
|
/// @notice Admin command that revokes guardian status from a list of account IDs.
|
|
10
|
-
/// Each ACCOUNT block in the
|
|
9
|
+
/// Each ACCOUNT block in the input is disabled as a guardian on the host.
|
|
11
10
|
/// Only callable by the admin account.
|
|
12
11
|
abstract contract Dismiss is AdminBase {
|
|
13
|
-
|
|
12
|
+
uint private immutable descriptor;
|
|
14
13
|
|
|
15
14
|
constructor() {
|
|
16
|
-
(, descriptor) = command("dismiss",
|
|
15
|
+
(, descriptor) = command("dismiss", Specs.Empty, Specs.Account, Specs.Empty, 0, false, true);
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
/// @notice Dismiss each ACCOUNT block in the admin
|
|
20
|
-
/// @param
|
|
18
|
+
/// @notice Dismiss each ACCOUNT block in the admin input from guardian status.
|
|
19
|
+
/// @param input ACCOUNT block stream.
|
|
21
20
|
/// @return Empty output state.
|
|
21
|
+
/// @return Empty transaction stream.
|
|
22
22
|
function dismiss(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
bytes32 account,
|
|
24
|
+
bytes calldata,
|
|
25
|
+
bytes calldata input
|
|
26
|
+
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
27
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
26
28
|
|
|
27
|
-
while (
|
|
28
|
-
bytes32
|
|
29
|
-
setGuardian(
|
|
29
|
+
while (exec.more()) {
|
|
30
|
+
bytes32 guardian = exec.unpackAccount(Lanes.Input);
|
|
31
|
+
setGuardian(guardian, false);
|
|
30
32
|
}
|
|
31
|
-
|
|
33
|
+
|
|
34
|
+
return close(exec, account);
|
|
32
35
|
}
|
|
33
36
|
}
|
|
@@ -1,36 +1,38 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AdminBase,
|
|
5
|
-
import {Payable} from "../../core/Payable.sol";
|
|
6
|
-
import {Cursors, Cur} from "../../Cursors.sol";
|
|
7
|
-
import {Budget} from "../../utils/Value.sol";
|
|
4
|
+
import {AdminBase, Execution, Executions, Lanes, Specs} from "./Base.sol";
|
|
8
5
|
|
|
9
|
-
using
|
|
6
|
+
using Executions for Execution;
|
|
10
7
|
|
|
11
8
|
/// @title ExecutePayable
|
|
12
9
|
/// @notice Admin command that forwards raw calldata to one or more target nodes.
|
|
13
10
|
/// Each CALL block specifies a target node ID, packed resources, and raw calldata payload.
|
|
14
11
|
/// Only callable by the admin account.
|
|
15
|
-
/// Unspent top-level `msg.value`
|
|
16
|
-
abstract contract ExecutePayable is AdminBase
|
|
17
|
-
|
|
12
|
+
/// Unspent top-level `msg.value` is returned as a refund transaction.
|
|
13
|
+
abstract contract ExecutePayable is AdminBase {
|
|
14
|
+
uint private immutable descriptor;
|
|
18
15
|
|
|
19
16
|
constructor() {
|
|
20
|
-
(, descriptor) = command("executePayable",
|
|
17
|
+
(, descriptor) = command("executePayable", Specs.Empty, Specs.Call, Specs.Empty, 0, true, true);
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
/// @notice Execute each CALL block in the admin
|
|
24
|
-
/// @param
|
|
20
|
+
/// @notice Execute each CALL block in the admin input.
|
|
21
|
+
/// @param input CALL block stream.
|
|
25
22
|
/// @return Empty output state.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
/// @return Remaining native value as a refund transaction stream.
|
|
24
|
+
function executePayable(
|
|
25
|
+
bytes32 account,
|
|
26
|
+
bytes calldata,
|
|
27
|
+
bytes calldata input
|
|
28
|
+
) external payable onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
29
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
29
30
|
|
|
30
|
-
while (
|
|
31
|
-
(uint target, uint resources, bytes calldata data) =
|
|
32
|
-
rawCall(target, useValue(
|
|
31
|
+
while (exec.more()) {
|
|
32
|
+
(uint target, uint resources, bytes calldata data) = exec.unpackCall(Lanes.Input);
|
|
33
|
+
rawCall(target, exec.useValue(resources), data);
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
|
|
36
|
+
return close(exec, account);
|
|
35
37
|
}
|
|
36
38
|
}
|
package/commands/admin/Label.sol
CHANGED
|
@@ -1,31 +1,36 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AdminBase,
|
|
5
|
-
|
|
6
|
-
using Cursors for Cur;
|
|
4
|
+
import {AdminBase, Execution, Executions, Lanes, Specs} from "./Base.sol";
|
|
5
|
+
using Executions for Execution;
|
|
7
6
|
|
|
8
7
|
/// @title Label
|
|
9
8
|
/// @notice Admin command that publishes namespaced labels for node IDs.
|
|
10
|
-
/// Each LABEL block in the
|
|
9
|
+
/// Each LABEL block in the input emits one `Labeled` event. Only callable by
|
|
11
10
|
/// the admin account.
|
|
12
11
|
abstract contract Label is AdminBase {
|
|
13
|
-
|
|
12
|
+
uint private immutable descriptor;
|
|
14
13
|
|
|
15
14
|
constructor() {
|
|
16
|
-
(, descriptor) = command("label",
|
|
15
|
+
(, descriptor) = command("label", Specs.Empty, Specs.Label, Specs.Empty, 0, false, true);
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
/// @notice Publish each LABEL block in the admin
|
|
20
|
-
/// @param
|
|
18
|
+
/// @notice Publish each LABEL block in the admin input.
|
|
19
|
+
/// @param input LABEL block stream.
|
|
21
20
|
/// @return Empty output state.
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
/// @return Empty transaction stream.
|
|
22
|
+
function label(
|
|
23
|
+
bytes32 account,
|
|
24
|
+
bytes calldata,
|
|
25
|
+
bytes calldata input
|
|
26
|
+
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
27
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
24
28
|
|
|
25
|
-
while (
|
|
26
|
-
(uint node, bytes32 namespace, string memory name) =
|
|
29
|
+
while (exec.more()) {
|
|
30
|
+
(uint node, bytes32 namespace, string memory name) = exec.unpackLabel(Lanes.Input);
|
|
27
31
|
emit Labeled(node, namespace, name);
|
|
28
32
|
}
|
|
29
|
-
|
|
33
|
+
|
|
34
|
+
return close(exec, account);
|
|
30
35
|
}
|
|
31
36
|
}
|
|
@@ -1,31 +1,36 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AdminBase,
|
|
5
|
-
|
|
6
|
-
using Cursors for Cur;
|
|
4
|
+
import {AdminBase, Execution, Executions, Lanes, Specs} from "./Base.sol";
|
|
5
|
+
using Executions for Execution;
|
|
7
6
|
|
|
8
7
|
/// @title PublishSchema
|
|
9
8
|
/// @notice Admin command that publishes block schemas for keys.
|
|
10
|
-
/// Each SCHEMA block in the
|
|
9
|
+
/// Each SCHEMA block in the input emits one `Schema` event. Only callable by
|
|
11
10
|
/// the admin account.
|
|
12
11
|
abstract contract PublishSchema is AdminBase {
|
|
13
|
-
|
|
12
|
+
uint private immutable descriptor;
|
|
14
13
|
|
|
15
14
|
constructor() {
|
|
16
|
-
(, descriptor) = command("publishSchema",
|
|
15
|
+
(, descriptor) = command("publishSchema", Specs.Empty, Specs.Schema, Specs.Empty, 0, false, true);
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
/// @notice Publish each SCHEMA block in the admin
|
|
20
|
-
/// @param
|
|
18
|
+
/// @notice Publish each SCHEMA block in the admin input.
|
|
19
|
+
/// @param input SCHEMA block stream.
|
|
21
20
|
/// @return Empty output state.
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
/// @return Empty transaction stream.
|
|
22
|
+
function publishSchema(
|
|
23
|
+
bytes32 account,
|
|
24
|
+
bytes calldata,
|
|
25
|
+
bytes calldata input
|
|
26
|
+
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
27
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
24
28
|
|
|
25
|
-
while (
|
|
26
|
-
(
|
|
27
|
-
emit Schema(host,
|
|
29
|
+
while (exec.more()) {
|
|
30
|
+
(uint spec, string memory body, bytes32 name) = exec.unpackSchema(Lanes.Input);
|
|
31
|
+
emit Schema(host, spec, body, name);
|
|
28
32
|
}
|
|
29
|
-
|
|
33
|
+
|
|
34
|
+
return close(exec, account);
|
|
30
35
|
}
|
|
31
36
|
}
|
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AdminBase,
|
|
5
|
-
|
|
6
|
-
using Cursors for Cur;
|
|
4
|
+
import {AdminBase, Execution, Executions, Lanes, Specs} from "./Base.sol";
|
|
5
|
+
using Executions for Execution;
|
|
7
6
|
|
|
8
7
|
/// @title Unauthorize
|
|
9
8
|
/// @notice Admin command that revokes authorization from a list of node IDs.
|
|
10
|
-
/// Each NODE block in the
|
|
9
|
+
/// Each NODE block in the input is deauthorized on the host.
|
|
11
10
|
/// Only callable by the admin account.
|
|
12
11
|
abstract contract Unauthorize is AdminBase {
|
|
13
|
-
|
|
14
|
-
uint
|
|
12
|
+
uint private immutable descriptor;
|
|
13
|
+
uint private immutable id;
|
|
15
14
|
|
|
16
15
|
constructor() {
|
|
17
|
-
(
|
|
16
|
+
(id, descriptor) = command("unauthorize", Specs.Empty, Specs.Node, Specs.Empty, 0, false, true);
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
/// @notice
|
|
21
|
-
|
|
19
|
+
/// @notice Return the registered UNAUTHORIZE command ID.
|
|
20
|
+
function unauthorizeId() internal view returns (uint) {
|
|
21
|
+
return id;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// @notice Unauthorize each NODE block in the admin input.
|
|
25
|
+
/// @param input NODE block stream.
|
|
22
26
|
/// @return Empty output state.
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
/// @return Empty transaction stream.
|
|
28
|
+
function unauthorize(
|
|
29
|
+
bytes32 account,
|
|
30
|
+
bytes calldata,
|
|
31
|
+
bytes calldata input
|
|
32
|
+
) external onlyAdmin(account) returns (bytes memory, bytes memory) {
|
|
33
|
+
Execution memory exec = openInput(input, descriptor, 0);
|
|
25
34
|
|
|
26
|
-
while (
|
|
27
|
-
uint node =
|
|
35
|
+
while (exec.more()) {
|
|
36
|
+
uint node = exec.unpackNode(Lanes.Input);
|
|
28
37
|
setNode(node, false);
|
|
29
38
|
}
|
|
30
|
-
|
|
39
|
+
|
|
40
|
+
return close(exec, account);
|
|
31
41
|
}
|
|
32
42
|
}
|
package/core/Calls.sol
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {AccessControl} from "./Access.sol";
|
|
5
|
-
import {CommandContext} from "../commands/Base.sol";
|
|
6
5
|
import {Nodes} from "../utils/Nodes.sol";
|
|
7
6
|
|
|
8
7
|
/// @dev Emitted when a trusted inter-node call fails.
|
|
@@ -14,13 +13,6 @@ error FailedCall(address addr, bytes4 selector, bytes err);
|
|
|
14
13
|
/// @title NodeCalls
|
|
15
14
|
/// @notice Shared low-level inter-node call helpers for contracts that can talk to other nodes.
|
|
16
15
|
abstract contract NodeCalls is AccessControl {
|
|
17
|
-
/// @notice Return the host node ID corresponding to the current caller.
|
|
18
|
-
/// @dev Encodes `msg.sender` as a host ID using the local-chain host layout.
|
|
19
|
-
/// @return Host node ID for `msg.sender`.
|
|
20
|
-
function caller() internal view returns (uint) {
|
|
21
|
-
return Nodes.toHost(msg.sender);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
16
|
/// @notice Try a raw low-level call to another node and return whether it succeeded.
|
|
25
17
|
/// @param node Node ID of the callee.
|
|
26
18
|
/// @param value Native value to forward in wei.
|
|
@@ -89,18 +81,19 @@ abstract contract CommandCalls is NodeCalls {
|
|
|
89
81
|
/// @param value Native value to forward in wei.
|
|
90
82
|
/// @param account Command account identifier.
|
|
91
83
|
/// @param state Current command state block stream.
|
|
92
|
-
/// @param
|
|
93
|
-
/// @return Decoded command output block stream.
|
|
84
|
+
/// @param input Command input block stream.
|
|
85
|
+
/// @return nextState Decoded command output state block stream.
|
|
86
|
+
/// @return transactions Decoded command transaction block stream.
|
|
94
87
|
function callCommand(
|
|
95
88
|
uint command,
|
|
96
89
|
uint128 value,
|
|
97
90
|
bytes32 account,
|
|
98
91
|
bytes memory state,
|
|
99
|
-
bytes calldata
|
|
100
|
-
) internal returns (bytes memory) {
|
|
92
|
+
bytes calldata input
|
|
93
|
+
) internal returns (bytes memory nextState, bytes memory transactions) {
|
|
101
94
|
bytes4 selector = Nodes.commandSelector(command);
|
|
102
|
-
bytes memory data = abi.encodeWithSelector(selector,
|
|
103
|
-
return abi.decode(trustedCall(command, value, data), (bytes));
|
|
95
|
+
bytes memory data = abi.encodeWithSelector(selector, account, state, input);
|
|
96
|
+
return abi.decode(trustedCall(command, value, data), (bytes, bytes));
|
|
104
97
|
}
|
|
105
98
|
}
|
|
106
99
|
|
package/core/Endpoint.sol
CHANGED
|
@@ -1,159 +1,76 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import {Specs} from "../codec/Specs.sol";
|
|
5
|
+
import {Execution, Executions} from "../execution/Execution.sol";
|
|
6
6
|
import {EndpointEvent} from "../events/Endpoint.sol";
|
|
7
7
|
import {LabeledEvent} from "../events/Labeled.sol";
|
|
8
8
|
import {SchemaEvent} from "../events/Schema.sol";
|
|
9
|
+
import {Descriptors} from "../codec/Descriptors.sol";
|
|
9
10
|
import {Runtime} from "./Runtime.sol";
|
|
10
11
|
|
|
11
|
-
/// @title Lane
|
|
12
|
-
/// @notice Bit offsets for endpoint descriptor lanes.
|
|
13
|
-
library Lane {
|
|
14
|
-
/// @dev Descriptor shift for the state lane.
|
|
15
|
-
uint internal constant State = 184;
|
|
16
|
-
/// @dev Descriptor shift for the input lane.
|
|
17
|
-
uint internal constant Input = 112;
|
|
18
|
-
/// @dev Descriptor shift for the output lane.
|
|
19
|
-
uint internal constant Output = 40;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
12
|
/// @title EndpointBase
|
|
23
13
|
/// @notice Shared endpoint metadata helpers.
|
|
24
14
|
abstract contract EndpointBase is Runtime, EndpointEvent, LabeledEvent, SchemaEvent {
|
|
25
|
-
/// @
|
|
26
|
-
/// A non-empty lane with group 0 defaults to group 1; a zero lane is absent.
|
|
27
|
-
/// Layout: `[state:8][group:1][input:8][group:1][output:8][group:1]`
|
|
28
|
-
/// `[flags:1][reserved:4]`. Flag bits: funded = 0, admin = 1.
|
|
29
|
-
/// @param state Packed state lane plus optional group byte.
|
|
30
|
-
/// @param input Packed input lane plus optional group byte.
|
|
31
|
-
/// @param output Packed output lane plus optional group byte.
|
|
32
|
-
/// @param funded Whether the endpoint accepts nonzero native value.
|
|
33
|
-
/// @param admin Whether the endpoint is restricted to the admin account.
|
|
34
|
-
/// @return value Packed endpoint descriptor as an integer.
|
|
35
|
-
function pack(
|
|
36
|
-
bytes9 state,
|
|
37
|
-
bytes9 input,
|
|
38
|
-
bytes9 output,
|
|
39
|
-
bool funded,
|
|
40
|
-
bool admin
|
|
41
|
-
) private pure returns (uint value) {
|
|
42
|
-
value |= uint(uint72(state)) << Lane.State;
|
|
43
|
-
value |= uint(uint72(input)) << Lane.Input;
|
|
44
|
-
value |= uint(uint72(output)) << Lane.Output;
|
|
45
|
-
value |= uint(funded ? 1 : 0) << 32;
|
|
46
|
-
value |= uint(admin ? 1 : 0) << 33;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/// @dev Return a lane's effective group size, defaulting non-empty lanes to one.
|
|
50
|
-
/// @param descriptor Packed endpoint descriptor.
|
|
51
|
-
/// @param shift Bit offset of the lane to inspect.
|
|
52
|
-
/// @return size Effective group size, or zero when the lane is absent.
|
|
53
|
-
function laneGroup(bytes32 descriptor, uint shift) private pure returns (uint8 size) {
|
|
54
|
-
uint72 lane = uint72(uint(descriptor) >> shift);
|
|
55
|
-
if (lane == 0) return 0;
|
|
56
|
-
|
|
57
|
-
size = uint8(lane);
|
|
58
|
-
if (size == 0) size = 1;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/// @notice Return an 8-byte lane value for a generic LIST containing `item`.
|
|
62
|
-
/// @param item Block key expected inside each LIST payload.
|
|
63
|
-
/// @return Packed lane key `[Keys.List][item]`.
|
|
64
|
-
function many(bytes4 item) internal pure returns (bytes8) {
|
|
65
|
-
return bytes8(bytes.concat(Keys.List, item));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/// @notice Append an explicit group size to an 8-byte lane value.
|
|
69
|
-
/// @param value Packed lane key `[key][item]`.
|
|
70
|
-
/// @param size Explicit per-operation group size for the lane.
|
|
71
|
-
/// @return Packed lane key plus group byte.
|
|
72
|
-
function group(bytes8 value, uint8 size) internal pure returns (bytes9) {
|
|
73
|
-
return bytes9(bytes.concat(value, bytes1(size)));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/// @dev Open a descriptor lane and return its effective group and output counts.
|
|
77
|
-
/// An absent lane inherits `expected`; a present lane must match it when nonzero.
|
|
78
|
-
/// @param source Block stream to open for the requested lane.
|
|
79
|
-
/// @param descriptor Packed endpoint descriptor.
|
|
80
|
-
/// @param shift Bit offset of the lane to open.
|
|
81
|
-
/// @param expected Required group count, or zero to accept the lane's count.
|
|
82
|
-
/// @return cur Cursor scoped to the lane's first block run.
|
|
83
|
-
/// @return groups Number of lane groups in `cur`, or `expected` for an absent lane.
|
|
84
|
-
/// @return outputs Number of output blocks implied by `groups` and the descriptor output lane.
|
|
85
|
-
function openLane(
|
|
86
|
-
bytes calldata source,
|
|
87
|
-
bytes32 descriptor,
|
|
88
|
-
uint shift,
|
|
89
|
-
uint expected
|
|
90
|
-
) internal pure returns (Cur memory cur, uint groups, uint outputs) {
|
|
91
|
-
(cur, groups) = Cursors.init(source, laneGroup(descriptor, shift));
|
|
92
|
-
if (groups == 0) groups = expected;
|
|
93
|
-
else if (expected != 0 && groups != expected) revert Cursors.BadRatio();
|
|
94
|
-
outputs = groups * laneGroup(descriptor, Lane.Output);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/// @notice Open an endpoint state stream and return the expected output block count.
|
|
98
|
-
/// @param source State block stream to open.
|
|
99
|
-
/// @param descriptor Packed endpoint descriptor.
|
|
100
|
-
/// @return state Cursor scoped to the state lane's first block run.
|
|
101
|
-
/// @return outputs Number of output blocks implied by the state group count.
|
|
102
|
-
function openState(
|
|
103
|
-
bytes calldata source,
|
|
104
|
-
bytes32 descriptor
|
|
105
|
-
) internal pure returns (Cur memory state, uint outputs) {
|
|
106
|
-
(state, , outputs) = openLane(source, descriptor, Lane.State, 0);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/// @notice Open an endpoint input stream and return the expected output block count.
|
|
15
|
+
/// @notice Open an endpoint input stream with an expected batch count.
|
|
110
16
|
/// @param source Input block stream to open.
|
|
111
17
|
/// @param descriptor Packed endpoint descriptor.
|
|
112
|
-
/// @
|
|
113
|
-
/// @return
|
|
18
|
+
/// @param batches Required batch count, or zero to accept the input count.
|
|
19
|
+
/// @return exec Execution with its output buffer metadata initialized for the input batch count.
|
|
114
20
|
function openInput(
|
|
115
21
|
bytes calldata source,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
22
|
+
uint descriptor,
|
|
23
|
+
uint batches
|
|
24
|
+
) internal view returns (Execution memory exec) {
|
|
25
|
+
return Executions.openInput(source, descriptor, batches);
|
|
119
26
|
}
|
|
120
27
|
|
|
121
|
-
/// @notice
|
|
122
|
-
/// @param
|
|
123
|
-
/// @return
|
|
124
|
-
function
|
|
125
|
-
return
|
|
28
|
+
/// @notice Finalize an execution output and return its encoded block stream.
|
|
29
|
+
/// @param exec Completed endpoint execution.
|
|
30
|
+
/// @return Encoded output block stream.
|
|
31
|
+
function close(Execution memory exec) internal pure returns (bytes memory) {
|
|
32
|
+
return Executions.finish(exec);
|
|
126
33
|
}
|
|
127
34
|
|
|
128
|
-
/// @notice
|
|
35
|
+
/// @notice Construct and publish a context-local block specification.
|
|
129
36
|
/// @param key Context-local key value.
|
|
37
|
+
/// @param min Minimum accepted payload length.
|
|
38
|
+
/// @param max Maximum accepted payload length; zero means unbounded.
|
|
39
|
+
/// @param hint Initial per-block payload capacity.
|
|
130
40
|
/// @param body Schema DSL string describing the block payload body.
|
|
131
|
-
/// @
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
41
|
+
/// @param name Schema alias name, or zero for unnamed schemas.
|
|
42
|
+
/// @return spec The context-local block specification.
|
|
43
|
+
function schema(
|
|
44
|
+
uint32 key,
|
|
45
|
+
uint32 min,
|
|
46
|
+
uint32 max,
|
|
47
|
+
uint32 hint,
|
|
48
|
+
string memory body,
|
|
49
|
+
bytes32 name
|
|
50
|
+
) internal returns (uint spec) {
|
|
51
|
+
spec = Specs.create(bytes4(key), min, max, hint);
|
|
52
|
+
emit Schema(host, spec, body, name);
|
|
136
53
|
}
|
|
137
54
|
|
|
138
55
|
/// @notice Create and publish endpoint metadata with a default label.
|
|
139
56
|
/// @param id Endpoint node ID.
|
|
140
57
|
/// @param name Default human-readable endpoint label.
|
|
141
|
-
/// @param state
|
|
142
|
-
/// @param input
|
|
143
|
-
/// @param output
|
|
144
|
-
/// @param
|
|
145
|
-
/// @param
|
|
58
|
+
/// @param state State block specification.
|
|
59
|
+
/// @param input Input block specification.
|
|
60
|
+
/// @param output Output block specification.
|
|
61
|
+
/// @param transactions Number of transaction blocks produced per batch, or zero for none.
|
|
62
|
+
/// @param flags Packed endpoint behavior flags.
|
|
146
63
|
/// @return descriptor Packed endpoint lane metadata and flags.
|
|
147
64
|
function endpoint(
|
|
148
65
|
uint id,
|
|
149
66
|
string memory name,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
) internal returns (
|
|
156
|
-
descriptor =
|
|
67
|
+
uint state,
|
|
68
|
+
uint input,
|
|
69
|
+
uint output,
|
|
70
|
+
uint8 transactions,
|
|
71
|
+
uint8 flags
|
|
72
|
+
) internal returns (uint descriptor) {
|
|
73
|
+
descriptor = Descriptors.create(state, input, output, transactions, flags);
|
|
157
74
|
emit Endpoint(host, id, descriptor);
|
|
158
75
|
emit Labeled(id, bytes32(0), name);
|
|
159
76
|
}
|
package/core/Host.sol
CHANGED
|
@@ -43,7 +43,15 @@ abstract contract Host is
|
|
|
43
43
|
/// on it during construction.
|
|
44
44
|
constructor(address cmdr) AccessControl(cmdr) {
|
|
45
45
|
if (cmdr == address(0) || cmdr == address(this) || cmdr.code.length == 0) return;
|
|
46
|
-
|
|
46
|
+
introduceTo(Nodes.toHost(cmdr));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// @notice Introduce this host to the contract address embedded in a local EVM node ID.
|
|
50
|
+
/// @dev Accepts host and endpoint IDs such as commands, ports, queries, and guards.
|
|
51
|
+
/// Reverts when `node` is not local or embeds the zero address.
|
|
52
|
+
/// @param node Local EVM node ID whose underlying contract receives the introduction.
|
|
53
|
+
function introduceTo(uint node) internal {
|
|
54
|
+
IHostIntroduction(Nodes.addr(node)).introduce(host, block.number);
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
/// @notice Record a host introduction claim.
|
|
@@ -51,7 +59,7 @@ abstract contract Host is
|
|
|
51
59
|
/// @param peer Host node ID being introduced.
|
|
52
60
|
/// @param blocknum Block number at which the host was deployed.
|
|
53
61
|
function introduce(uint peer, uint blocknum) external {
|
|
54
|
-
emit Introduction(Nodes.matchHost(peer, msg.sender), blocknum);
|
|
62
|
+
emit Introduction(host, Nodes.matchHost(peer, msg.sender), blocknum);
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
/// @notice Accept native ETH transfers (e.g. from command value flows).
|
package/core/Pipeline.sol
CHANGED
|
@@ -1,34 +1,38 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {Budget} from "../
|
|
4
|
+
import {Decoders, Cur, Readers, Reader} from "../Codec.sol";
|
|
5
|
+
import {Settlement} from "./Settlement.sol";
|
|
6
|
+
import {Budget, Budgets} from "../execution/Budget.sol";
|
|
7
7
|
|
|
8
|
-
using
|
|
8
|
+
using Decoders for Cur;
|
|
9
|
+
using Readers for Reader;
|
|
10
|
+
using Budgets for Budget;
|
|
9
11
|
|
|
10
12
|
/// @title Pipeline
|
|
11
13
|
/// @notice Core pipeline functionality shared by higher-level surfaces.
|
|
12
|
-
abstract contract Pipeline is
|
|
14
|
+
abstract contract Pipeline is Settlement {
|
|
13
15
|
/// @dev Thrown when the pipeline finishes with non-empty threaded state.
|
|
14
16
|
error UnexpectedState();
|
|
15
17
|
|
|
16
18
|
/// @notice Override to dispatch one piped step.
|
|
17
|
-
/// Called once per STEP block. The returned
|
|
18
|
-
/// the next step, and the final returned state must be empty.
|
|
19
|
-
///
|
|
19
|
+
/// Called once per STEP block. The returned state becomes the state passed to
|
|
20
|
+
/// the next step, and the final returned state must be empty. Returned
|
|
21
|
+
/// transactions are decoded and passed individually to `settle` before the next step runs.
|
|
22
|
+
/// @param cmd Command node ID to invoke or handle.
|
|
20
23
|
/// @param account Account identifier for the piped context.
|
|
21
24
|
/// @param state Current threaded state block stream.
|
|
22
|
-
/// @param
|
|
25
|
+
/// @param input Step input block stream.
|
|
23
26
|
/// @param value Native EVM value assigned to this step.
|
|
24
|
-
/// @return Updated state block stream for the next step.
|
|
27
|
+
/// @return output Updated state block stream for the next step.
|
|
28
|
+
/// @return transactions Transaction block stream produced by the command.
|
|
25
29
|
function dispatch(
|
|
26
|
-
uint
|
|
30
|
+
uint cmd,
|
|
27
31
|
bytes32 account,
|
|
28
32
|
bytes memory state,
|
|
29
|
-
bytes calldata
|
|
33
|
+
bytes calldata input,
|
|
30
34
|
uint128 value
|
|
31
|
-
) internal virtual returns (bytes memory);
|
|
35
|
+
) internal virtual returns (bytes memory output, bytes memory transactions);
|
|
32
36
|
|
|
33
37
|
/// @notice Execute a STEP block stream through the pipeline.
|
|
34
38
|
/// @dev Reverts with `UnexpectedState` if the final threaded state is non-empty.
|
|
@@ -37,20 +41,20 @@ abstract contract Pipeline is Payable {
|
|
|
37
41
|
/// @param state Initial state block stream passed to the first step.
|
|
38
42
|
/// @param steps STEP block stream to execute.
|
|
39
43
|
/// @param budget Mutable native-value budget shared across all steps.
|
|
40
|
-
function pipe(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
function pipe(bytes32 account, bytes memory state, bytes calldata steps, Budget memory budget) internal {
|
|
45
|
+
Cur memory cur = Decoders.open(steps, 1);
|
|
46
|
+
|
|
47
|
+
while (cur.more()) {
|
|
48
|
+
(uint cmd, uint resources, bytes calldata input) = cur.unpackStep();
|
|
49
|
+
Reader memory txs;
|
|
50
|
+
(state, txs.source) = dispatch(cmd, account, state, input, budget.use(resources));
|
|
51
|
+
|
|
52
|
+
while (txs.more()) {
|
|
53
|
+
(bytes32 from, bytes32 to, bytes32 asset, uint amount) = txs.unpackTransaction();
|
|
54
|
+
settle(from, to, asset, amount);
|
|
55
|
+
}
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
if (state.length != 0) revert UnexpectedState();
|
|
54
|
-
input.complete();
|
|
55
59
|
}
|
|
56
60
|
}
|