@rootzero/contracts 1.6.0 → 1.8.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 +54 -1
- package/Core.sol +1 -1
- package/Endpoints.sol +15 -15
- package/Events.sol +2 -1
- package/README.md +9 -9
- package/blocks/Cursors.sol +36 -49
- package/blocks/Keys.sol +5 -5
- package/blocks/Schema.sol +4 -2
- package/blocks/Writers.sol +0 -35
- package/commands/Deposit.sol +2 -2
- package/commands/Provision.sol +2 -2
- package/commands/Recover.sol +48 -0
- package/commands/Relay.sol +4 -4
- package/commands/admin/Execute.sol +2 -4
- package/core/Calls.sol +74 -38
- package/core/Commitments.sol +1 -1
- package/core/Payable.sol +15 -28
- package/core/Pipeline.sol +1 -1
- package/docs/Schema.md +13 -2
- package/events/Commitment.sol +4 -4
- package/events/Dispatch.sol +20 -0
- package/events/Port.sol +22 -0
- package/guards/Base.sol +0 -11
- package/package.json +1 -1
- package/ports/AllowAssets.sol +40 -0
- package/ports/Allowance.sol +37 -0
- package/ports/Base.sol +30 -0
- package/ports/Credit.sol +35 -0
- package/ports/Debit.sol +35 -0
- package/ports/DenyAssets.sol +40 -0
- package/{peer → ports}/Dispatch.sol +11 -15
- package/ports/Pipe.sol +39 -0
- package/{peer → ports}/Redeem.sol +11 -15
- package/ports/Settle.sol +37 -0
- package/queries/Base.sol +0 -11
- package/utils/Layout.sol +3 -3
- package/utils/Nodes.sol +21 -21
- package/utils/Value.sol +12 -5
- package/events/Peer.sol +0 -22
- package/peer/AllowAssets.sol +0 -44
- package/peer/Allowance.sol +0 -41
- package/peer/Base.sol +0 -41
- package/peer/Credit.sol +0 -39
- package/peer/Debit.sol +0 -39
- package/peer/DenyAssets.sol +0 -44
- package/peer/Pipe.sol +0 -44
- package/peer/Recover.sol +0 -51
- package/peer/Settle.sol +0 -41
package/ports/Pipe.sol
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {PortBase} from "./Base.sol";
|
|
5
|
+
import {Pipeline} from "../core/Pipeline.sol";
|
|
6
|
+
import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
7
|
+
import {Budget} from "../utils/Value.sol";
|
|
8
|
+
|
|
9
|
+
using Cursors for Cur;
|
|
10
|
+
|
|
11
|
+
/// @title PortPipePayable
|
|
12
|
+
/// @notice Port that consumes CONTEXT blocks and executes each request as a step stream.
|
|
13
|
+
/// Each context's request bytes are passed to the shared pipeline.
|
|
14
|
+
abstract contract PortPipePayable is PortBase, Pipeline {
|
|
15
|
+
uint internal immutable portPipePayableId = portId(this.portPipePayable.selector);
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
emit Port(host, portPipePayableId, "1:0", Schemas.Context, "", true);
|
|
19
|
+
emit Labeled(portPipePayableId, bytes32(0), "portPipePayable");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// @notice Execute peer-supplied contexts through the shared payable pipe.
|
|
23
|
+
/// @dev All contexts share the peer call's native-value budget. Any unspent
|
|
24
|
+
/// `msg.value` remains on this host.
|
|
25
|
+
/// @param data CONTEXT block stream supplied by the trusted peer.
|
|
26
|
+
/// @return Empty response bytes.
|
|
27
|
+
function portPipePayable(bytes calldata data) external payable onlyPeer returns (bytes memory) {
|
|
28
|
+
(Cur memory input, , ) = Cursors.init(data, 1);
|
|
29
|
+
Budget memory budget = openValue();
|
|
30
|
+
|
|
31
|
+
while (input.i < input.len) {
|
|
32
|
+
(bytes32 account, bytes calldata state, bytes calldata request) = input.unpackContext();
|
|
33
|
+
pipe(account, state, request, budget);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
input.complete();
|
|
37
|
+
return "";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {PortBase} from "./Base.sol";
|
|
5
5
|
import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
6
6
|
|
|
7
7
|
using Cursors for Cur;
|
|
8
8
|
|
|
9
|
-
interface IPeerRedeemBalance {
|
|
10
|
-
function peerRedeemBalance(bytes calldata request) external returns (bytes memory);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
9
|
abstract contract RedeemBalanceHook {
|
|
14
10
|
/// @notice Override to redeem one balance claim from a peer host into local assets.
|
|
15
11
|
/// @param peer Peer host node ID for this request.
|
|
@@ -18,23 +14,23 @@ abstract contract RedeemBalanceHook {
|
|
|
18
14
|
function redeemBalance(uint peer, bytes32 asset, uint amount) internal virtual;
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
/// @title
|
|
22
|
-
/// @notice
|
|
17
|
+
/// @title PortRedeemBalance
|
|
18
|
+
/// @notice Port that redeems balance state from a peer host into local assets.
|
|
23
19
|
/// Each BALANCE block in the request calls `redeemBalance(peer, asset, amount)`.
|
|
24
20
|
/// Restricted to trusted peers.
|
|
25
|
-
abstract contract
|
|
26
|
-
uint internal immutable
|
|
21
|
+
abstract contract PortRedeemBalance is PortBase, RedeemBalanceHook {
|
|
22
|
+
uint internal immutable portRedeemBalanceId = portId(this.portRedeemBalance.selector);
|
|
27
23
|
|
|
28
24
|
constructor() {
|
|
29
|
-
emit
|
|
30
|
-
emit Labeled(
|
|
25
|
+
emit Port(host, portRedeemBalanceId, "1:0", Schemas.Balance, "", false);
|
|
26
|
+
emit Labeled(portRedeemBalanceId, bytes32(0), "portRedeemBalance");
|
|
31
27
|
}
|
|
32
28
|
|
|
33
|
-
/// @notice Execute the balance redemption
|
|
34
|
-
/// @param
|
|
29
|
+
/// @notice Execute the balance redemption port call.
|
|
30
|
+
/// @param data BALANCE block stream supplied by the trusted peer.
|
|
35
31
|
/// @return Empty response bytes.
|
|
36
|
-
function
|
|
37
|
-
(Cur memory input, , ) = Cursors.init(
|
|
32
|
+
function portRedeemBalance(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
33
|
+
(Cur memory input, , ) = Cursors.init(data, 1);
|
|
38
34
|
uint peer = caller();
|
|
39
35
|
|
|
40
36
|
while (input.i < input.len) {
|
package/ports/Settle.sol
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import { PortBase } from "./Base.sol";
|
|
5
|
+
import { CreditAccountHook } from "../commands/Credit.sol";
|
|
6
|
+
import { DebitAccountHook } from "../commands/Debit.sol";
|
|
7
|
+
import { Cursors, Cur, Schemas } from "../Cursors.sol";
|
|
8
|
+
|
|
9
|
+
using Cursors for Cur;
|
|
10
|
+
|
|
11
|
+
/// @title PortSettle
|
|
12
|
+
/// @notice Port that consumes peer-supplied TRANSACTION blocks through debit and credit hooks.
|
|
13
|
+
/// Each TRANSACTION block calls `debitAccount` for `from` and `creditAccount` for `to`.
|
|
14
|
+
abstract contract PortSettle is PortBase, DebitAccountHook, CreditAccountHook {
|
|
15
|
+
uint internal immutable portSettleId = portId(this.portSettle.selector);
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
emit Port(host, portSettleId, "1:0", Schemas.Transaction, "", false);
|
|
19
|
+
emit Labeled(portSettleId, bytes32(0), "portSettle");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// @notice Execute the port-settle call.
|
|
23
|
+
/// @param data TRANSACTION block stream supplied by the trusted peer.
|
|
24
|
+
/// @return Empty response bytes.
|
|
25
|
+
function portSettle(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
26
|
+
(Cur memory state, , ) = Cursors.init(data, 1);
|
|
27
|
+
|
|
28
|
+
while (state.i < state.len) {
|
|
29
|
+
(bytes32 from, bytes32 to, bytes32 asset, uint amount) = state.unpackTransaction();
|
|
30
|
+
if (from != 0) debitAccount(from, asset, amount);
|
|
31
|
+
if (to != 0) creditAccount(to, asset, amount);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
state.complete();
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
}
|
package/queries/Base.sol
CHANGED
|
@@ -6,17 +6,6 @@ import { LabeledEvent } from "../events/Labeled.sol";
|
|
|
6
6
|
import { QueryEvent } from "../events/Query.sol";
|
|
7
7
|
import { Nodes } from "../utils/Nodes.sol";
|
|
8
8
|
|
|
9
|
-
/// @notice ABI-encode a query call from a target query ID and request block stream.
|
|
10
|
-
/// @dev Derives the function selector from `target` via `Nodes.querySelector(target)`.
|
|
11
|
-
/// Reverts if `target` is not a valid query ID.
|
|
12
|
-
/// @param target Destination query node ID embedding the target selector.
|
|
13
|
-
/// @param request Input block stream for the query invocation.
|
|
14
|
-
/// @return ABI-encoded calldata for the query entry point.
|
|
15
|
-
function encodeQueryCall(uint target, bytes calldata request) pure returns (bytes memory) {
|
|
16
|
-
bytes4 selector = Nodes.querySelector(target);
|
|
17
|
-
return abi.encodeWithSelector(selector, request);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
9
|
/// @title QueryBase
|
|
21
10
|
/// @notice Abstract base for rootzero query contracts.
|
|
22
11
|
/// Queries are view-only entry points that consume a block-stream request and
|
package/utils/Layout.sol
CHANGED
|
@@ -29,7 +29,7 @@ library Layout {
|
|
|
29
29
|
|
|
30
30
|
/// @dev ID encodes an account.
|
|
31
31
|
uint8 constant Account = 0x01;
|
|
32
|
-
/// @dev ID encodes a network node (host, command, or
|
|
32
|
+
/// @dev ID encodes a network node (host, command, port, query, or guard).
|
|
33
33
|
uint8 constant Node = 0x02;
|
|
34
34
|
/// @dev ID encodes an asset.
|
|
35
35
|
uint8 constant Asset = 0x03;
|
|
@@ -54,8 +54,8 @@ library Layout {
|
|
|
54
54
|
uint8 constant Host = 0x02;
|
|
55
55
|
/// @dev Node is a command contract.
|
|
56
56
|
uint8 constant Command = 0x03;
|
|
57
|
-
/// @dev Node is a peer
|
|
58
|
-
uint8 constant
|
|
57
|
+
/// @dev Node is a port callable by trusted peer hosts.
|
|
58
|
+
uint8 constant Port = 0x04;
|
|
59
59
|
/// @dev Node is a query contract.
|
|
60
60
|
uint8 constant Query = 0x05;
|
|
61
61
|
/// @dev Node is a guardian-only direct action.
|
package/utils/Nodes.sol
CHANGED
|
@@ -9,9 +9,9 @@ import {ensureAddr, isFamily, matchesBase, toLocalBase} from "./Utils.sol";
|
|
|
9
9
|
/// @notice Encoding and decoding helpers for 256-bit node identifiers.
|
|
10
10
|
///
|
|
11
11
|
/// Node IDs share a common layout:
|
|
12
|
-
/// - bits [255:224] — 4-byte type prefix (`Host`, `Command`,
|
|
12
|
+
/// - bits [255:224] — 4-byte type prefix (`Host`, `Command`, `Port`, etc.)
|
|
13
13
|
/// - bits [223:192] — current `block.chainid` (makes IDs chain-local)
|
|
14
|
-
/// - bits [191:160] — 4-byte ABI selector (commands and
|
|
14
|
+
/// - bits [191:160] — 4-byte ABI selector (commands, ports, queries, and guards)
|
|
15
15
|
/// - bits [159:0] — 160-bit EVM contract address
|
|
16
16
|
///
|
|
17
17
|
/// If the first byte is zero, the node is an opaque
|
|
@@ -31,8 +31,8 @@ library Nodes {
|
|
|
31
31
|
uint32 constant Host = (uint32(Layout.Evm) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Host);
|
|
32
32
|
/// @dev Full 4-byte type prefix for command nodes.
|
|
33
33
|
uint32 constant Command = (uint32(Layout.Evm) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Command);
|
|
34
|
-
/// @dev Full 4-byte type prefix for
|
|
35
|
-
uint32 constant
|
|
34
|
+
/// @dev Full 4-byte type prefix for port nodes.
|
|
35
|
+
uint32 constant Port = (uint32(Layout.Evm) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Port);
|
|
36
36
|
/// @dev Full 4-byte type prefix for query nodes.
|
|
37
37
|
uint32 constant Query = (uint32(Layout.Evm) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Query);
|
|
38
38
|
/// @dev Full 4-byte type prefix for guard action nodes.
|
|
@@ -48,9 +48,9 @@ library Nodes {
|
|
|
48
48
|
return uint32(node >> 224) == Command;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
/// @notice Return true if `node` is a
|
|
52
|
-
function
|
|
53
|
-
return uint32(node >> 224) ==
|
|
51
|
+
/// @notice Return true if `node` is a port node ID.
|
|
52
|
+
function isPort(uint node) internal pure returns (bool) {
|
|
53
|
+
return uint32(node >> 224) == Port;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/// @notice Return true if `node` is a query node ID.
|
|
@@ -94,11 +94,11 @@ library Nodes {
|
|
|
94
94
|
return value;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
/// @notice Assert that `value` is a
|
|
97
|
+
/// @notice Assert that `value` is a port node ID and return it as a node.
|
|
98
98
|
/// @param value Value to validate.
|
|
99
|
-
/// @return node The same `value` if it is a
|
|
100
|
-
function
|
|
101
|
-
if (!
|
|
99
|
+
/// @return node The same `value` if it is a port node.
|
|
100
|
+
function port(uint value) internal pure returns (uint node) {
|
|
101
|
+
if (!isPort(value)) revert InvalidId();
|
|
102
102
|
return value;
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -149,11 +149,11 @@ library Nodes {
|
|
|
149
149
|
return bytes4(uint32(command(node) >> 160));
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
/// @notice Assert that `node` is a
|
|
152
|
+
/// @notice Assert that `node` is a port ID and return its embedded ABI selector.
|
|
153
153
|
/// @param node Node ID to validate.
|
|
154
|
-
/// @return selector 4-byte
|
|
155
|
-
function
|
|
156
|
-
return bytes4(uint32(
|
|
154
|
+
/// @return selector 4-byte port selector stored in bits [191:160].
|
|
155
|
+
function portSelector(uint node) internal pure returns (bytes4 selector) {
|
|
156
|
+
return bytes4(uint32(port(node) >> 160));
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
/// @notice Assert that `node` is a query ID and return its embedded ABI selector.
|
|
@@ -201,12 +201,12 @@ library Nodes {
|
|
|
201
201
|
node |= uint(uint32(selector)) << 160;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
/// @notice Build a chain-local
|
|
205
|
-
/// @param selector 4-byte ABI selector of the
|
|
206
|
-
/// @param target
|
|
207
|
-
/// @return node
|
|
208
|
-
function
|
|
209
|
-
node = toLocalBase(
|
|
204
|
+
/// @notice Build a chain-local port ID for the given selector and contract.
|
|
205
|
+
/// @param selector 4-byte ABI selector of the port entry point.
|
|
206
|
+
/// @param target Port contract address.
|
|
207
|
+
/// @return node Port node ID embedding both the selector and address.
|
|
208
|
+
function toPort(bytes4 selector, address target) internal view returns (uint node) {
|
|
209
|
+
node = toLocalBase(Port) | uint(uint160(target));
|
|
210
210
|
node |= uint(uint32(selector)) << 160;
|
|
211
211
|
}
|
|
212
212
|
|
package/utils/Value.sol
CHANGED
|
@@ -18,19 +18,26 @@ library Values {
|
|
|
18
18
|
/// @param budget Mutable budget to deduct from.
|
|
19
19
|
/// @param amount Native value to spend in wei.
|
|
20
20
|
/// @return The same `amount`, ready to forward to a callee.
|
|
21
|
-
function use(Budget memory budget,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
budget.remaining -= value;
|
|
21
|
+
function use(Budget memory budget, uint amount) internal pure returns (uint) {
|
|
22
|
+
if (amount > budget.remaining) revert InsufficientValue();
|
|
23
|
+
budget.remaining -= amount;
|
|
25
24
|
return amount;
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
/// @notice Drain the remaining native value from `budget` and return it.
|
|
28
|
+
/// @param budget Mutable budget to drain.
|
|
29
|
+
/// @return value Native value removed from the budget, in wei.
|
|
30
|
+
function drain(Budget memory budget) internal pure returns (uint value) {
|
|
31
|
+
value = budget.remaining;
|
|
32
|
+
budget.remaining = 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
/// @notice Deduct `amount` from the budget and return it as a new sub-budget.
|
|
29
36
|
/// Reverts if `amount` exceeds `budget.remaining`.
|
|
30
37
|
/// @param budget Mutable parent budget to deduct from.
|
|
31
38
|
/// @param amount Native value to assign to the sub-budget, in wei.
|
|
32
39
|
/// @return A new budget with `amount` remaining.
|
|
33
|
-
function allocate(Budget memory budget,
|
|
40
|
+
function allocate(Budget memory budget, uint amount) internal pure returns (Budget memory) {
|
|
34
41
|
return Budget({remaining: use(budget, amount)});
|
|
35
42
|
}
|
|
36
43
|
}
|
package/events/Peer.sol
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import {EventEmitter} from "./Emitter.sol";
|
|
5
|
-
|
|
6
|
-
/// @notice Emitted once per peer during host deployment to publish its request and response schemas.
|
|
7
|
-
abstract contract PeerEvent is EventEmitter {
|
|
8
|
-
string private constant ABI =
|
|
9
|
-
"event Peer(uint indexed host, uint id, bytes32 shape, string request, string response, bool funded)";
|
|
10
|
-
|
|
11
|
-
/// @param host Host node ID that owns this peer.
|
|
12
|
-
/// @param id Peer node ID.
|
|
13
|
-
/// @param shape Per-operation block counts encoded as `request:response`.
|
|
14
|
-
/// @param request Schema DSL string describing the input request run, or empty if none.
|
|
15
|
-
/// @param response Schema DSL string describing the peer response shape.
|
|
16
|
-
/// @param funded Whether the peer entrypoint accepts nonzero `msg.value`.
|
|
17
|
-
event Peer(uint indexed host, uint id, bytes32 shape, string request, string response, bool funded);
|
|
18
|
-
|
|
19
|
-
constructor() {
|
|
20
|
-
emit EventAbi(ABI);
|
|
21
|
-
}
|
|
22
|
-
}
|
package/peer/AllowAssets.sol
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import { PeerBase } from "./Base.sol";
|
|
5
|
-
import { AllowAssetsHook } from "../commands/admin/AllowAssets.sol";
|
|
6
|
-
import { Cursors, Cur, Schemas } from "../Cursors.sol";
|
|
7
|
-
|
|
8
|
-
using Cursors for Cur;
|
|
9
|
-
|
|
10
|
-
interface IPeerAllowAssets {
|
|
11
|
-
function peerAllowAssets(bytes calldata request) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/// @title PeerAllowAssets
|
|
15
|
-
/// @notice Peer that permits a list of assets on behalf of a peer host.
|
|
16
|
-
/// Each ASSET block in the request calls `allowAsset`. Restricted to trusted peers.
|
|
17
|
-
abstract contract PeerAllowAssets is PeerBase, AllowAssetsHook, IPeerAllowAssets {
|
|
18
|
-
uint internal immutable peerAllowAssetsId = peerId(this.peerAllowAssets.selector);
|
|
19
|
-
|
|
20
|
-
constructor() {
|
|
21
|
-
emit Peer(host, peerAllowAssetsId, "1:0", Schemas.Asset, "", false);
|
|
22
|
-
emit Labeled(peerAllowAssetsId, bytes32(0), "peerAllowAssets");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/// @notice Execute the allow-assets peer call.
|
|
26
|
-
/// @param request ASSET block stream supplied by the trusted peer.
|
|
27
|
-
/// @return Empty response bytes.
|
|
28
|
-
function peerAllowAssets(bytes calldata request) external onlyPeer returns (bytes memory) {
|
|
29
|
-
(Cur memory assets, , ) = Cursors.init(request, 1);
|
|
30
|
-
|
|
31
|
-
while (assets.i < assets.len) {
|
|
32
|
-
bytes32 asset = assets.unpackAsset();
|
|
33
|
-
allowAsset(asset);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
assets.complete();
|
|
37
|
-
return "";
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
package/peer/Allowance.sol
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import {PeerBase} from "./Base.sol";
|
|
5
|
-
import {AllowanceHook} from "../commands/admin/Allowance.sol";
|
|
6
|
-
import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
7
|
-
|
|
8
|
-
using Cursors for Cur;
|
|
9
|
-
|
|
10
|
-
interface IPeerAllowance {
|
|
11
|
-
function peerAllowance(bytes calldata request) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/// @title PeerAllowance
|
|
15
|
-
/// @notice Peer that lets a trusted peer host request or refresh its own allowance.
|
|
16
|
-
/// Each AMOUNT block in the request is scoped to the peer host and passed to the
|
|
17
|
-
/// shared allowance hook as a host-scoped allowance. Restricted to trusted peers.
|
|
18
|
-
abstract contract PeerAllowance is PeerBase, AllowanceHook, IPeerAllowance {
|
|
19
|
-
uint internal immutable peerAllowanceId = peerId(this.peerAllowance.selector);
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
emit Peer(host, peerAllowanceId, "1:0", Schemas.Amount, "", false);
|
|
23
|
-
emit Labeled(peerAllowanceId, bytes32(0), "peerAllowance");
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/// @notice Execute the allowance peer call.
|
|
27
|
-
/// @param request AMOUNT block stream requested by the trusted peer.
|
|
28
|
-
/// @return Empty response bytes.
|
|
29
|
-
function peerAllowance(bytes calldata request) external onlyPeer returns (bytes memory) {
|
|
30
|
-
(Cur memory amounts, , ) = Cursors.init(request, 1);
|
|
31
|
-
uint peer = caller();
|
|
32
|
-
|
|
33
|
-
while (amounts.i < amounts.len) {
|
|
34
|
-
(bytes32 asset, uint amount) = amounts.unpackAmount();
|
|
35
|
-
allowance(peer, asset, amount);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
amounts.complete();
|
|
39
|
-
return "";
|
|
40
|
-
}
|
|
41
|
-
}
|
package/peer/Base.sol
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import { NodeCalls } from "../core/Calls.sol";
|
|
5
|
-
import { PeerEvent } from "../events/Peer.sol";
|
|
6
|
-
import { LabeledEvent } from "../events/Labeled.sol";
|
|
7
|
-
import { Nodes } from "../utils/Nodes.sol";
|
|
8
|
-
|
|
9
|
-
/// @notice ABI-encode a peer call from a target peer ID and request block stream.
|
|
10
|
-
/// @dev Derives the function selector from `target` via `Nodes.peerSelector(target)`.
|
|
11
|
-
/// Reverts if `target` is not a valid peer ID.
|
|
12
|
-
/// @param target Destination peer node ID embedding the target selector.
|
|
13
|
-
/// @param request Input block stream for the peer invocation.
|
|
14
|
-
/// @return ABI-encoded calldata for the peer entry point.
|
|
15
|
-
function encodePeerCall(uint target, bytes calldata request) pure returns (bytes memory) {
|
|
16
|
-
bytes4 selector = Nodes.peerSelector(target);
|
|
17
|
-
return abi.encodeWithSelector(selector, request);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/// @title PeerBase
|
|
21
|
-
/// @notice Abstract base for all rootzero peer contracts.
|
|
22
|
-
/// Peers handle inter-host operations and asset allow/deny management
|
|
23
|
-
/// between cooperating hosts. Access is restricted to trusted callers via `onlyPeer`.
|
|
24
|
-
abstract contract PeerBase is NodeCalls, PeerEvent, LabeledEvent {
|
|
25
|
-
/// @dev Thrown when the commander attempts to call a peer entrypoint directly.
|
|
26
|
-
error CommanderNotAllowed();
|
|
27
|
-
|
|
28
|
-
/// @dev Restrict execution to trusted callers, excluding the commander.
|
|
29
|
-
modifier onlyPeer() {
|
|
30
|
-
if (msg.sender == commander) revert CommanderNotAllowed();
|
|
31
|
-
enforceCaller(msg.sender);
|
|
32
|
-
_;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/// @notice Derive the deterministic node ID for a peer selector on this contract.
|
|
36
|
-
/// @param selector Peer entrypoint selector.
|
|
37
|
-
/// @return Peer node ID.
|
|
38
|
-
function peerId(bytes4 selector) internal view returns (uint) {
|
|
39
|
-
return Nodes.toPeer(selector, address(this));
|
|
40
|
-
}
|
|
41
|
-
}
|
package/peer/Credit.sol
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import { PeerBase } from "./Base.sol";
|
|
5
|
-
import { CreditAccountHook } from "../commands/Credit.sol";
|
|
6
|
-
import { Cursors, Cur, Forms } from "../Cursors.sol";
|
|
7
|
-
|
|
8
|
-
using Cursors for Cur;
|
|
9
|
-
|
|
10
|
-
interface IPeerCreditAccount {
|
|
11
|
-
function peerCreditAccount(bytes calldata request) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/// @title PeerCreditAccount
|
|
15
|
-
/// @notice Peer that lets a trusted peer credit supplied accounts directly.
|
|
16
|
-
/// Each ACCOUNT_AMOUNT block calls `creditAccount` for its account.
|
|
17
|
-
abstract contract PeerCreditAccount is PeerBase, CreditAccountHook, IPeerCreditAccount {
|
|
18
|
-
uint internal immutable peerCreditAccountId = peerId(this.peerCreditAccount.selector);
|
|
19
|
-
|
|
20
|
-
constructor() {
|
|
21
|
-
emit Peer(host, peerCreditAccountId, "1:0", Forms.AccountAmount, "", false);
|
|
22
|
-
emit Labeled(peerCreditAccountId, bytes32(0), "peerCreditAccount");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/// @notice Execute the peer-credit call.
|
|
26
|
-
/// @param request ACCOUNT_AMOUNT block stream supplied by the trusted peer.
|
|
27
|
-
/// @return Empty response bytes.
|
|
28
|
-
function peerCreditAccount(bytes calldata request) external onlyPeer returns (bytes memory) {
|
|
29
|
-
(Cur memory amounts, , ) = Cursors.init(request, 1);
|
|
30
|
-
|
|
31
|
-
while (amounts.i < amounts.len) {
|
|
32
|
-
(bytes32 account, bytes32 asset, uint amount) = amounts.unpackAccountAmount();
|
|
33
|
-
creditAccount(account, asset, amount);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
amounts.complete();
|
|
37
|
-
return "";
|
|
38
|
-
}
|
|
39
|
-
}
|
package/peer/Debit.sol
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import { PeerBase } from "./Base.sol";
|
|
5
|
-
import { DebitAccountHook } from "../commands/Debit.sol";
|
|
6
|
-
import { Cursors, Cur, Forms } from "../Cursors.sol";
|
|
7
|
-
|
|
8
|
-
using Cursors for Cur;
|
|
9
|
-
|
|
10
|
-
interface IPeerDebitAccount {
|
|
11
|
-
function peerDebitAccount(bytes calldata request) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/// @title PeerDebitAccount
|
|
15
|
-
/// @notice Peer that lets a trusted peer debit supplied accounts directly.
|
|
16
|
-
/// Each ACCOUNT_AMOUNT block calls `debitAccount` for its account.
|
|
17
|
-
abstract contract PeerDebitAccount is PeerBase, DebitAccountHook, IPeerDebitAccount {
|
|
18
|
-
uint internal immutable peerDebitAccountId = peerId(this.peerDebitAccount.selector);
|
|
19
|
-
|
|
20
|
-
constructor() {
|
|
21
|
-
emit Peer(host, peerDebitAccountId, "1:0", Forms.AccountAmount, "", false);
|
|
22
|
-
emit Labeled(peerDebitAccountId, bytes32(0), "peerDebitAccount");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/// @notice Execute the peer-debit call.
|
|
26
|
-
/// @param request ACCOUNT_AMOUNT block stream supplied by the trusted peer.
|
|
27
|
-
/// @return Empty response bytes.
|
|
28
|
-
function peerDebitAccount(bytes calldata request) external onlyPeer returns (bytes memory) {
|
|
29
|
-
(Cur memory amounts, , ) = Cursors.init(request, 1);
|
|
30
|
-
|
|
31
|
-
while (amounts.i < amounts.len) {
|
|
32
|
-
(bytes32 account, bytes32 asset, uint amount) = amounts.unpackAccountAmount();
|
|
33
|
-
debitAccount(account, asset, amount);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
amounts.complete();
|
|
37
|
-
return "";
|
|
38
|
-
}
|
|
39
|
-
}
|
package/peer/DenyAssets.sol
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import {PeerBase} from "./Base.sol";
|
|
5
|
-
import {DenyAssetsHook} from "../commands/admin/DenyAssets.sol";
|
|
6
|
-
import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
7
|
-
|
|
8
|
-
using Cursors for Cur;
|
|
9
|
-
|
|
10
|
-
interface IPeerDenyAssets {
|
|
11
|
-
function peerDenyAssets(bytes calldata request) external returns (bytes memory);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/// @title PeerDenyAssets
|
|
15
|
-
/// @notice Peer that blocks a list of assets on behalf of a peer host.
|
|
16
|
-
/// Each ASSET block in the request calls `denyAsset`. Restricted to trusted peers.
|
|
17
|
-
abstract contract PeerDenyAssets is PeerBase, DenyAssetsHook, IPeerDenyAssets {
|
|
18
|
-
uint internal immutable peerDenyAssetsId = peerId(this.peerDenyAssets.selector);
|
|
19
|
-
|
|
20
|
-
constructor() {
|
|
21
|
-
emit Peer(host, peerDenyAssetsId, "1:0", Schemas.Asset, "", false);
|
|
22
|
-
emit Labeled(peerDenyAssetsId, bytes32(0), "peerDenyAssets");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/// @notice Execute the deny-assets peer call.
|
|
26
|
-
/// @param request ASSET block stream supplied by the trusted peer.
|
|
27
|
-
/// @return Empty response bytes.
|
|
28
|
-
function peerDenyAssets(bytes calldata request) external onlyPeer returns (bytes memory) {
|
|
29
|
-
(Cur memory assets, , ) = Cursors.init(request, 1);
|
|
30
|
-
|
|
31
|
-
while (assets.i < assets.len) {
|
|
32
|
-
bytes32 asset = assets.unpackAsset();
|
|
33
|
-
denyAsset(asset);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
assets.complete();
|
|
37
|
-
return "";
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
package/peer/Pipe.sol
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
-
pragma solidity ^0.8.33;
|
|
3
|
-
|
|
4
|
-
import {PeerBase} from "./Base.sol";
|
|
5
|
-
import {Pipeline} from "../core/Pipeline.sol";
|
|
6
|
-
import {Cursors, Cur, Schemas} from "../Cursors.sol";
|
|
7
|
-
import {Budget} from "../utils/Value.sol";
|
|
8
|
-
|
|
9
|
-
using Cursors for Cur;
|
|
10
|
-
|
|
11
|
-
interface IPeerPipePayable {
|
|
12
|
-
function peerPipePayable(bytes calldata request) external payable returns (bytes memory);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/// @title PeerPipePayable
|
|
16
|
-
/// @notice Peer that consumes PIPE blocks and executes each context step stream.
|
|
17
|
-
/// Each PIPE block carries chain resources plus a CONTEXT block; the nested
|
|
18
|
-
/// context steps are passed to the shared pipeline as the step stream.
|
|
19
|
-
abstract contract PeerPipePayable is PeerBase, Pipeline, IPeerPipePayable {
|
|
20
|
-
uint internal immutable peerPipePayableId = peerId(this.peerPipePayable.selector);
|
|
21
|
-
|
|
22
|
-
constructor() {
|
|
23
|
-
emit Peer(host, peerPipePayableId, "1:0", Schemas.Pipe, "", true);
|
|
24
|
-
emit Labeled(peerPipePayableId, bytes32(0), "peerPipePayable");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/// @notice Execute peer-supplied pipes through the shared payable pipe.
|
|
28
|
-
/// @dev Each pipe receives its own explicit EVM value sub-budget. Any top-level
|
|
29
|
-
/// `msg.value` not assigned to a pipe remains on this host.
|
|
30
|
-
/// @param request PIPE block stream supplied by the trusted peer.
|
|
31
|
-
/// @return Empty response bytes.
|
|
32
|
-
function peerPipePayable(bytes calldata request) external payable onlyPeer returns (bytes memory) {
|
|
33
|
-
(Cur memory input, , ) = Cursors.init(request, 1);
|
|
34
|
-
Budget memory budget = valueBudget();
|
|
35
|
-
|
|
36
|
-
while (input.i < input.len) {
|
|
37
|
-
(uint resources, bytes32 account, bytes calldata state, bytes calldata steps) = input.unpackPipe();
|
|
38
|
-
pipe(account, state, steps, allocateValue(budget, resources));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
input.complete();
|
|
42
|
-
return "";
|
|
43
|
-
}
|
|
44
|
-
}
|