21 Commits

Author SHA1 Message Date
hdbg
01b12515bd housekeeping(server): fixed clippy warns
Some checks failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-lint Pipeline failed
ci/woodpecker/pr/server-test Pipeline failed
ci/woodpecker/pr/useragent-analyze Pipeline failed
2026-04-04 14:33:48 +02:00
hdbg
4a50daa7ea refactor(user-agent): remove backfill pubkey integrity tags
Some checks failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-lint Pipeline failed
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-test Pipeline failed
ci/woodpecker/pr/useragent-analyze Pipeline failed
2026-04-04 14:32:00 +02:00
hdbg
352ee3ee63 fix(server): previously, user agent auth accepted invalid signatures
Some checks failed
ci/woodpecker/pr/server-lint Pipeline failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-test Pipeline failed
ci/woodpecker/pr/useragent-analyze Pipeline failed
2026-04-04 14:28:07 +02:00
hdbg
dd51d756da refactor(server): separate crypto by purpose and moved outside of actor into separate module 2026-04-04 14:21:52 +02:00
CleverWild
0bb6e596ac feat(auth): implement attestation status verification for public keys
Some checks failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-lint Pipeline failed
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-test Pipeline failed
ci/woodpecker/pr/useragent-analyze Pipeline failed
2026-04-04 12:10:45 +02:00
CleverWild
881f16bb1a fix(keyholder): comment drift 2026-04-04 12:02:50 +02:00
CleverWild
78895bca5b refactor(keyholder): generalize derive_useragent_integrity_key and compute_useragent_pubkey_integrity_tag corespondenly to derive_integrity_key and compute_integrity_tag 2026-04-04 12:00:39 +02:00
CleverWild
a02ef68a70 feat(auth): add seal-key-derived pubkey integrity tags with auth enforcement and unseal backfill
Some checks failed
ci/woodpecker/pr/server-lint Pipeline failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-test Pipeline failed
2026-03-30 00:17:04 +02:00
hdbg
e5be55e141 style(dashboard): format code and add title margin
Some checks failed
ci/woodpecker/push/useragent-analyze Pipeline failed
2026-03-29 10:54:02 +02:00
hdbg
8f0eb7130b feat(grants-create): add configurable grant authorization fields 2026-03-29 00:37:58 +01:00
hdbg
94fe04a6a4 refactor(useragent::evm::grants): split into more files & flutter_form_builder usage 2026-03-29 00:37:58 +01:00
hdbg
976c11902c fix(useragent::dashboard): screen pushed twice due to improper listen hook 2026-03-29 00:37:58 +01:00
hdbg
c8d2662a36 refactor(grants): wrap grant list in SingleChildScrollView 2026-03-29 00:37:58 +01:00
hdbg
ac5fedddd1 style(dashboard): remove const from _CalloutBell and add title to nav rail 2026-03-29 00:37:58 +01:00
hdbg
0c2d4986a2 refactor(useragent): moved shared CreamPanel and StatePanel into generic widgets 2026-03-29 00:37:58 +01:00
hdbg
a3203936d2 feat(evm): add EVM grants screen with create UI and list 2026-03-29 00:37:58 +01:00
hdbg
fb1c0ec130 refactor(proto): restructure wallet access messages for improved data organization 2026-03-29 00:37:58 +01:00
hdbg
2a21758369 refactor(server::evm): removed repetetive errors and error variants 2026-03-29 00:37:58 +01:00
hdbg
1abb5fa006 refactor(useragent::evm::table): broke down into more widgets 2026-03-29 00:37:58 +01:00
hdbg
e1b1c857fa refactor(useragent::evm): moved out header into general widget 2026-03-29 00:37:58 +01:00
hdbg
4216007af3 feat(useragent): vibe-coded access list 2026-03-29 00:37:58 +01:00
147 changed files with 8552 additions and 9432 deletions

View File

@@ -1,26 +0,0 @@
when:
- event: pull_request
path:
include: [".woodpecker/server-*.yaml", "server/**"]
- event: push
branch: main
path:
include: [".woodpecker/server-*.yaml", "server/**"]
steps:
- name: compile
image: jdxcode/mise:latest
directory: server
environment:
CARGO_TERM_COLOR: always
CARGO_TARGET_DIR: /usr/local/cargo/target
CARGO_HOME: /usr/local/cargo/registry
volumes:
- cargo-target:/usr/local/cargo/target
- cargo-registry:/usr/local/cargo/registry
commands:
- apt-get update && apt-get install -y pkg-config
# Install only the necessary Rust toolchain
- mise install rust
- mise install protoc
- cargo check --all-features

View File

@@ -67,18 +67,7 @@ The `program_client.nonce` column stores the **next usable nonce** — i.e. it i
## Cryptography ## Cryptography
### Authentication ### Authentication
- **Client protocol:** ed25519 - **Signature scheme:** ed25519
### User-Agent Authentication
User-agent authentication supports multiple signature schemes because platform-provided "hardware-bound" keys do not expose a uniform algorithm across operating systems and hardware.
- **Supported schemes:** RSA, Ed25519, ECDSA (secp256k1)
- **Why:** the user agent authenticates with keys backed by platform facilities, and those facilities differ by platform
- **Apple Silicon Secure Enclave / Secure Element:** ECDSA-only in practice
- **Windows Hello / TPM 2.0:** currently RSA-backed in our integration
This is why the user-agent auth protocol carries an explicit `KeyType`, while the SDK client protocol remains fixed to ed25519.
### Encryption at Rest ### Encryption at Rest
- **Scheme:** Symmetric AEAD — currently **XChaCha20-Poly1305** - **Scheme:** Symmetric AEAD — currently **XChaCha20-Poly1305**
@@ -159,7 +148,7 @@ The central abstraction is the `Policy` trait. Each implementation handles one s
Every grant has two layers: Every grant has two layers:
- **Shared (`evm_basic_grant`)** — wallet, chain, validity period, gas fee caps, transaction count rate limit. One row per grant regardless of type. - **Shared (`evm_basic_grant`)** — wallet, chain, validity period, gas fee caps, transaction count rate limit. One row per grant regardless of type.
- **Specific** — policy-owned tables (`evm_ether_transfer_grant`, `evm_token_transfer_grant`) holding type-specific configuration. - **Specific** — policy-owned tables (`evm_ether_transfer_grant`, `evm_token_transfer_grant`, etc.) holding type-specific configuration.
`find_all_grants` uses a `#[diesel::auto_type]` base join between the specific and shared tables, then batch-loads related rows (targets, volume limits) in two additional queries to avoid N+1. `find_all_grants` uses a `#[diesel::auto_type]` base join between the specific and shared tables, then batch-loads related rows (targets, volume limits) in two additional queries to avoid N+1.
@@ -182,6 +171,7 @@ These are checked centrally in `check_shared_constraints` before policy evaluati
- **Only EIP-1559 transactions are supported.** Legacy and EIP-2930 types are rejected outright. - **Only EIP-1559 transactions are supported.** Legacy and EIP-2930 types are rejected outright.
- **No opaque-calldata (unknown contract) grant type.** The architecture describes a category for unrecognised contracts, but no policy implements it yet. Any transaction that is not a plain ETH transfer or a known ERC-20 transfer is unconditionally rejected. - **No opaque-calldata (unknown contract) grant type.** The architecture describes a category for unrecognised contracts, but no policy implements it yet. Any transaction that is not a plain ETH transfer or a known ERC-20 transfer is unconditionally rejected.
- **Token registry is static.** Tokens are recognised only if they appear in the hard-coded `arbiter_tokens_registry` crate. There is no mechanism to register additional contracts at runtime. - **Token registry is static.** Tokens are recognised only if they appear in the hard-coded `arbiter_tokens_registry` crate. There is no mechanism to register additional contracts at runtime.
- **Nonce management is not implemented.** The architecture lists nonce deduplication as a core responsibility, but no nonce tracking or enforcement exists yet.
--- ---
@@ -189,5 +179,5 @@ These are checked centrally in `check_shared_constraints` before policy evaluati
The unsealed root key must be held in a hardened memory cell resistant to dumps, page swaps, and hibernation. The unsealed root key must be held in a hardened memory cell resistant to dumps, page swaps, and hibernation.
- **Current:** A dedicated memory-protection abstraction is in place, with `memsafe` used behind that abstraction today - **Current:** Using the `memsafe` crate as an interim solution
- **Planned:** Additional backends can be introduced behind the same abstraction, including a custom implementation based on `mlock` (Unix) and `VirtualProtect` (Windows) - **Planned:** Custom implementation based on `mlock` (Unix) and `VirtualProtect` (Windows)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,821 @@
# Grant Grid View Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add an "EVM Grants" dashboard tab that displays all grants as enriched cards (type, chain, wallet address, client name) with per-card revoke support.
**Architecture:** A new `walletAccessListProvider` fetches wallet accesses with their DB row IDs. The screen (`grants.dart`) watches only `evmGrantsProvider` for top-level state. Each `GrantCard` widget (its own file) watches enrichment providers (`walletAccessListProvider`, `evmProvider`, `sdkClientsProvider`) and the revoke mutation directly — keeping rebuilds scoped to the card. The screen is registered as a dashboard tab in `AdaptiveScaffold`.
**Tech Stack:** Flutter, Riverpod (`riverpod_annotation` + `build_runner` codegen), `sizer` (adaptive sizing), `auto_route`, Protocol Buffers (Dart), `Palette` design tokens.
---
## File Map
| File | Action | Responsibility |
|---|---|---|
| `useragent/lib/theme/palette.dart` | Modify | Add `Palette.token` (indigo accent for token-transfer cards) |
| `useragent/lib/features/connection/evm/wallet_access.dart` | Modify | Add `listAllWalletAccesses()` function |
| `useragent/lib/providers/sdk_clients/wallet_access_list.dart` | Create | `WalletAccessListProvider` — fetches full wallet access list with IDs |
| `useragent/lib/screens/dashboard/evm/grants/widgets/grant_card.dart` | Create | `GrantCard` widget — watches enrichment providers + revoke mutation; one card per grant |
| `useragent/lib/screens/dashboard/evm/grants/grants.dart` | Create | `EvmGrantsScreen` — watches `evmGrantsProvider`; handles loading/error/empty/data states; renders `GrantCard` list |
| `useragent/lib/router.dart` | Modify | Register `EvmGrantsRoute` in dashboard children |
| `useragent/lib/screens/dashboard.dart` | Modify | Add Grants entry to `routes` list and `NavigationDestination` list |
---
## Task 1: Add `Palette.token`
**Files:**
- Modify: `useragent/lib/theme/palette.dart`
- [ ] **Step 1: Add the color**
Replace the contents of `useragent/lib/theme/palette.dart` with:
```dart
import 'package:flutter/material.dart';
class Palette {
static const ink = Color(0xFF15263C);
static const coral = Color(0xFFE26254);
static const cream = Color(0xFFFFFAF4);
static const line = Color(0x1A15263C);
static const token = Color(0xFF5C6BC0);
}
```
- [ ] **Step 2: Verify**
```sh
cd useragent && flutter analyze lib/theme/palette.dart
```
Expected: no issues.
- [ ] **Step 3: Commit**
```sh
jj describe -m "feat(theme): add Palette.token for token-transfer grant cards"
jj new
```
---
## Task 2: Add `listAllWalletAccesses` feature function
**Files:**
- Modify: `useragent/lib/features/connection/evm/wallet_access.dart`
`readClientWalletAccess` (existing) filters the list to one client's wallet IDs and returns `Set<int>`. This new function returns the complete unfiltered list with row IDs so the grant cards can resolve wallet_access_id → wallet + client.
- [ ] **Step 1: Append function**
Add at the bottom of `useragent/lib/features/connection/evm/wallet_access.dart`:
```dart
Future<List<SdkClientWalletAccess>> listAllWalletAccesses(
Connection connection,
) async {
final response = await connection.ask(
UserAgentRequest(listWalletAccess: Empty()),
);
if (!response.hasListWalletAccessResponse()) {
throw Exception(
'Expected list wallet access response, got ${response.whichPayload()}',
);
}
return response.listWalletAccessResponse.accesses.toList(growable: false);
}
```
Each returned `SdkClientWalletAccess` has:
- `.id` — the `evm_wallet_access` row ID (same value as `wallet_access_id` in a `GrantEntry`)
- `.access.walletId` — the EVM wallet DB ID
- `.access.sdkClientId` — the SDK client DB ID
- [ ] **Step 2: Verify**
```sh
cd useragent && flutter analyze lib/features/connection/evm/wallet_access.dart
```
Expected: no issues.
- [ ] **Step 3: Commit**
```sh
jj describe -m "feat(evm): add listAllWalletAccesses feature function"
jj new
```
---
## Task 3: Create `WalletAccessListProvider`
**Files:**
- Create: `useragent/lib/providers/sdk_clients/wallet_access_list.dart`
- Generated: `useragent/lib/providers/sdk_clients/wallet_access_list.g.dart`
Mirrors the structure of `EvmGrants` in `providers/evm/evm_grants.dart` — class-based `@riverpod` with a `refresh()` method.
- [ ] **Step 1: Write the provider**
Create `useragent/lib/providers/sdk_clients/wallet_access_list.dart`:
```dart
import 'package:arbiter/features/connection/evm/wallet_access.dart';
import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:arbiter/providers/connection/connection_manager.dart';
import 'package:mtcore/markettakers.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'wallet_access_list.g.dart';
@riverpod
class WalletAccessList extends _$WalletAccessList {
@override
Future<List<SdkClientWalletAccess>?> build() async {
final connection = await ref.watch(connectionManagerProvider.future);
if (connection == null) {
return null;
}
try {
return await listAllWalletAccesses(connection);
} catch (e, st) {
talker.handle(e, st);
rethrow;
}
}
Future<void> refresh() async {
final connection = await ref.read(connectionManagerProvider.future);
if (connection == null) {
state = const AsyncData(null);
return;
}
state = const AsyncLoading();
state = await AsyncValue.guard(() => listAllWalletAccesses(connection));
}
}
```
- [ ] **Step 2: Run code generation**
```sh
cd useragent && dart run build_runner build --delete-conflicting-outputs
```
Expected: `useragent/lib/providers/sdk_clients/wallet_access_list.g.dart` created. No errors.
- [ ] **Step 3: Verify**
```sh
cd useragent && flutter analyze lib/providers/sdk_clients/
```
Expected: no issues.
- [ ] **Step 4: Commit**
```sh
jj describe -m "feat(providers): add WalletAccessListProvider"
jj new
```
---
## Task 4: Create `GrantCard` widget
**Files:**
- Create: `useragent/lib/screens/dashboard/evm/grants/widgets/grant_card.dart`
This widget owns all per-card logic: enrichment lookups, revoke action, and rebuild scope. The screen only passes it a `GrantEntry` — the card fetches everything else itself.
**Key types:**
- `GrantEntry` (from `proto/evm.pb.dart`): `.id`, `.shared.walletAccessId`, `.shared.chainId`, `.specific.whichGrant()`
- `SpecificGrant_Grant.etherTransfer` / `.tokenTransfer` — enum values for the oneof
- `SdkClientWalletAccess` (from `proto/user_agent.pb.dart`): `.id`, `.access.walletId`, `.access.sdkClientId`
- `WalletEntry` (from `proto/evm.pb.dart`): `.id`, `.address` (List<int>)
- `SdkClientEntry` (from `proto/user_agent.pb.dart`): `.id`, `.info.name`
- `revokeEvmGrantMutation``Mutation<void>` (global; all revoke buttons disable together while any revoke is in flight)
- `executeRevokeEvmGrant(ref, grantId: int)``Future<void>`
- [ ] **Step 1: Write the widget**
Create `useragent/lib/screens/dashboard/evm/grants/widgets/grant_card.dart`:
```dart
import 'package:arbiter/proto/evm.pb.dart';
import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:arbiter/providers/evm/evm.dart';
import 'package:arbiter/providers/evm/evm_grants.dart';
import 'package:arbiter/providers/sdk_clients/list.dart';
import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart';
import 'package:arbiter/theme/palette.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/experimental/mutation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:sizer/sizer.dart';
String _shortAddress(List<int> bytes) {
final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}';
}
String _formatError(Object error) {
final message = error.toString();
if (message.startsWith('Exception: ')) {
return message.substring('Exception: '.length);
}
return message;
}
class GrantCard extends ConsumerWidget {
const GrantCard({super.key, required this.grant});
final GrantEntry grant;
@override
Widget build(BuildContext context, WidgetRef ref) {
// Enrichment lookups — each watch scopes rebuilds to this card only
final walletAccesses =
ref.watch(walletAccessListProvider).asData?.value ?? const [];
final wallets = ref.watch(evmProvider).asData?.value ?? const [];
final clients = ref.watch(sdkClientsProvider).asData?.value ?? const [];
final revoking = ref.watch(revokeEvmGrantMutation) is MutationPending;
final isEther =
grant.specific.whichGrant() == SpecificGrant_Grant.etherTransfer;
final accent = isEther ? Palette.coral : Palette.token;
final typeLabel = isEther ? 'Ether' : 'Token';
final theme = Theme.of(context);
final muted = Palette.ink.withValues(alpha: 0.62);
// Resolve wallet_access_id → wallet address + client name
final accessById = <int, SdkClientWalletAccess>{
for (final a in walletAccesses) a.id: a,
};
final walletById = <int, WalletEntry>{
for (final w in wallets) w.id: w,
};
final clientNameById = <int, String>{
for (final c in clients) c.id: c.info.name,
};
final accessId = grant.shared.walletAccessId;
final access = accessById[accessId];
final wallet = access != null ? walletById[access.access.walletId] : null;
final walletLabel = wallet != null
? _shortAddress(wallet.address)
: 'Access #$accessId';
final clientLabel = () {
if (access == null) return '';
final name = clientNameById[access.access.sdkClientId] ?? '';
return name.isEmpty ? 'Client #${access.access.sdkClientId}' : name;
}();
void showError(String message) {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message), behavior: SnackBarBehavior.floating),
);
}
Future<void> revoke() async {
try {
await executeRevokeEvmGrant(ref, grantId: grant.id);
} catch (e) {
showError(_formatError(e));
}
}
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
color: Palette.cream.withValues(alpha: 0.92),
border: Border.all(color: Palette.line),
),
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Accent strip
Container(
width: 0.8.w,
decoration: BoxDecoration(
color: accent,
borderRadius: const BorderRadius.horizontal(
left: Radius.circular(24),
),
),
),
// Card body
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 1.6.w,
vertical: 1.4.h,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row 1: type badge · chain · spacer · revoke button
Row(
children: [
Container(
padding: EdgeInsets.symmetric(
horizontal: 1.w,
vertical: 0.4.h,
),
decoration: BoxDecoration(
color: accent.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(8),
),
child: Text(
typeLabel,
style: theme.textTheme.labelSmall?.copyWith(
color: accent,
fontWeight: FontWeight.w800,
),
),
),
SizedBox(width: 1.w),
Container(
padding: EdgeInsets.symmetric(
horizontal: 1.w,
vertical: 0.4.h,
),
decoration: BoxDecoration(
color: Palette.ink.withValues(alpha: 0.06),
borderRadius: BorderRadius.circular(8),
),
child: Text(
'Chain ${grant.shared.chainId}',
style: theme.textTheme.labelSmall?.copyWith(
color: muted,
fontWeight: FontWeight.w700,
),
),
),
const Spacer(),
if (revoking)
SizedBox(
width: 1.8.h,
height: 1.8.h,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Palette.coral,
),
)
else
OutlinedButton.icon(
onPressed: revoke,
style: OutlinedButton.styleFrom(
foregroundColor: Palette.coral,
side: BorderSide(
color: Palette.coral.withValues(alpha: 0.4),
),
padding: EdgeInsets.symmetric(
horizontal: 1.w,
vertical: 0.6.h,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
icon: const Icon(Icons.block_rounded, size: 16),
label: const Text('Revoke'),
),
],
),
SizedBox(height: 0.8.h),
// Row 2: wallet address · client name
Row(
children: [
Text(
walletLabel,
style: theme.textTheme.bodySmall?.copyWith(
color: Palette.ink,
fontFamily: 'monospace',
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 0.8.w),
child: Text(
'·',
style: theme.textTheme.bodySmall
?.copyWith(color: muted),
),
),
Expanded(
child: Text(
clientLabel,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.bodySmall
?.copyWith(color: muted),
),
),
],
),
],
),
),
),
],
),
),
);
}
}
```
- [ ] **Step 2: Verify**
```sh
cd useragent && flutter analyze lib/screens/dashboard/evm/grants/widgets/grant_card.dart
```
Expected: no issues.
- [ ] **Step 3: Commit**
```sh
jj describe -m "feat(grants): add GrantCard widget with self-contained enrichment"
jj new
```
---
## Task 5: Create `EvmGrantsScreen`
**Files:**
- Create: `useragent/lib/screens/dashboard/evm/grants/grants.dart`
The screen watches only `evmGrantsProvider` for top-level state (loading / error / no connection / empty / data). When there is data it renders a list of `GrantCard` widgets — each card manages its own enrichment subscriptions.
- [ ] **Step 1: Write the screen**
Create `useragent/lib/screens/dashboard/evm/grants/grants.dart`:
```dart
import 'package:arbiter/proto/evm.pb.dart';
import 'package:arbiter/providers/evm/evm_grants.dart';
import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart';
import 'package:arbiter/router.gr.dart';
import 'package:arbiter/screens/dashboard/evm/grants/widgets/grant_card.dart';
import 'package:arbiter/theme/palette.dart';
import 'package:arbiter/widgets/page_header.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:sizer/sizer.dart';
String _formatError(Object error) {
final message = error.toString();
if (message.startsWith('Exception: ')) {
return message.substring('Exception: '.length);
}
return message;
}
// ─── State panel ──────────────────────────────────────────────────────────────
class _StatePanel extends StatelessWidget {
const _StatePanel({
required this.icon,
required this.title,
required this.body,
this.actionLabel,
this.onAction,
this.busy = false,
});
final IconData icon;
final String title;
final String body;
final String? actionLabel;
final Future<void> Function()? onAction;
final bool busy;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
color: Palette.cream.withValues(alpha: 0.92),
border: Border.all(color: Palette.line),
),
child: Padding(
padding: EdgeInsets.all(2.8.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (busy)
SizedBox(
width: 2.8.h,
height: 2.8.h,
child: const CircularProgressIndicator(strokeWidth: 2.5),
)
else
Icon(icon, size: 34, color: Palette.coral),
SizedBox(height: 1.8.h),
Text(
title,
style: theme.textTheme.headlineSmall?.copyWith(
color: Palette.ink,
fontWeight: FontWeight.w800,
),
),
SizedBox(height: 1.h),
Text(
body,
style: theme.textTheme.bodyLarge?.copyWith(
color: Palette.ink.withValues(alpha: 0.72),
height: 1.5,
),
),
if (actionLabel != null && onAction != null) ...[
SizedBox(height: 2.h),
OutlinedButton.icon(
onPressed: () => onAction!(),
icon: const Icon(Icons.refresh),
label: Text(actionLabel!),
),
],
],
),
),
);
}
}
// ─── Grant list ───────────────────────────────────────────────────────────────
class _GrantList extends StatelessWidget {
const _GrantList({required this.grants});
final List<GrantEntry> grants;
@override
Widget build(BuildContext context) {
return Column(
children: [
for (var i = 0; i < grants.length; i++)
Padding(
padding: EdgeInsets.only(
bottom: i == grants.length - 1 ? 0 : 1.8.h,
),
child: GrantCard(grant: grants[i]),
),
],
);
}
}
// ─── Screen ───────────────────────────────────────────────────────────────────
@RoutePage()
class EvmGrantsScreen extends ConsumerWidget {
const EvmGrantsScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// Screen watches only the grant list for top-level state decisions
final grantsAsync = ref.watch(evmGrantsProvider);
Future<void> refresh() async {
await Future.wait([
ref.read(evmGrantsProvider.notifier).refresh(),
ref.read(walletAccessListProvider.notifier).refresh(),
]);
}
void showMessage(String message) {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message), behavior: SnackBarBehavior.floating),
);
}
Future<void> safeRefresh() async {
try {
await refresh();
} catch (e) {
showMessage(_formatError(e));
}
}
final grantsState = grantsAsync.asData?.value;
final grants = grantsState?.grants;
final content = switch (grantsAsync) {
AsyncLoading() when grantsState == null => const _StatePanel(
icon: Icons.hourglass_top,
title: 'Loading grants',
body: 'Pulling grant registry from Arbiter.',
busy: true,
),
AsyncError(:final error) => _StatePanel(
icon: Icons.sync_problem,
title: 'Grant registry unavailable',
body: _formatError(error),
actionLabel: 'Retry',
onAction: safeRefresh,
),
AsyncData(:final value) when value == null => _StatePanel(
icon: Icons.portable_wifi_off,
title: 'No active server connection',
body: 'Reconnect to Arbiter to list EVM grants.',
actionLabel: 'Refresh',
onAction: safeRefresh,
),
_ when grants != null && grants.isEmpty => _StatePanel(
icon: Icons.policy_outlined,
title: 'No grants yet',
body: 'Create a grant to allow SDK clients to sign transactions.',
actionLabel: 'Create grant',
onAction: () => context.router.push(const CreateEvmGrantRoute()),
),
_ => _GrantList(grants: grants ?? const []),
};
return Scaffold(
body: SafeArea(
child: RefreshIndicator.adaptive(
color: Palette.ink,
backgroundColor: Colors.white,
onRefresh: safeRefresh,
child: ListView(
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics(),
),
padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h),
children: [
PageHeader(
title: 'EVM Grants',
isBusy: grantsAsync.isLoading,
actions: [
FilledButton.icon(
onPressed: () =>
context.router.push(const CreateEvmGrantRoute()),
icon: const Icon(Icons.add_rounded),
label: const Text('Create grant'),
),
SizedBox(width: 1.w),
OutlinedButton.icon(
onPressed: safeRefresh,
style: OutlinedButton.styleFrom(
foregroundColor: Palette.ink,
side: BorderSide(color: Palette.line),
padding: EdgeInsets.symmetric(
horizontal: 1.4.w,
vertical: 1.2.h,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
icon: const Icon(Icons.refresh, size: 18),
label: const Text('Refresh'),
),
],
),
SizedBox(height: 1.8.h),
content,
],
),
),
),
);
}
}
```
- [ ] **Step 2: Verify**
```sh
cd useragent && flutter analyze lib/screens/dashboard/evm/grants/
```
Expected: no issues.
- [ ] **Step 3: Commit**
```sh
jj describe -m "feat(grants): add EvmGrantsScreen"
jj new
```
---
## Task 6: Wire router and dashboard tab
**Files:**
- Modify: `useragent/lib/router.dart`
- Modify: `useragent/lib/screens/dashboard.dart`
- Regenerated: `useragent/lib/router.gr.dart`
- [ ] **Step 1: Add route to `router.dart`**
Replace the contents of `useragent/lib/router.dart` with:
```dart
import 'package:auto_route/auto_route.dart';
import 'router.gr.dart';
@AutoRouterConfig(generateForDir: ['lib/screens'])
class Router extends RootStackRouter {
@override
List<AutoRoute> get routes => [
AutoRoute(page: Bootstrap.page, path: '/bootstrap', initial: true),
AutoRoute(page: ServerInfoSetupRoute.page, path: '/server-info'),
AutoRoute(page: ServerConnectionRoute.page, path: '/server-connection'),
AutoRoute(page: VaultSetupRoute.page, path: '/vault'),
AutoRoute(page: ClientDetailsRoute.page, path: '/clients/:clientId'),
AutoRoute(page: CreateEvmGrantRoute.page, path: '/evm-grants/create'),
AutoRoute(
page: DashboardRouter.page,
path: '/dashboard',
children: [
AutoRoute(page: EvmRoute.page, path: 'evm'),
AutoRoute(page: ClientsRoute.page, path: 'clients'),
AutoRoute(page: EvmGrantsRoute.page, path: 'grants'),
AutoRoute(page: AboutRoute.page, path: 'about'),
],
),
];
}
```
- [ ] **Step 2: Update `dashboard.dart`**
In `useragent/lib/screens/dashboard.dart`, replace the `routes` constant:
```dart
final routes = [
const EvmRoute(),
const ClientsRoute(),
const EvmGrantsRoute(),
const AboutRoute(),
];
```
And replace the `destinations` list inside `AdaptiveScaffold`:
```dart
destinations: const [
NavigationDestination(
icon: Icon(Icons.account_balance_wallet_outlined),
selectedIcon: Icon(Icons.account_balance_wallet),
label: 'Wallets',
),
NavigationDestination(
icon: Icon(Icons.devices_other_outlined),
selectedIcon: Icon(Icons.devices_other),
label: 'Clients',
),
NavigationDestination(
icon: Icon(Icons.policy_outlined),
selectedIcon: Icon(Icons.policy),
label: 'Grants',
),
NavigationDestination(
icon: Icon(Icons.info_outline),
selectedIcon: Icon(Icons.info),
label: 'About',
),
],
```
- [ ] **Step 3: Regenerate router**
```sh
cd useragent && dart run build_runner build --delete-conflicting-outputs
```
Expected: `lib/router.gr.dart` updated, `EvmGrantsRoute` now available, no errors.
- [ ] **Step 4: Full project verify**
```sh
cd useragent && flutter analyze
```
Expected: no issues.
- [ ] **Step 5: Commit**
```sh
jj describe -m "feat(nav): add Grants dashboard tab"
jj new
```

View File

@@ -0,0 +1,170 @@
# Grant Grid View — Design Spec
**Date:** 2026-03-28
## Overview
Add a "Grants" dashboard tab to the Flutter user-agent app that displays all EVM grants as a card-based grid. Each card shows a compact summary (type, chain, wallet address, client name) with a revoke action. The tab integrates into the existing `AdaptiveScaffold` navigation alongside Wallets, Clients, and About.
## Scope
- New `walletAccessListProvider` for fetching wallet access entries with their DB row IDs
- New `EvmGrantsScreen` as a dashboard tab
- Grant card widget with enriched display (type, chain, wallet, client)
- Revoke action wired to existing `executeRevokeEvmGrant` mutation
- Dashboard tab bar and router updated
- New token-transfer accent color added to `Palette`
**Out of scope:** Fixing grant creation (separate task).
---
## Data Layer
### `walletAccessListProvider`
**File:** `useragent/lib/providers/sdk_clients/wallet_access_list.dart`
- `@riverpod` class, watches `connectionManagerProvider.future`
- Returns `List<SdkClientWalletAccess>?` (null when not connected)
- Each entry: `.id` (wallet_access_id), `.access.walletId`, `.access.sdkClientId`
- Exposes a `refresh()` method following the same pattern as `EvmGrants.refresh()`
### Enrichment at render time (Approach A)
The `EvmGrantsScreen` watches four providers:
1. `evmGrantsProvider` — the grant list
2. `walletAccessListProvider` — to resolve wallet_access_id → (wallet_id, sdk_client_id)
3. `evmProvider` — to resolve wallet_id → wallet address
4. `sdkClientsProvider` — to resolve sdk_client_id → client name
All lookups are in-memory Maps built inside the build method; no extra model class needed.
Fallbacks:
- Wallet address not found → `"Access #N"` where N is the wallet_access_id
- Client name not found → `"Client #N"` where N is the sdk_client_id
---
## Route Structure
```
/dashboard
/evm ← existing (Wallets tab)
/clients ← existing (Clients tab)
/grants ← NEW (Grants tab)
/about ← existing
/evm-grants/create ← existing push route (unchanged)
```
### Changes to `router.dart`
Add inside dashboard children:
```dart
AutoRoute(page: EvmGrantsRoute.page, path: 'grants'),
```
### Changes to `dashboard.dart`
Add to `routes` list:
```dart
const EvmGrantsRoute()
```
Add `NavigationDestination`:
```dart
NavigationDestination(
icon: Icon(Icons.policy_outlined),
selectedIcon: Icon(Icons.policy),
label: 'Grants',
),
```
---
## Screen: `EvmGrantsScreen`
**File:** `useragent/lib/screens/dashboard/evm/grants/grants.dart`
```
Scaffold
└─ SafeArea
└─ RefreshIndicator.adaptive (refreshes evmGrantsProvider + walletAccessListProvider)
└─ ListView (BouncingScrollPhysics + AlwaysScrollableScrollPhysics)
├─ PageHeader
│ title: 'EVM Grants'
│ isBusy: evmGrantsProvider.isLoading
│ actions: [CreateGrantButton, RefreshButton]
├─ SizedBox(height: 1.8.h)
└─ <content>
```
### State handling
Matches the pattern from `EvmScreen` and `ClientsScreen`:
| State | Display |
|---|---|
| Loading (no data yet) | `_StatePanel` with spinner, "Loading grants" |
| Error | `_StatePanel` with coral icon, error message, Retry button |
| No connection | `_StatePanel`, "No active server connection" |
| Empty list | `_StatePanel`, "No grants yet", with Create Grant shortcut |
| Data | Column of `_GrantCard` widgets |
### Header actions
**CreateGrantButton:** `FilledButton.icon` with `Icons.add_rounded`, pushes `CreateEvmGrantRoute()` via `context.router.push(...)`.
**RefreshButton:** `OutlinedButton.icon` with `Icons.refresh`, calls `ref.read(evmGrantsProvider.notifier).refresh()`.
---
## Grant Card: `_GrantCard`
**Layout:**
```
Container (rounded 24, Palette.cream bg, Palette.line border)
└─ IntrinsicHeight > Row
├─ Accent strip (0.8.w wide, full height, rounded left)
└─ Padding > Column
├─ Row 1: TypeBadge + ChainChip + Spacer + RevokeButton
└─ Row 2: WalletText + "·" + ClientText
```
**Accent color by grant type:**
- Ether transfer → `Palette.coral`
- Token transfer → `Palette.token` (new entry in `Palette` — indigo, e.g. `Color(0xFF5C6BC0)`)
**TypeBadge:** Small pill container with accent color background at 15% opacity, accent-colored text. Label: `'Ether'` or `'Token'`.
**ChainChip:** Small container: `'Chain ${grant.shared.chainId}'`, muted ink color.
**WalletText:** Short hex address (`0xabc...def`) from wallet lookup, `bodySmall`, monospace font family.
**ClientText:** Client name from `sdkClientsProvider` lookup, or fallback string. `bodySmall`, muted ink.
**RevokeButton:**
- `OutlinedButton` with `Icons.block_rounded` icon, label `'Revoke'`
- `foregroundColor: Palette.coral`, `side: BorderSide(color: Palette.coral.withValues(alpha: 0.4))`
- Disabled (replaced with `CircularProgressIndicator`) while `revokeEvmGrantMutation` is pending — note: this is a single global mutation, so all revoke buttons disable while any revoke is in flight
- On press: calls `executeRevokeEvmGrant(ref, grantId: grant.id)`; shows `SnackBar` on error
---
## Adaptive Sizing
All sizing uses `sizer` units (`1.h`, `1.w`, etc.). No hardcoded pixel values.
---
## Files to Create / Modify
| File | Action |
|---|---|
| `lib/theme/palette.dart` | Modify — add `Palette.token` color |
| `lib/providers/sdk_clients/wallet_access_list.dart` | Create |
| `lib/screens/dashboard/evm/grants/grants.dart` | Create |
| `lib/router.dart` | Modify — add grants route to dashboard children |
| `lib/screens/dashboard.dart` | Modify — add tab to routes list and NavigationDestinations |

View File

@@ -8,18 +8,10 @@ backend = "aqua:ast-grep/ast-grep"
checksum = "sha256:5c830eae8456569e2f7212434ed9c238f58dca412d76045418ed6d394a755836" checksum = "sha256:5c830eae8456569e2f7212434ed9c238f58dca412d76045418ed6d394a755836"
url = "https://github.com/ast-grep/ast-grep/releases/download/0.42.0/app-aarch64-unknown-linux-gnu.zip" url = "https://github.com/ast-grep/ast-grep/releases/download/0.42.0/app-aarch64-unknown-linux-gnu.zip"
[tools.ast-grep."platforms.linux-arm64-musl"]
checksum = "sha256:5c830eae8456569e2f7212434ed9c238f58dca412d76045418ed6d394a755836"
url = "https://github.com/ast-grep/ast-grep/releases/download/0.42.0/app-aarch64-unknown-linux-gnu.zip"
[tools.ast-grep."platforms.linux-x64"] [tools.ast-grep."platforms.linux-x64"]
checksum = "sha256:e825a05603f0bcc4cd9076c4cc8c9abd6d008b7cd07d9aa3cc323ba4b8606651" checksum = "sha256:e825a05603f0bcc4cd9076c4cc8c9abd6d008b7cd07d9aa3cc323ba4b8606651"
url = "https://github.com/ast-grep/ast-grep/releases/download/0.42.0/app-x86_64-unknown-linux-gnu.zip" url = "https://github.com/ast-grep/ast-grep/releases/download/0.42.0/app-x86_64-unknown-linux-gnu.zip"
[tools.ast-grep."platforms.linux-x64-musl"]
checksum = "sha256:e825a05603f0bcc4cd9076c4cc8c9abd6d008b7cd07d9aa3cc323ba4b8606651"
url = "https://github.com/ast-grep/ast-grep/releases/download/0.42.0/app-x86_64-unknown-linux-gnu.zip"
[tools.ast-grep."platforms.macos-arm64"] [tools.ast-grep."platforms.macos-arm64"]
checksum = "sha256:fc300d5293b1c770a5aece03a8a193b92e71e87cec726c28096990691a582620" checksum = "sha256:fc300d5293b1c770a5aece03a8a193b92e71e87cec726c28096990691a582620"
url = "https://github.com/ast-grep/ast-grep/releases/download/0.42.0/app-aarch64-apple-darwin.zip" url = "https://github.com/ast-grep/ast-grep/releases/download/0.42.0/app-aarch64-apple-darwin.zip"
@@ -40,6 +32,10 @@ backend = "cargo:cargo-audit"
version = "0.13.9" version = "0.13.9"
backend = "cargo:cargo-edit" backend = "cargo:cargo-edit"
[[tools."cargo:cargo-features"]]
version = "1.0.0"
backend = "cargo:cargo-features"
[[tools."cargo:cargo-features-manager"]] [[tools."cargo:cargo-features-manager"]]
version = "0.11.1" version = "0.11.1"
backend = "cargo:cargo-features-manager" backend = "cargo:cargo-features-manager"
@@ -53,13 +49,21 @@ version = "0.9.126"
backend = "cargo:cargo-nextest" backend = "cargo:cargo-nextest"
[[tools."cargo:cargo-shear"]] [[tools."cargo:cargo-shear"]]
version = "1.11.2" version = "1.9.1"
backend = "cargo:cargo-shear" backend = "cargo:cargo-shear"
[[tools."cargo:cargo-vet"]] [[tools."cargo:cargo-vet"]]
version = "0.10.2" version = "0.10.2"
backend = "cargo:cargo-vet" backend = "cargo:cargo-vet"
[[tools."cargo:diesel-cli"]]
version = "2.3.6"
backend = "cargo:diesel-cli"
[tools."cargo:diesel-cli".options]
default-features = "false"
features = "sqlite,sqlite-bundled"
[[tools."cargo:diesel_cli"]] [[tools."cargo:diesel_cli"]]
version = "2.3.6" version = "2.3.6"
backend = "cargo:diesel_cli" backend = "cargo:diesel_cli"
@@ -68,6 +72,10 @@ backend = "cargo:diesel_cli"
default-features = "false" default-features = "false"
features = "sqlite,sqlite-bundled" features = "sqlite,sqlite-bundled"
[[tools."cargo:rinf_cli"]]
version = "8.9.1"
backend = "cargo:rinf_cli"
[[tools.flutter]] [[tools.flutter]]
version = "3.38.9-stable" version = "3.38.9-stable"
backend = "asdf:flutter" backend = "asdf:flutter"
@@ -80,18 +88,10 @@ backend = "aqua:protocolbuffers/protobuf/protoc"
checksum = "sha256:2594ff4fcae8cb57310d394d0961b236190ad9c5efbfdf1f597ea471d424fe79" checksum = "sha256:2594ff4fcae8cb57310d394d0961b236190ad9c5efbfdf1f597ea471d424fe79"
url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.6/protoc-29.6-linux-aarch_64.zip" url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.6/protoc-29.6-linux-aarch_64.zip"
[tools.protoc."platforms.linux-arm64-musl"]
checksum = "sha256:2594ff4fcae8cb57310d394d0961b236190ad9c5efbfdf1f597ea471d424fe79"
url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.6/protoc-29.6-linux-aarch_64.zip"
[tools.protoc."platforms.linux-x64"] [tools.protoc."platforms.linux-x64"]
checksum = "sha256:48785a926e73ffa3f68e2f22b14e7b849620c7a1d36809ac9249a5495e280323" checksum = "sha256:48785a926e73ffa3f68e2f22b14e7b849620c7a1d36809ac9249a5495e280323"
url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.6/protoc-29.6-linux-x86_64.zip" url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.6/protoc-29.6-linux-x86_64.zip"
[tools.protoc."platforms.linux-x64-musl"]
checksum = "sha256:48785a926e73ffa3f68e2f22b14e7b849620c7a1d36809ac9249a5495e280323"
url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.6/protoc-29.6-linux-x86_64.zip"
[tools.protoc."platforms.macos-arm64"] [tools.protoc."platforms.macos-arm64"]
checksum = "sha256:b9576b5fa1a1ef3fe13a8c91d9d8204b46545759bea5ae155cd6ba2ea4cdaeed" checksum = "sha256:b9576b5fa1a1ef3fe13a8c91d9d8204b46545759bea5ae155cd6ba2ea4cdaeed"
url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.6/protoc-29.6-osx-aarch_64.zip" url = "https://github.com/protocolbuffers/protobuf/releases/download/v29.6/protoc-29.6-osx-aarch_64.zip"
@@ -109,32 +109,24 @@ version = "3.14.3"
backend = "core:python" backend = "core:python"
[tools.python."platforms.linux-arm64"] [tools.python."platforms.linux-arm64"]
checksum = "sha256:53700338695e402a1a1fe22be4a41fbdacc70e22bb308a48eca8ed67cb7992be" checksum = "sha256:be0f4dc2932f762292b27d46ea7d3e8e66ddf3969a5eb0254a229015ed402625"
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260324/cpython-3.14.3+20260324-aarch64-unknown-linux-gnu-install_only_stripped.tar.gz" url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260303/cpython-3.14.3+20260303-aarch64-unknown-linux-gnu-install_only_stripped.tar.gz"
[tools.python."platforms.linux-arm64-musl"]
checksum = "sha256:53700338695e402a1a1fe22be4a41fbdacc70e22bb308a48eca8ed67cb7992be"
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260324/cpython-3.14.3+20260324-aarch64-unknown-linux-gnu-install_only_stripped.tar.gz"
[tools.python."platforms.linux-x64"] [tools.python."platforms.linux-x64"]
checksum = "sha256:d7a9f970914bb4c88756fe3bdcc186d4feb90e9500e54f1db47dae4dc9687e39" checksum = "sha256:0a73413f89efd417871876c9accaab28a9d1e3cd6358fbfff171a38ec99302f0"
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260324/cpython-3.14.3+20260324-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz" url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260303/cpython-3.14.3+20260303-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz"
[tools.python."platforms.linux-x64-musl"]
checksum = "sha256:d7a9f970914bb4c88756fe3bdcc186d4feb90e9500e54f1db47dae4dc9687e39"
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260324/cpython-3.14.3+20260324-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz"
[tools.python."platforms.macos-arm64"] [tools.python."platforms.macos-arm64"]
checksum = "sha256:c43aecde4a663aebff99b9b83da0efec506479f1c3f98331442f33d2c43501f9" checksum = "sha256:4703cdf18b26798fde7b49b6b66149674c25f97127be6a10dbcf29309bdcdcdb"
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260324/cpython-3.14.3+20260324-aarch64-apple-darwin-install_only_stripped.tar.gz" url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260303/cpython-3.14.3+20260303-aarch64-apple-darwin-install_only_stripped.tar.gz"
[tools.python."platforms.macos-x64"] [tools.python."platforms.macos-x64"]
checksum = "sha256:9ab41dbc2f100a2a45d1833b9c11165f51051c558b5213eda9a9731d5948a0c0" checksum = "sha256:76f1cc26e3d262eae8ca546a93e8bded10cf0323613f7e246fea2e10a8115eb7"
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260324/cpython-3.14.3+20260324-x86_64-apple-darwin-install_only_stripped.tar.gz" url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260303/cpython-3.14.3+20260303-x86_64-apple-darwin-install_only_stripped.tar.gz"
[tools.python."platforms.windows-x64"] [tools.python."platforms.windows-x64"]
checksum = "sha256:bbe19034b35b0267176a7442575ae7dc6343480fd4d35598cb7700173d431e09" checksum = "sha256:950c5f21a015c1bdd1337f233456df2470fab71e4d794407d27a84cb8b9909a0"
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260324/cpython-3.14.3+20260324-x86_64-pc-windows-msvc-install_only_stripped.tar.gz" url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260303/cpython-3.14.3+20260303-x86_64-pc-windows-msvc-install_only_stripped.tar.gz"
[[tools.rust]] [[tools.rust]]
version = "1.93.0" version = "1.93.0"

View File

@@ -14,9 +14,9 @@ ast-grep = "0.42.0"
"cargo:cargo-edit" = "0.13.9" "cargo:cargo-edit" = "0.13.9"
[tasks.codegen] [tasks.codegen]
sources = ['protobufs/*.proto', 'protobufs/**/*.proto'] sources = ['protobufs/*.proto']
outputs = ['useragent/lib/proto/**'] outputs = ['useragent/lib/proto/*']
run = ''' run = '''
dart pub global activate protoc_plugin && \ dart pub global activate protoc_plugin && \
protoc --dart_out=grpc:useragent/lib/proto --proto_path=protobufs/ $(find protobufs -name '*.proto' | sort) protoc --dart_out=grpc:useragent/lib/proto --proto_path=protobufs/ protobufs/*.proto
''' '''

View File

@@ -2,24 +2,63 @@ syntax = "proto3";
package arbiter.client; package arbiter.client;
import "client/auth.proto"; import "evm.proto";
import "client/evm.proto"; import "google/protobuf/empty.proto";
import "client/vault.proto";
message ClientInfo {
string name = 1;
optional string description = 2;
optional string version = 3;
}
message AuthChallengeRequest {
bytes pubkey = 1;
ClientInfo client_info = 2;
}
message AuthChallenge {
bytes pubkey = 1;
int32 nonce = 2;
}
message AuthChallengeSolution {
bytes signature = 1;
}
enum AuthResult {
AUTH_RESULT_UNSPECIFIED = 0;
AUTH_RESULT_SUCCESS = 1;
AUTH_RESULT_INVALID_KEY = 2;
AUTH_RESULT_INVALID_SIGNATURE = 3;
AUTH_RESULT_APPROVAL_DENIED = 4;
AUTH_RESULT_NO_USER_AGENTS_ONLINE = 5;
AUTH_RESULT_INTERNAL = 6;
}
enum VaultState {
VAULT_STATE_UNSPECIFIED = 0;
VAULT_STATE_UNBOOTSTRAPPED = 1;
VAULT_STATE_SEALED = 2;
VAULT_STATE_UNSEALED = 3;
VAULT_STATE_ERROR = 4;
}
message ClientRequest { message ClientRequest {
int32 request_id = 4; int32 request_id = 4;
oneof payload { oneof payload {
auth.Request auth = 1; AuthChallengeRequest auth_challenge_request = 1;
vault.Request vault = 2; AuthChallengeSolution auth_challenge_solution = 2;
evm.Request evm = 3; google.protobuf.Empty query_vault_state = 3;
} }
} }
message ClientResponse { message ClientResponse {
optional int32 request_id = 7; optional int32 request_id = 7;
oneof payload { oneof payload {
auth.Response auth = 1; AuthChallenge auth_challenge = 1;
vault.Response vault = 2; AuthResult auth_result = 2;
evm.Response evm = 3; arbiter.evm.EvmSignTransactionResponse evm_sign_transaction = 3;
arbiter.evm.EvmAnalyzeTransactionResponse evm_analyze_transaction = 4;
VaultState vault_state = 6;
} }
} }

View File

@@ -1,43 +0,0 @@
syntax = "proto3";
package arbiter.client.auth;
import "shared/client.proto";
message AuthChallengeRequest {
bytes pubkey = 1;
arbiter.shared.ClientInfo client_info = 2;
}
message AuthChallenge {
bytes pubkey = 1;
int32 nonce = 2;
}
message AuthChallengeSolution {
bytes signature = 1;
}
enum AuthResult {
AUTH_RESULT_UNSPECIFIED = 0;
AUTH_RESULT_SUCCESS = 1;
AUTH_RESULT_INVALID_KEY = 2;
AUTH_RESULT_INVALID_SIGNATURE = 3;
AUTH_RESULT_APPROVAL_DENIED = 4;
AUTH_RESULT_NO_USER_AGENTS_ONLINE = 5;
AUTH_RESULT_INTERNAL = 6;
}
message Request {
oneof payload {
AuthChallengeRequest challenge_request = 1;
AuthChallengeSolution challenge_solution = 2;
}
}
message Response {
oneof payload {
AuthChallenge challenge = 1;
AuthResult result = 2;
}
}

View File

@@ -1,19 +0,0 @@
syntax = "proto3";
package arbiter.client.evm;
import "evm.proto";
message Request {
oneof payload {
arbiter.evm.EvmSignTransactionRequest sign_transaction = 1;
arbiter.evm.EvmAnalyzeTransactionRequest analyze_transaction = 2;
}
}
message Response {
oneof payload {
arbiter.evm.EvmSignTransactionResponse sign_transaction = 1;
arbiter.evm.EvmAnalyzeTransactionResponse analyze_transaction = 2;
}
}

View File

@@ -1,18 +0,0 @@
syntax = "proto3";
package arbiter.client.vault;
import "google/protobuf/empty.proto";
import "shared/vault.proto";
message Request {
oneof payload {
google.protobuf.Empty query_state = 1;
}
}
message Response {
oneof payload {
arbiter.shared.VaultState state = 1;
}
}

View File

@@ -4,7 +4,6 @@ package arbiter.evm;
import "google/protobuf/empty.proto"; import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto"; import "google/protobuf/timestamp.proto";
import "shared/evm.proto";
enum EvmError { enum EvmError {
EVM_ERROR_UNSPECIFIED = 0; EVM_ERROR_UNSPECIFIED = 0;
@@ -75,6 +74,70 @@ message SpecificGrant {
} }
} }
message EtherTransferMeaning {
bytes to = 1; // 20-byte Ethereum address
bytes value = 2; // U256 as big-endian bytes
}
message TokenInfo {
string symbol = 1;
bytes address = 2; // 20-byte Ethereum address
uint64 chain_id = 3;
}
// Mirror of token_transfers::Meaning
message TokenTransferMeaning {
TokenInfo token = 1;
bytes to = 2; // 20-byte Ethereum address
bytes value = 3; // U256 as big-endian bytes
}
// Mirror of policies::SpecificMeaning
message SpecificMeaning {
oneof meaning {
EtherTransferMeaning ether_transfer = 1;
TokenTransferMeaning token_transfer = 2;
}
}
// --- Eval error types ---
message GasLimitExceededViolation {
optional bytes max_gas_fee_per_gas = 1; // U256 as big-endian bytes
optional bytes max_priority_fee_per_gas = 2; // U256 as big-endian bytes
}
message EvalViolation {
oneof kind {
bytes invalid_target = 1; // 20-byte Ethereum address
GasLimitExceededViolation gas_limit_exceeded = 2;
google.protobuf.Empty rate_limit_exceeded = 3;
google.protobuf.Empty volumetric_limit_exceeded = 4;
google.protobuf.Empty invalid_time = 5;
google.protobuf.Empty invalid_transaction_type = 6;
}
}
// Transaction was classified but no grant covers it
message NoMatchingGrantError {
SpecificMeaning meaning = 1;
}
// Transaction was classified and a grant was found, but constraints were violated
message PolicyViolationsError {
SpecificMeaning meaning = 1;
repeated EvalViolation violations = 2;
}
// top-level error returned when transaction evaluation fails
message TransactionEvalError {
oneof kind {
google.protobuf.Empty contract_creation_not_supported = 1;
google.protobuf.Empty unsupported_transaction_type = 2;
NoMatchingGrantError no_matching_grant = 3;
PolicyViolationsError policy_violations = 4;
}
}
// --- UserAgent grant management --- // --- UserAgent grant management ---
message EvmGrantCreateRequest { message EvmGrantCreateRequest {
SharedSettings shared = 1; SharedSettings shared = 1;
@@ -134,7 +197,7 @@ message EvmSignTransactionRequest {
message EvmSignTransactionResponse { message EvmSignTransactionResponse {
oneof result { oneof result {
bytes signature = 1; // 65-byte signature: r[32] || s[32] || v[1] bytes signature = 1; // 65-byte signature: r[32] || s[32] || v[1]
arbiter.shared.evm.TransactionEvalError eval_error = 2; TransactionEvalError eval_error = 2;
EvmError error = 3; EvmError error = 3;
} }
} }
@@ -146,8 +209,8 @@ message EvmAnalyzeTransactionRequest {
message EvmAnalyzeTransactionResponse { message EvmAnalyzeTransactionResponse {
oneof result { oneof result {
arbiter.shared.evm.SpecificMeaning meaning = 1; SpecificMeaning meaning = 1;
arbiter.shared.evm.TransactionEvalError eval_error = 2; TransactionEvalError eval_error = 2;
EvmError error = 3; EvmError error = 3;
} }
} }

View File

@@ -1,9 +0,0 @@
syntax = "proto3";
package arbiter.shared;
message ClientInfo {
string name = 1;
optional string description = 2;
optional string version = 3;
}

View File

@@ -1,68 +0,0 @@
syntax = "proto3";
package arbiter.shared.evm;
import "google/protobuf/empty.proto";
message EtherTransferMeaning {
bytes to = 1; // 20-byte Ethereum address
bytes value = 2; // U256 as big-endian bytes
}
message TokenInfo {
string symbol = 1;
bytes address = 2; // 20-byte Ethereum address
uint64 chain_id = 3;
}
// Mirror of token_transfers::Meaning
message TokenTransferMeaning {
TokenInfo token = 1;
bytes to = 2; // 20-byte Ethereum address
bytes value = 3; // U256 as big-endian bytes
}
// Mirror of policies::SpecificMeaning
message SpecificMeaning {
oneof meaning {
EtherTransferMeaning ether_transfer = 1;
TokenTransferMeaning token_transfer = 2;
}
}
message GasLimitExceededViolation {
optional bytes max_gas_fee_per_gas = 1; // U256 as big-endian bytes
optional bytes max_priority_fee_per_gas = 2; // U256 as big-endian bytes
}
message EvalViolation {
oneof kind {
bytes invalid_target = 1; // 20-byte Ethereum address
GasLimitExceededViolation gas_limit_exceeded = 2;
google.protobuf.Empty rate_limit_exceeded = 3;
google.protobuf.Empty volumetric_limit_exceeded = 4;
google.protobuf.Empty invalid_time = 5;
google.protobuf.Empty invalid_transaction_type = 6;
}
}
// Transaction was classified but no grant covers it
message NoMatchingGrantError {
SpecificMeaning meaning = 1;
}
// Transaction was classified and a grant was found, but constraints were violated
message PolicyViolationsError {
SpecificMeaning meaning = 1;
repeated EvalViolation violations = 2;
}
// top-level error returned when transaction evaluation fails
message TransactionEvalError {
oneof kind {
google.protobuf.Empty contract_creation_not_supported = 1;
google.protobuf.Empty unsupported_transaction_type = 2;
NoMatchingGrantError no_matching_grant = 3;
PolicyViolationsError policy_violations = 4;
}
}

View File

@@ -1,11 +0,0 @@
syntax = "proto3";
package arbiter.shared;
enum VaultState {
VAULT_STATE_UNSPECIFIED = 0;
VAULT_STATE_UNBOOTSTRAPPED = 1;
VAULT_STATE_SEALED = 2;
VAULT_STATE_UNSEALED = 3;
VAULT_STATE_ERROR = 4;
}

View File

@@ -2,27 +2,198 @@ syntax = "proto3";
package arbiter.user_agent; package arbiter.user_agent;
import "user_agent/auth.proto"; import "client.proto";
import "user_agent/evm.proto"; import "evm.proto";
import "user_agent/sdk_client.proto"; import "google/protobuf/empty.proto";
import "user_agent/vault/vault.proto";
enum KeyType {
KEY_TYPE_UNSPECIFIED = 0;
KEY_TYPE_ED25519 = 1;
KEY_TYPE_ECDSA_SECP256K1 = 2;
KEY_TYPE_RSA = 3;
}
// --- SDK client management ---
enum SdkClientError {
SDK_CLIENT_ERROR_UNSPECIFIED = 0;
SDK_CLIENT_ERROR_ALREADY_EXISTS = 1;
SDK_CLIENT_ERROR_NOT_FOUND = 2;
SDK_CLIENT_ERROR_HAS_RELATED_DATA = 3; // hard-delete blocked by FK (client has grants or transaction logs)
SDK_CLIENT_ERROR_INTERNAL = 4;
}
message SdkClientRevokeRequest {
int32 client_id = 1;
}
message SdkClientEntry {
int32 id = 1;
bytes pubkey = 2;
arbiter.client.ClientInfo info = 3;
int32 created_at = 4;
}
message SdkClientList {
repeated SdkClientEntry clients = 1;
}
message SdkClientRevokeResponse {
oneof result {
google.protobuf.Empty ok = 1;
SdkClientError error = 2;
}
}
message SdkClientListResponse {
oneof result {
SdkClientList clients = 1;
SdkClientError error = 2;
}
}
message AuthChallengeRequest {
bytes pubkey = 1;
optional string bootstrap_token = 2;
KeyType key_type = 3;
}
message AuthChallenge {
int32 nonce = 2;
reserved 1;
}
message AuthChallengeSolution {
bytes signature = 1;
}
enum AuthResult {
AUTH_RESULT_UNSPECIFIED = 0;
AUTH_RESULT_SUCCESS = 1;
AUTH_RESULT_INVALID_KEY = 2;
AUTH_RESULT_INVALID_SIGNATURE = 3;
AUTH_RESULT_BOOTSTRAP_REQUIRED = 4;
AUTH_RESULT_TOKEN_INVALID = 5;
AUTH_RESULT_INTERNAL = 6;
}
message UnsealStart {
bytes client_pubkey = 1;
}
message UnsealStartResponse {
bytes server_pubkey = 1;
}
message UnsealEncryptedKey {
bytes nonce = 1;
bytes ciphertext = 2;
bytes associated_data = 3;
}
message BootstrapEncryptedKey {
bytes nonce = 1;
bytes ciphertext = 2;
bytes associated_data = 3;
}
enum UnsealResult {
UNSEAL_RESULT_UNSPECIFIED = 0;
UNSEAL_RESULT_SUCCESS = 1;
UNSEAL_RESULT_INVALID_KEY = 2;
UNSEAL_RESULT_UNBOOTSTRAPPED = 3;
}
enum BootstrapResult {
BOOTSTRAP_RESULT_UNSPECIFIED = 0;
BOOTSTRAP_RESULT_SUCCESS = 1;
BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED = 2;
BOOTSTRAP_RESULT_INVALID_KEY = 3;
}
enum VaultState {
VAULT_STATE_UNSPECIFIED = 0;
VAULT_STATE_UNBOOTSTRAPPED = 1;
VAULT_STATE_SEALED = 2;
VAULT_STATE_UNSEALED = 3;
VAULT_STATE_ERROR = 4;
}
message SdkClientConnectionRequest {
bytes pubkey = 1;
arbiter.client.ClientInfo info = 2;
}
message SdkClientConnectionResponse {
bool approved = 1;
bytes pubkey = 2;
}
message SdkClientConnectionCancel {
bytes pubkey = 1;
}
message WalletAccess {
int32 wallet_id = 1;
int32 sdk_client_id = 2;
}
message SdkClientWalletAccess {
int32 id = 1;
WalletAccess access = 2;
}
message SdkClientGrantWalletAccess {
repeated WalletAccess accesses = 1;
}
message SdkClientRevokeWalletAccess {
repeated int32 accesses = 1;
}
message ListWalletAccessResponse {
repeated SdkClientWalletAccess accesses = 1;
}
message UserAgentRequest { message UserAgentRequest {
int32 id = 16; int32 id = 16;
oneof payload { oneof payload {
auth.Request auth = 1; AuthChallengeRequest auth_challenge_request = 1;
vault.Request vault = 2; AuthChallengeSolution auth_challenge_solution = 2;
evm.Request evm = 3; UnsealStart unseal_start = 3;
sdk_client.Request sdk_client = 4; UnsealEncryptedKey unseal_encrypted_key = 4;
google.protobuf.Empty query_vault_state = 5;
google.protobuf.Empty evm_wallet_create = 6;
google.protobuf.Empty evm_wallet_list = 7;
arbiter.evm.EvmGrantCreateRequest evm_grant_create = 8;
arbiter.evm.EvmGrantDeleteRequest evm_grant_delete = 9;
arbiter.evm.EvmGrantListRequest evm_grant_list = 10;
SdkClientConnectionResponse sdk_client_connection_response = 11;
SdkClientRevokeRequest sdk_client_revoke = 12;
google.protobuf.Empty sdk_client_list = 13;
BootstrapEncryptedKey bootstrap_encrypted_key = 14;
SdkClientGrantWalletAccess grant_wallet_access = 15;
SdkClientRevokeWalletAccess revoke_wallet_access = 17;
google.protobuf.Empty list_wallet_access = 18;
} }
} }
message UserAgentResponse { message UserAgentResponse {
optional int32 id = 16; optional int32 id = 16;
oneof payload { oneof payload {
auth.Response auth = 1; AuthChallenge auth_challenge = 1;
vault.Response vault = 2; AuthResult auth_result = 2;
evm.Response evm = 3; UnsealStartResponse unseal_start_response = 3;
sdk_client.Response sdk_client = 4; UnsealResult unseal_result = 4;
VaultState vault_state = 5;
arbiter.evm.WalletCreateResponse evm_wallet_create = 6;
arbiter.evm.WalletListResponse evm_wallet_list = 7;
arbiter.evm.EvmGrantCreateResponse evm_grant_create = 8;
arbiter.evm.EvmGrantDeleteResponse evm_grant_delete = 9;
arbiter.evm.EvmGrantListResponse evm_grant_list = 10;
SdkClientConnectionRequest sdk_client_connection_request = 11;
SdkClientConnectionCancel sdk_client_connection_cancel = 12;
SdkClientRevokeResponse sdk_client_revoke_response = 13;
SdkClientListResponse sdk_client_list_response = 14;
BootstrapResult bootstrap_result = 15;
ListWalletAccessResponse list_wallet_access_response = 17;
} }
} }

View File

@@ -1,48 +0,0 @@
syntax = "proto3";
package arbiter.user_agent.auth;
enum KeyType {
KEY_TYPE_UNSPECIFIED = 0;
KEY_TYPE_ED25519 = 1;
KEY_TYPE_ECDSA_SECP256K1 = 2;
KEY_TYPE_RSA = 3;
}
message AuthChallengeRequest {
bytes pubkey = 1;
optional string bootstrap_token = 2;
KeyType key_type = 3;
}
message AuthChallenge {
int32 nonce = 1;
}
message AuthChallengeSolution {
bytes signature = 1;
}
enum AuthResult {
AUTH_RESULT_UNSPECIFIED = 0;
AUTH_RESULT_SUCCESS = 1;
AUTH_RESULT_INVALID_KEY = 2;
AUTH_RESULT_INVALID_SIGNATURE = 3;
AUTH_RESULT_BOOTSTRAP_REQUIRED = 4;
AUTH_RESULT_TOKEN_INVALID = 5;
AUTH_RESULT_INTERNAL = 6;
}
message Request {
oneof payload {
AuthChallengeRequest challenge_request = 1;
AuthChallengeSolution challenge_solution = 2;
}
}
message Response {
oneof payload {
AuthChallenge challenge = 1;
AuthResult result = 2;
}
}

View File

@@ -1,33 +0,0 @@
syntax = "proto3";
package arbiter.user_agent.evm;
import "evm.proto";
import "google/protobuf/empty.proto";
message SignTransactionRequest {
int32 client_id = 1;
arbiter.evm.EvmSignTransactionRequest request = 2;
}
message Request {
oneof payload {
google.protobuf.Empty wallet_create = 1;
google.protobuf.Empty wallet_list = 2;
arbiter.evm.EvmGrantCreateRequest grant_create = 3;
arbiter.evm.EvmGrantDeleteRequest grant_delete = 4;
arbiter.evm.EvmGrantListRequest grant_list = 5;
SignTransactionRequest sign_transaction = 6;
}
}
message Response {
oneof payload {
arbiter.evm.WalletCreateResponse wallet_create = 1;
arbiter.evm.WalletListResponse wallet_list = 2;
arbiter.evm.EvmGrantCreateResponse grant_create = 3;
arbiter.evm.EvmGrantDeleteResponse grant_delete = 4;
arbiter.evm.EvmGrantListResponse grant_list = 5;
arbiter.evm.EvmSignTransactionResponse sign_transaction = 6;
}
}

View File

@@ -1,100 +0,0 @@
syntax = "proto3";
package arbiter.user_agent.sdk_client;
import "shared/client.proto";
import "google/protobuf/empty.proto";
enum Error {
ERROR_UNSPECIFIED = 0;
ERROR_ALREADY_EXISTS = 1;
ERROR_NOT_FOUND = 2;
ERROR_HAS_RELATED_DATA = 3; // hard-delete blocked by FK (client has grants or transaction logs)
ERROR_INTERNAL = 4;
}
message RevokeRequest {
int32 client_id = 1;
}
message Entry {
int32 id = 1;
bytes pubkey = 2;
arbiter.shared.ClientInfo info = 3;
int32 created_at = 4;
}
message List {
repeated Entry clients = 1;
}
message RevokeResponse {
oneof result {
google.protobuf.Empty ok = 1;
Error error = 2;
}
}
message ListResponse {
oneof result {
List clients = 1;
Error error = 2;
}
}
message ConnectionRequest {
bytes pubkey = 1;
arbiter.shared.ClientInfo info = 2;
}
message ConnectionResponse {
bool approved = 1;
bytes pubkey = 2;
}
message ConnectionCancel {
bytes pubkey = 1;
}
message WalletAccess {
int32 wallet_id = 1;
int32 sdk_client_id = 2;
}
message WalletAccessEntry {
int32 id = 1;
WalletAccess access = 2;
}
message GrantWalletAccess {
repeated WalletAccess accesses = 1;
}
message RevokeWalletAccess {
repeated int32 accesses = 1;
}
message ListWalletAccessResponse {
repeated WalletAccessEntry accesses = 1;
}
message Request {
oneof payload {
ConnectionResponse connection_response = 1;
RevokeRequest revoke = 2;
google.protobuf.Empty list = 3;
GrantWalletAccess grant_wallet_access = 4;
RevokeWalletAccess revoke_wallet_access = 5;
google.protobuf.Empty list_wallet_access = 6;
}
}
message Response {
oneof payload {
ConnectionRequest connection_request = 1;
ConnectionCancel connection_cancel = 2;
RevokeResponse revoke = 3;
ListResponse list = 4;
ListWalletAccessResponse list_wallet_access = 5;
}
}

View File

@@ -1,24 +0,0 @@
syntax = "proto3";
package arbiter.user_agent.vault.bootstrap;
message BootstrapEncryptedKey {
bytes nonce = 1;
bytes ciphertext = 2;
bytes associated_data = 3;
}
enum BootstrapResult {
BOOTSTRAP_RESULT_UNSPECIFIED = 0;
BOOTSTRAP_RESULT_SUCCESS = 1;
BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED = 2;
BOOTSTRAP_RESULT_INVALID_KEY = 3;
}
message Request {
BootstrapEncryptedKey encrypted_key = 2;
}
message Response {
BootstrapResult result = 1;
}

View File

@@ -1,37 +0,0 @@
syntax = "proto3";
package arbiter.user_agent.vault.unseal;
message UnsealStart {
bytes client_pubkey = 1;
}
message UnsealStartResponse {
bytes server_pubkey = 1;
}
message UnsealEncryptedKey {
bytes nonce = 1;
bytes ciphertext = 2;
bytes associated_data = 3;
}
enum UnsealResult {
UNSEAL_RESULT_UNSPECIFIED = 0;
UNSEAL_RESULT_SUCCESS = 1;
UNSEAL_RESULT_INVALID_KEY = 2;
UNSEAL_RESULT_UNBOOTSTRAPPED = 3;
}
message Request {
oneof payload {
UnsealStart start = 1;
UnsealEncryptedKey encrypted_key = 2;
}
}
message Response {
oneof payload {
UnsealStartResponse start = 1;
UnsealResult result = 2;
}
}

View File

@@ -1,24 +0,0 @@
syntax = "proto3";
package arbiter.user_agent.vault;
import "google/protobuf/empty.proto";
import "shared/vault.proto";
import "user_agent/vault/bootstrap.proto";
import "user_agent/vault/unseal.proto";
message Request {
oneof payload {
google.protobuf.Empty query_state = 1;
unseal.Request unseal = 2;
bootstrap.Request bootstrap = 3;
}
}
message Response {
oneof payload {
arbiter.shared.VaultState state = 1;
unseal.Response unseal = 2;
bootstrap.Response bootstrap = 3;
}
}

1
server/Cargo.lock generated
View File

@@ -737,6 +737,7 @@ dependencies = [
"ed25519-dalek", "ed25519-dalek",
"fatality", "fatality",
"futures", "futures",
"hmac",
"insta", "insta",
"k256", "k256",
"kameo", "kameo",

View File

@@ -1,17 +1,9 @@
use arbiter_proto::{ use arbiter_proto::{
ClientMetadata, format_challenge, ClientMetadata, format_challenge,
proto::{ proto::client::{
client::{ AuthChallengeRequest, AuthChallengeSolution, AuthResult, ClientInfo as ProtoClientInfo,
ClientRequest, ClientRequest, client_request::Payload as ClientRequestPayload,
auth::{ client_response::Payload as ClientResponsePayload,
self as proto_auth, AuthChallenge, AuthChallengeRequest, AuthChallengeSolution,
AuthResult, request::Payload as AuthRequestPayload,
response::Payload as AuthResponsePayload,
},
client_request::Payload as ClientRequestPayload,
client_response::Payload as ClientResponsePayload,
},
shared::ClientInfo as ProtoClientInfo,
}, },
}; };
use ed25519_dalek::Signer as _; use ed25519_dalek::Signer as _;
@@ -59,16 +51,16 @@ async fn send_auth_challenge_request(
transport transport
.send(ClientRequest { .send(ClientRequest {
request_id: next_request_id(), request_id: next_request_id(),
payload: Some(ClientRequestPayload::Auth(proto_auth::Request { payload: Some(ClientRequestPayload::AuthChallengeRequest(
payload: Some(AuthRequestPayload::ChallengeRequest(AuthChallengeRequest { AuthChallengeRequest {
pubkey: key.verifying_key().to_bytes().to_vec(), pubkey: key.verifying_key().to_bytes().to_vec(),
client_info: Some(ProtoClientInfo { client_info: Some(ProtoClientInfo {
name: metadata.name, name: metadata.name,
description: metadata.description, description: metadata.description,
version: metadata.version, version: metadata.version,
}), }),
})), },
})), )),
}) })
.await .await
.map_err(|_| AuthError::UnexpectedAuthResponse) .map_err(|_| AuthError::UnexpectedAuthResponse)
@@ -76,7 +68,7 @@ async fn send_auth_challenge_request(
async fn receive_auth_challenge( async fn receive_auth_challenge(
transport: &mut ClientTransport, transport: &mut ClientTransport,
) -> std::result::Result<AuthChallenge, AuthError> { ) -> std::result::Result<arbiter_proto::proto::client::AuthChallenge, AuthError> {
let response = transport let response = transport
.recv() .recv()
.await .await
@@ -84,11 +76,8 @@ async fn receive_auth_challenge(
let payload = response.payload.ok_or(AuthError::MissingAuthChallenge)?; let payload = response.payload.ok_or(AuthError::MissingAuthChallenge)?;
match payload { match payload {
ClientResponsePayload::Auth(response) => match response.payload { ClientResponsePayload::AuthChallenge(challenge) => Ok(challenge),
Some(AuthResponsePayload::Challenge(challenge)) => Ok(challenge), ClientResponsePayload::AuthResult(result) => Err(map_auth_result(result)),
Some(AuthResponsePayload::Result(result)) => Err(map_auth_result(result)),
None => Err(AuthError::MissingAuthChallenge),
},
_ => Err(AuthError::UnexpectedAuthResponse), _ => Err(AuthError::UnexpectedAuthResponse),
} }
} }
@@ -96,7 +85,7 @@ async fn receive_auth_challenge(
async fn send_auth_challenge_solution( async fn send_auth_challenge_solution(
transport: &mut ClientTransport, transport: &mut ClientTransport,
key: &ed25519_dalek::SigningKey, key: &ed25519_dalek::SigningKey,
challenge: AuthChallenge, challenge: arbiter_proto::proto::client::AuthChallenge,
) -> std::result::Result<(), AuthError> { ) -> std::result::Result<(), AuthError> {
let challenge_payload = format_challenge(challenge.nonce, &challenge.pubkey); let challenge_payload = format_challenge(challenge.nonce, &challenge.pubkey);
let signature = key.sign(&challenge_payload).to_bytes().to_vec(); let signature = key.sign(&challenge_payload).to_bytes().to_vec();
@@ -104,11 +93,9 @@ async fn send_auth_challenge_solution(
transport transport
.send(ClientRequest { .send(ClientRequest {
request_id: next_request_id(), request_id: next_request_id(),
payload: Some(ClientRequestPayload::Auth(proto_auth::Request { payload: Some(ClientRequestPayload::AuthChallengeSolution(
payload: Some(AuthRequestPayload::ChallengeSolution( AuthChallengeSolution { signature },
AuthChallengeSolution { signature }, )),
)),
})),
}) })
.await .await
.map_err(|_| AuthError::UnexpectedAuthResponse) .map_err(|_| AuthError::UnexpectedAuthResponse)
@@ -122,19 +109,14 @@ async fn receive_auth_confirmation(
.await .await
.map_err(|_| AuthError::UnexpectedAuthResponse)?; .map_err(|_| AuthError::UnexpectedAuthResponse)?;
let payload = response let payload = response.payload.ok_or(AuthError::UnexpectedAuthResponse)?;
.payload
.ok_or(AuthError::UnexpectedAuthResponse)?;
match payload { match payload {
ClientResponsePayload::Auth(response) => match response.payload { ClientResponsePayload::AuthResult(result)
Some(AuthResponsePayload::Result(result)) if AuthResult::try_from(result).ok() == Some(AuthResult::Success) =>
if AuthResult::try_from(result).ok() == Some(AuthResult::Success) => {
{ Ok(())
Ok(()) }
} ClientResponsePayload::AuthResult(result) => Err(map_auth_result(result)),
Some(AuthResponsePayload::Result(result)) => Err(map_auth_result(result)),
_ => Err(AuthError::UnexpectedAuthResponse),
},
_ => Err(AuthError::UnexpectedAuthResponse), _ => Err(AuthError::UnexpectedAuthResponse),
} }
} }

View File

@@ -1,4 +1,3 @@
use std::io::{self, Write}; use std::io::{self, Write};
use arbiter_client::ArbiterClient; use arbiter_client::ArbiterClient;
@@ -22,8 +21,6 @@ async fn main() {
return; return;
} }
let url = match ArbiterUrl::try_from(input) { let url = match ArbiterUrl::try_from(input) {
Ok(url) => url, Ok(url) => url,
Err(err) => { Err(err) => {
@@ -32,7 +29,7 @@ async fn main() {
} }
}; };
println!("{:#?}", url); println!("{:#?}", url);
let metadata = ClientMetadata { let metadata = ClientMetadata {
name: "arbiter-client test_connect".to_string(), name: "arbiter-client test_connect".to_string(),

View File

@@ -1,11 +1,16 @@
use arbiter_proto::{ClientMetadata, proto::arbiter_service_client::ArbiterServiceClient, url::ArbiterUrl}; use arbiter_proto::{
ClientMetadata, proto::arbiter_service_client::ArbiterServiceClient, url::ArbiterUrl,
};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::{Mutex, mpsc}; use tokio::sync::{Mutex, mpsc};
use tokio_stream::wrappers::ReceiverStream; use tokio_stream::wrappers::ReceiverStream;
use tonic::transport::ClientTlsConfig; use tonic::transport::ClientTlsConfig;
use crate::{ use crate::{
StorageError, auth::{AuthError, authenticate}, storage::{FileSigningKeyStorage, SigningKeyStorage}, transport::{BUFFER_LENGTH, ClientTransport} StorageError,
auth::{AuthError, authenticate},
storage::{FileSigningKeyStorage, SigningKeyStorage},
transport::{BUFFER_LENGTH, ClientTransport},
}; };
#[cfg(feature = "evm")] #[cfg(feature = "evm")]
@@ -30,7 +35,6 @@ pub enum Error {
#[error("Storage error")] #[error("Storage error")]
Storage(#[from] StorageError), Storage(#[from] StorageError),
} }
pub struct ArbiterClient { pub struct ArbiterClient {
@@ -61,10 +65,11 @@ impl ArbiterClient {
let anchor = webpki::anchor_from_trusted_cert(&url.ca_cert)?.to_owned(); let anchor = webpki::anchor_from_trusted_cert(&url.ca_cert)?.to_owned();
let tls = ClientTlsConfig::new().trust_anchor(anchor); let tls = ClientTlsConfig::new().trust_anchor(anchor);
let channel = tonic::transport::Channel::from_shared(format!("https://{}:{}", url.host, url.port))? let channel =
.tls_config(tls)? tonic::transport::Channel::from_shared(format!("https://{}:{}", url.host, url.port))?
.connect() .tls_config(tls)?
.await?; .connect()
.await?;
let mut client = ArbiterServiceClient::new(channel); let mut client = ArbiterServiceClient::new(channel);
let (tx, rx) = mpsc::channel(BUFFER_LENGTH); let (tx, rx) = mpsc::channel(BUFFER_LENGTH);

View File

@@ -8,15 +8,7 @@ use async_trait::async_trait;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use arbiter_proto::proto::{ use crate::transport::ClientTransport;
client::{
ClientRequest, client_request::Payload as ClientRequestPayload,
client_response::Payload as ClientResponsePayload,
},
evm::evm_sign_transaction_response::Result as EvmSignTransactionResult,
};
use crate::transport::{ClientTransport, next_request_id};
pub struct ArbiterEvmWallet { pub struct ArbiterEvmWallet {
transport: Arc<Mutex<ClientTransport>>, transport: Arc<Mutex<ClientTransport>>,
@@ -87,61 +79,11 @@ impl TxSigner<Signature> for ArbiterEvmWallet {
&self, &self,
tx: &mut dyn SignableTransaction<Signature>, tx: &mut dyn SignableTransaction<Signature>,
) -> Result<Signature> { ) -> Result<Signature> {
let _transport = self.transport.lock().await;
self.validate_chain_id(tx)?; self.validate_chain_id(tx)?;
let mut transport = self.transport.lock().await; Err(Error::other(
let request_id = next_request_id(); "transaction signing is not supported by current arbiter.client protocol",
let rlp_transaction = tx.encoded_for_signing(); ))
transport
.send(ClientRequest {
request_id,
payload: Some(ClientRequestPayload::EvmSignTransaction(
arbiter_proto::proto::evm::EvmSignTransactionRequest {
wallet_address: self.address.to_vec(),
rlp_transaction,
},
)),
})
.await
.map_err(|_| Error::other("failed to send evm sign transaction request"))?;
let response = transport
.recv()
.await
.map_err(|_| Error::other("failed to receive evm sign transaction response"))?;
if response.request_id != Some(request_id) {
return Err(Error::other(
"received mismatched response id for evm sign transaction",
));
}
let payload = response
.payload
.ok_or_else(|| Error::other("missing evm sign transaction response payload"))?;
let ClientResponsePayload::EvmSignTransaction(response) = payload else {
return Err(Error::other(
"unexpected response payload for evm sign transaction request",
));
};
let result = response
.result
.ok_or_else(|| Error::other("missing evm sign transaction result"))?;
match result {
EvmSignTransactionResult::Signature(signature) => {
Signature::try_from(signature.as_slice())
.map_err(|_| Error::other("invalid signature returned by server"))
}
EvmSignTransactionResult::EvalError(eval_error) => Err(Error::other(format!(
"transaction rejected by policy: {eval_error:?}"
))),
EvmSignTransactionResult::Error(code) => Err(Error::other(format!(
"server failed to sign transaction with error code {code}"
))),
}
} }
} }

View File

@@ -6,56 +6,12 @@ use base64::{Engine, prelude::BASE64_STANDARD};
pub mod proto { pub mod proto {
tonic::include_proto!("arbiter"); tonic::include_proto!("arbiter");
pub mod shared {
tonic::include_proto!("arbiter.shared");
pub mod evm {
tonic::include_proto!("arbiter.shared.evm");
}
}
pub mod user_agent { pub mod user_agent {
tonic::include_proto!("arbiter.user_agent"); tonic::include_proto!("arbiter.user_agent");
pub mod auth {
tonic::include_proto!("arbiter.user_agent.auth");
}
pub mod evm {
tonic::include_proto!("arbiter.user_agent.evm");
}
pub mod sdk_client {
tonic::include_proto!("arbiter.user_agent.sdk_client");
}
pub mod vault {
tonic::include_proto!("arbiter.user_agent.vault");
pub mod bootstrap {
tonic::include_proto!("arbiter.user_agent.vault.bootstrap");
}
pub mod unseal {
tonic::include_proto!("arbiter.user_agent.vault.unseal");
}
}
} }
pub mod client { pub mod client {
tonic::include_proto!("arbiter.client"); tonic::include_proto!("arbiter.client");
pub mod auth {
tonic::include_proto!("arbiter.client.auth");
}
pub mod evm {
tonic::include_proto!("arbiter.client.evm");
}
pub mod vault {
tonic::include_proto!("arbiter.client.vault");
}
} }
pub mod evm { pub mod evm {

View File

@@ -7,7 +7,6 @@ const ARBITER_URL_SCHEME: &str = "arbiter";
const CERT_QUERY_KEY: &str = "cert"; const CERT_QUERY_KEY: &str = "cert";
const BOOTSTRAP_TOKEN_QUERY_KEY: &str = "bootstrap_token"; const BOOTSTRAP_TOKEN_QUERY_KEY: &str = "bootstrap_token";
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ArbiterUrl { pub struct ArbiterUrl {
pub host: String, pub host: String,

View File

@@ -49,6 +49,7 @@ pem = "3.0.6"
k256.workspace = true k256.workspace = true
rsa.workspace = true rsa.workspace = true
sha2.workspace = true sha2.workspace = true
hmac = "0.12"
spki.workspace = true spki.workspace = true
alloy.workspace = true alloy.workspace = true
prost-types.workspace = true prost-types.workspace = true

View File

@@ -47,6 +47,7 @@ create table if not exists useragent_client (
id integer not null primary key, id integer not null primary key,
nonce integer not null default(1), -- used for auth challenge nonce integer not null default(1), -- used for auth challenge
public_key blob not null, public_key blob not null,
pubkey_integrity_tag blob,
key_type integer not null default(1), -- 1=Ed25519, 2=ECDSA(secp256k1) key_type integer not null default(1), -- 1=Ed25519, 2=ECDSA(secp256k1)
created_at integer not null default(unixepoch ('now')), created_at integer not null default(unixepoch ('now')),
updated_at integer not null default(unixepoch ('now')) updated_at integer not null default(unixepoch ('now'))

View File

@@ -84,6 +84,7 @@ async fn get_client_and_nonce(
})?; })?;
conn.exclusive_transaction(|conn| { conn.exclusive_transaction(|conn| {
let pubkey_bytes = pubkey_bytes.clone();
Box::pin(async move { Box::pin(async move {
let Some((client_id, current_nonce)) = program_client::table let Some((client_id, current_nonce)) = program_client::table
.filter(program_client::public_key.eq(&pubkey_bytes)) .filter(program_client::public_key.eq(&pubkey_bytes))
@@ -290,7 +291,7 @@ where
pub async fn authenticate<T>( pub async fn authenticate<T>(
props: &mut ClientConnection, props: &mut ClientConnection,
transport: &mut T, transport: &mut T,
) -> Result<i32, Error> ) -> Result<VerifyingKey, Error>
where where
T: Bi<Inbound, Result<Outbound, Error>> + Send + ?Sized, T: Bi<Inbound, Result<Outbound, Error>> + Send + ?Sized,
{ {
@@ -318,6 +319,7 @@ where
}; };
sync_client_metadata(&props.db, info.id, &metadata).await?; sync_client_metadata(&props.db, info.id, &metadata).await?;
challenge_client(transport, pubkey, info.current_nonce).await?; challenge_client(transport, pubkey, info.current_nonce).await?;
transport transport
@@ -328,5 +330,5 @@ where
Error::Transport Error::Transport
})?; })?;
Ok(info.id) Ok(pubkey)
} }

View File

@@ -20,10 +20,7 @@ pub struct ClientConnection {
impl ClientConnection { impl ClientConnection {
pub fn new(db: db::DatabasePool, actors: GlobalActors) -> Self { pub fn new(db: db::DatabasePool, actors: GlobalActors) -> Self {
Self { Self { db, actors }
db,
actors,
}
} }
} }
@@ -35,8 +32,8 @@ where
T: Bi<auth::Inbound, Result<auth::Outbound, auth::Error>> + Send + ?Sized, T: Bi<auth::Inbound, Result<auth::Outbound, auth::Error>> + Send + ?Sized,
{ {
match auth::authenticate(&mut props, transport).await { match auth::authenticate(&mut props, transport).await {
Ok(client_id) => { Ok(_pubkey) => {
ClientSession::spawn(ClientSession::new(props, client_id)); ClientSession::spawn(ClientSession::new(props));
info!("Client authenticated, session started"); info!("Client authenticated, session started");
} }
Err(err) => { Err(err) => {

View File

@@ -1,29 +1,21 @@
use kameo::{Actor, messages}; use kameo::{Actor, messages};
use tracing::error; use tracing::error;
use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature};
use crate::{ use crate::{
actors::{ actors::{
GlobalActors, GlobalActors, client::ClientConnection, flow_coordinator::RegisterClient,
client::ClientConnection, flow_coordinator::RegisterClient,
evm::{ClientSignTransaction, SignTransactionError},
keyholder::KeyHolderState, keyholder::KeyHolderState,
}, },
db, db,
evm::VetError,
}; };
pub struct ClientSession { pub struct ClientSession {
props: ClientConnection, props: ClientConnection,
client_id: i32,
} }
impl ClientSession { impl ClientSession {
pub(crate) fn new(props: ClientConnection, client_id: i32) -> Self { pub(crate) fn new(props: ClientConnection) -> Self {
Self { props, client_id } Self { props }
} }
} }
@@ -43,34 +35,6 @@ impl ClientSession {
Ok(vault_state) Ok(vault_state)
} }
#[message]
pub(crate) async fn handle_sign_transaction(
&mut self,
wallet_address: Address,
transaction: TxEip1559,
) -> Result<Signature, SignTransactionRpcError> {
match self
.props
.actors
.evm
.ask(ClientSignTransaction {
client_id: self.client_id,
wallet_address,
transaction,
})
.await
{
Ok(signature) => Ok(signature),
Err(kameo::error::SendError::HandlerError(SignTransactionError::Vet(vet_error))) => {
Err(SignTransactionRpcError::Vet(vet_error))
}
Err(err) => {
error!(?err, "Failed to sign EVM transaction in client session");
Err(SignTransactionRpcError::Internal)
}
}
}
} }
impl Actor for ClientSession { impl Actor for ClientSession {
@@ -95,7 +59,7 @@ impl Actor for ClientSession {
impl ClientSession { impl ClientSession {
pub fn new_test(db: db::DatabasePool, actors: GlobalActors) -> Self { pub fn new_test(db: db::DatabasePool, actors: GlobalActors) -> Self {
let props = ClientConnection::new(db, actors); let props = ClientConnection::new(db, actors);
Self { props, client_id: 0 } Self { props }
} }
} }
@@ -106,12 +70,3 @@ pub enum Error {
#[error("Internal error")] #[error("Internal error")]
Internal, Internal,
} }
#[derive(Debug, thiserror::Error)]
pub enum SignTransactionRpcError {
#[error("Policy evaluation failed")]
Vet(#[from] VetError),
#[error("Internal error")]
Internal,
}

View File

@@ -15,7 +15,7 @@ use crate::actors::{
pub struct Args { pub struct Args {
pub client: ClientProfile, pub client: ClientProfile,
pub user_agents: Vec<ActorRef<UserAgentSession>>, pub user_agents: Vec<ActorRef<UserAgentSession>>,
pub reply: ReplySender<Result<bool, ApprovalError>> pub reply: ReplySender<Result<bool, ApprovalError>>,
} }
pub struct ClientApprovalController { pub struct ClientApprovalController {
@@ -39,7 +39,11 @@ impl Actor for ClientApprovalController {
type Error = (); type Error = ();
async fn on_start( async fn on_start(
Args { client, mut user_agents, reply }: Self::Args, Args {
client,
mut user_agents,
reply,
}: Self::Args,
actor_ref: ActorRef<Self>, actor_ref: ActorRef<Self>,
) -> Result<Self, Self::Error> { ) -> Result<Self, Self::Error> {
let this = Self { let this = Self {

View File

@@ -8,7 +8,14 @@ use kameo::{Actor, Reply, messages};
use strum::{EnumDiscriminants, IntoDiscriminant}; use strum::{EnumDiscriminants, IntoDiscriminant};
use tracing::{error, info}; use tracing::{error, info};
use crate::safe_cell::SafeCell; use crate::{
crypto::{
KeyCell, derive_key,
encryption::v1::{self, Nonce},
integrity::v1::compute_integrity_tag,
},
safe_cell::SafeCell,
};
use crate::{ use crate::{
db::{ db::{
self, self,
@@ -17,9 +24,6 @@ use crate::{
}, },
safe_cell::SafeCellHandle as _, safe_cell::SafeCellHandle as _,
}; };
use encryption::v1::{self, KeyCell, Nonce};
pub mod encryption;
#[derive(Default, EnumDiscriminants)] #[derive(Default, EnumDiscriminants)]
#[strum_discriminants(derive(Reply), vis(pub), name(KeyHolderState))] #[strum_discriminants(derive(Reply), vis(pub), name(KeyHolderState))]
@@ -114,14 +118,13 @@ impl KeyHolder {
.first(conn) .first(conn)
.await?; .await?;
let mut nonce = let mut nonce = Nonce::try_from(current_nonce.as_slice()).map_err(|_| {
v1::Nonce::try_from(current_nonce.as_slice()).map_err(|_| { error!(
error!( "Broken database: invalid nonce for root key history id={}",
"Broken database: invalid nonce for root key history id={}", root_key_id
root_key_id );
); Error::BrokenDatabase
Error::BrokenDatabase })?;
})?;
nonce.increment(); nonce.increment();
update(schema::root_key_history::table) update(schema::root_key_history::table)
@@ -144,12 +147,12 @@ impl KeyHolder {
return Err(Error::AlreadyBootstrapped); return Err(Error::AlreadyBootstrapped);
} }
let salt = v1::generate_salt(); let salt = v1::generate_salt();
let mut seal_key = v1::derive_seal_key(seal_key_raw, &salt); let mut seal_key = derive_key(seal_key_raw, &salt);
let mut root_key = KeyCell::new_secure_random(); let mut root_key = KeyCell::new_secure_random();
// Zero nonces are fine because they are one-time // Zero nonces are fine because they are one-time
let root_key_nonce = v1::Nonce::default(); let root_key_nonce = Nonce::default();
let data_encryption_nonce = v1::Nonce::default(); let data_encryption_nonce = Nonce::default();
let root_key_ciphertext: Vec<u8> = root_key.0.read_inline(|reader| { let root_key_ciphertext: Vec<u8> = root_key.0.read_inline(|reader| {
let root_key_reader = reader.as_slice(); let root_key_reader = reader.as_slice();
@@ -214,6 +217,7 @@ impl KeyHolder {
let mut conn = self.db.get().await?; let mut conn = self.db.get().await?;
schema::root_key_history::table schema::root_key_history::table
.filter(schema::root_key_history::id.eq(*root_key_history_id)) .filter(schema::root_key_history::id.eq(*root_key_history_id))
.select(schema::root_key_history::data_encryption_nonce)
.select(RootKeyHistory::as_select()) .select(RootKeyHistory::as_select())
.first(&mut conn) .first(&mut conn)
.await? .await?
@@ -224,7 +228,7 @@ impl KeyHolder {
error!("Broken database: invalid salt for root key"); error!("Broken database: invalid salt for root key");
Error::BrokenDatabase Error::BrokenDatabase
})?; })?;
let mut seal_key = v1::derive_seal_key(seal_key_raw, &salt); let mut seal_key = derive_key(seal_key_raw, &salt);
let mut root_key = SafeCell::new(current_key.ciphertext.clone()); let mut root_key = SafeCell::new(current_key.ciphertext.clone());
@@ -244,7 +248,7 @@ impl KeyHolder {
self.state = State::Unsealed { self.state = State::Unsealed {
root_key_history_id: current_key.id, root_key_history_id: current_key.id,
root_key: v1::KeyCell::try_from(root_key).map_err(|err| { root_key: KeyCell::try_from(root_key).map_err(|err| {
error!(?err, "Broken database: invalid encryption key size"); error!(?err, "Broken database: invalid encryption key size");
Error::BrokenDatabase Error::BrokenDatabase
})?, })?,
@@ -255,7 +259,22 @@ impl KeyHolder {
Ok(()) Ok(())
} }
// Decrypts the `aead_encrypted` entry with the given ID and returns the plaintext // Signs a generic integrity payload using the vault-derived integrity key
#[message]
pub fn sign_integrity_tag(
&mut self,
purpose_tag: Vec<u8>,
data_parts: Vec<Vec<u8>>,
) -> Result<Vec<u8>, Error> {
let State::Unsealed { root_key, .. } = &mut self.state else {
return Err(Error::NotBootstrapped);
};
let tag =
compute_integrity_tag(root_key, &purpose_tag, data_parts.iter().map(Vec::as_slice));
Ok(tag.to_vec())
}
#[message] #[message]
pub async fn decrypt(&mut self, aead_id: i32) -> Result<SafeCell<Vec<u8>>, Error> { pub async fn decrypt(&mut self, aead_id: i32) -> Result<SafeCell<Vec<u8>>, Error> {
let State::Unsealed { root_key, .. } = &mut self.state else { let State::Unsealed { root_key, .. } = &mut self.state else {
@@ -291,6 +310,7 @@ impl KeyHolder {
let State::Unsealed { let State::Unsealed {
root_key, root_key,
root_key_history_id, root_key_history_id,
..
} = &mut self.state } = &mut self.state
else { else {
return Err(Error::NotBootstrapped); return Err(Error::NotBootstrapped);

View File

@@ -1,17 +1,27 @@
use arbiter_proto::transport::Bi; use arbiter_proto::transport::Bi;
use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl, update}; use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl, update};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use kameo::error::SendError;
use tracing::error; use tracing::error;
use super::Error; use super::Error;
use crate::{ use crate::{
actors::{ actors::{
bootstrap::ConsumeToken, bootstrap::ConsumeToken,
keyholder::{self, SignIntegrityTag},
user_agent::{AuthPublicKey, UserAgentConnection, auth::Outbound}, user_agent::{AuthPublicKey, UserAgentConnection, auth::Outbound},
}, },
crypto::integrity::v1::USERAGENT_INTEGRITY_TAG,
db::schema, db::schema,
}; };
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AttestationStatus {
Attested,
NotAttested,
Unavailable,
}
pub struct ChallengeRequest { pub struct ChallengeRequest {
pub pubkey: AuthPublicKey, pub pubkey: AuthPublicKey,
} }
@@ -40,7 +50,11 @@ smlang::statemachine!(
} }
); );
async fn create_nonce(db: &crate::db::DatabasePool, pubkey_bytes: &[u8]) -> Result<i32, Error> { async fn create_nonce(
db: &crate::db::DatabasePool,
pubkey_bytes: &[u8],
key_type: crate::db::models::KeyType,
) -> Result<i32, Error> {
let mut db_conn = db.get().await.map_err(|e| { let mut db_conn = db.get().await.map_err(|e| {
error!(error = ?e, "Database pool error"); error!(error = ?e, "Database pool error");
Error::internal("Database unavailable") Error::internal("Database unavailable")
@@ -50,12 +64,14 @@ async fn create_nonce(db: &crate::db::DatabasePool, pubkey_bytes: &[u8]) -> Resu
Box::pin(async move { Box::pin(async move {
let current_nonce = schema::useragent_client::table let current_nonce = schema::useragent_client::table
.filter(schema::useragent_client::public_key.eq(pubkey_bytes.to_vec())) .filter(schema::useragent_client::public_key.eq(pubkey_bytes.to_vec()))
.filter(schema::useragent_client::key_type.eq(key_type))
.select(schema::useragent_client::nonce) .select(schema::useragent_client::nonce)
.first::<i32>(conn) .first::<i32>(conn)
.await?; .await?;
update(schema::useragent_client::table) update(schema::useragent_client::table)
.filter(schema::useragent_client::public_key.eq(pubkey_bytes.to_vec())) .filter(schema::useragent_client::public_key.eq(pubkey_bytes.to_vec()))
.filter(schema::useragent_client::key_type.eq(key_type))
.set(schema::useragent_client::nonce.eq(current_nonce + 1)) .set(schema::useragent_client::nonce.eq(current_nonce + 1))
.execute(conn) .execute(conn)
.await?; .await?;
@@ -75,7 +91,11 @@ async fn create_nonce(db: &crate::db::DatabasePool, pubkey_bytes: &[u8]) -> Resu
}) })
} }
async fn register_key(db: &crate::db::DatabasePool, pubkey: &AuthPublicKey) -> Result<(), Error> { async fn register_key(
db: &crate::db::DatabasePool,
pubkey: &AuthPublicKey,
integrity_tag: Option<Vec<u8>>,
) -> Result<(), Error> {
let pubkey_bytes = pubkey.to_stored_bytes(); let pubkey_bytes = pubkey.to_stored_bytes();
let key_type = pubkey.key_type(); let key_type = pubkey.key_type();
let mut conn = db.get().await.map_err(|e| { let mut conn = db.get().await.map_err(|e| {
@@ -88,6 +108,7 @@ async fn register_key(db: &crate::db::DatabasePool, pubkey: &AuthPublicKey) -> R
schema::useragent_client::public_key.eq(pubkey_bytes), schema::useragent_client::public_key.eq(pubkey_bytes),
schema::useragent_client::nonce.eq(1), schema::useragent_client::nonce.eq(1),
schema::useragent_client::key_type.eq(key_type), schema::useragent_client::key_type.eq(key_type),
schema::useragent_client::pubkey_integrity_tag.eq(integrity_tag),
)) ))
.execute(&mut conn) .execute(&mut conn)
.await .await
@@ -120,8 +141,15 @@ where
&mut self, &mut self,
ChallengeRequest { pubkey }: ChallengeRequest, ChallengeRequest { pubkey }: ChallengeRequest,
) -> Result<ChallengeContext, Self::Error> { ) -> Result<ChallengeContext, Self::Error> {
match self.verify_pubkey_attestation_status(&pubkey).await? {
AttestationStatus::Attested | AttestationStatus::Unavailable => {}
AttestationStatus::NotAttested => {
return Err(Error::InvalidChallengeSolution);
}
}
let stored_bytes = pubkey.to_stored_bytes(); let stored_bytes = pubkey.to_stored_bytes();
let nonce = create_nonce(&self.conn.db, &stored_bytes).await?; let nonce = create_nonce(&self.conn.db, &stored_bytes, pubkey.key_type()).await?;
self.transport self.transport
.send(Ok(Outbound::AuthChallenge { nonce })) .send(Ok(Outbound::AuthChallenge { nonce }))
@@ -161,7 +189,15 @@ where
return Err(Error::InvalidBootstrapToken); return Err(Error::InvalidBootstrapToken);
} }
register_key(&self.conn.db, &pubkey).await?; let integrity_tag = self
.try_sign_pubkey_integrity_tag(&pubkey)
.await
.map_err(|err| {
error!(?err, "Failed to sign user-agent pubkey integrity tag");
Error::internal("Failed to sign user-agent pubkey integrity tag")
})?;
register_key(&self.conn.db, &pubkey, integrity_tag).await?;
self.transport self.transport
.send(Ok(Outbound::AuthSuccess)) .send(Ok(Outbound::AuthSuccess))
@@ -210,16 +246,112 @@ where
} }
}; };
if !valid { match valid {
error!("Invalid challenge solution signature"); true => {
return Err(Error::InvalidChallengeSolution); self.transport
.send(Ok(Outbound::AuthSuccess))
.await
.map_err(|_| Error::Transport)?;
Ok(key.clone())
}
false => {
self.transport
.send(Err(Error::InvalidChallengeSolution))
.await
.map_err(|_| Error::Transport)?;
Err(Error::InvalidChallengeSolution)
}
}
}
}
impl<T> AuthContext<'_, T>
where
T: Bi<super::Inbound, Result<super::Outbound, Error>> + Send,
{
async fn try_sign_pubkey_integrity_tag(
&self,
pubkey: &AuthPublicKey,
) -> Result<Option<Vec<u8>>, Error> {
let signed = self
.conn
.actors
.key_holder
.ask(SignIntegrityTag {
purpose_tag: USERAGENT_INTEGRITY_TAG.to_vec(),
data_parts: vec![
(pubkey.key_type() as i32).to_be_bytes().to_vec(),
pubkey.to_stored_bytes(),
],
})
.await;
match signed {
Ok(tag) => Ok(Some(tag)),
Err(SendError::HandlerError(keyholder::Error::NotBootstrapped)) => Ok(None),
Err(SendError::HandlerError(err)) => {
error!(
?err,
"Keyholder failed to sign user-agent pubkey integrity tag"
);
Err(Error::internal(
"Keyholder failed to sign user-agent pubkey integrity tag",
))
}
Err(err) => {
error!(
?err,
"Failed to contact keyholder for user-agent pubkey integrity tag"
);
Err(Error::internal(
"Failed to contact keyholder for user-agent pubkey integrity tag",
))
}
}
}
async fn verify_pubkey_attestation_status(
&self,
pubkey: &AuthPublicKey,
) -> Result<AttestationStatus, Error> {
let stored_tag: Option<Option<Vec<u8>>> = {
let mut conn = self.conn.db.get().await.map_err(|e| {
error!(error = ?e, "Database pool error");
Error::internal("Database unavailable")
})?;
schema::useragent_client::table
.filter(schema::useragent_client::public_key.eq(pubkey.to_stored_bytes()))
.filter(schema::useragent_client::key_type.eq(pubkey.key_type()))
.select(schema::useragent_client::pubkey_integrity_tag)
.first::<Option<Vec<u8>>>(&mut conn)
.await
.optional()
.map_err(|e| {
error!(error = ?e, "Database error");
Error::internal("Database operation failed")
})?
};
let Some(stored_tag) = stored_tag else {
return Err(Error::UnregisteredPublicKey);
};
let Some(expected_tag) = self.try_sign_pubkey_integrity_tag(pubkey).await? else {
// Vault sealed/unbootstrapped: cannot verify integrity yet.
return Ok(AttestationStatus::Unavailable);
};
match stored_tag {
Some(stored_tag) if stored_tag == expected_tag => Ok(AttestationStatus::Attested),
Some(_) => {
error!("User-agent pubkey integrity tag mismatch");
Ok(AttestationStatus::NotAttested)
}
None => {
error!("Missing pubkey integrity tag for registered key while vault is unsealed");
Ok(AttestationStatus::NotAttested)
}
} }
self.transport
.send(Ok(Outbound::AuthSuccess))
.await
.map_err(|_| Error::Transport)?;
Ok(key.clone())
} }
} }

View File

@@ -1,12 +1,12 @@
use std::sync::Mutex; use std::sync::Mutex;
use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature}; use alloy::primitives::Address;
use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit}; use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit};
use diesel::{ExpressionMethods as _, QueryDsl as _, SelectableHelper}; use diesel::{ExpressionMethods as _, QueryDsl as _, SelectableHelper};
use diesel_async::{AsyncConnection, RunQueryDsl}; use diesel_async::{AsyncConnection, RunQueryDsl};
use kameo::error::SendError; use kameo::error::SendError;
use kameo::prelude::Context;
use kameo::messages; use kameo::messages;
use kameo::prelude::Context;
use tracing::{error, info}; use tracing::{error, info};
use x25519_dalek::{EphemeralSecret, PublicKey}; use x25519_dalek::{EphemeralSecret, PublicKey};
@@ -21,8 +21,7 @@ use crate::safe_cell::SafeCell;
use crate::{ use crate::{
actors::{ actors::{
evm::{ evm::{
ClientSignTransaction, Generate, ListWallets, SignTransactionError as EvmSignError, Generate, ListWallets, UseragentCreateGrant, UseragentDeleteGrant, UseragentListGrants,
UseragentCreateGrant, UseragentDeleteGrant, UseragentListGrants,
}, },
keyholder::{self, Bootstrap, TryUnseal}, keyholder::{self, Bootstrap, TryUnseal},
user_agent::session::{ user_agent::session::{
@@ -111,15 +110,6 @@ pub enum BootstrapError {
General(#[from] super::Error), General(#[from] super::Error),
} }
#[derive(Debug, Error)]
pub enum SignTransactionError {
#[error("Policy evaluation failed")]
Vet(#[from] crate::evm::VetError),
#[error("Internal signing error")]
Internal,
}
#[messages] #[messages]
impl UserAgentSession { impl UserAgentSession {
#[message] #[message]
@@ -364,35 +354,6 @@ impl UserAgentSession {
} }
} }
#[message]
pub(crate) async fn handle_sign_transaction(
&mut self,
client_id: i32,
wallet_address: Address,
transaction: TxEip1559,
) -> Result<Signature, SignTransactionError> {
match self
.props
.actors
.evm
.ask(ClientSignTransaction {
client_id,
wallet_address,
transaction,
})
.await
{
Ok(signature) => Ok(signature),
Err(SendError::HandlerError(EvmSignError::Vet(vet_error))) => {
Err(SignTransactionError::Vet(vet_error))
}
Err(err) => {
error!(?err, "EVM sign transaction failed in user-agent session");
Err(SignTransactionError::Internal)
}
}
}
#[message] #[message]
pub(crate) async fn handle_grant_evm_wallet_access( pub(crate) async fn handle_grant_evm_wallet_access(
&mut self, &mut self,

View File

@@ -116,9 +116,7 @@ impl TlsCa {
]; ];
params params
.subject_alt_names .subject_alt_names
.push(SanType::IpAddress(IpAddr::from([ .push(SanType::IpAddress(IpAddr::from([127, 0, 0, 1])));
127, 0, 0, 1,
])));
let mut dn = DistinguishedName::new(); let mut dn = DistinguishedName::new();
dn.push(DnType::CommonName, "Arbiter Instance Leaf"); dn.push(DnType::CommonName, "Arbiter Instance Leaf");

View File

@@ -0,0 +1,109 @@
use argon2::password_hash::Salt as ArgonSalt;
use rand::{
Rng as _, SeedableRng,
rngs::{StdRng, SysRng},
};
pub const ROOT_KEY_TAG: &[u8] = "arbiter/seal/v1".as_bytes();
pub const TAG: &[u8] = "arbiter/private-key/v1".as_bytes();
pub const NONCE_LENGTH: usize = 24;
#[derive(Default)]
pub struct Nonce(pub [u8; NONCE_LENGTH]);
impl Nonce {
pub fn increment(&mut self) {
for i in (0..self.0.len()).rev() {
if self.0[i] == 0xFF {
self.0[i] = 0;
} else {
self.0[i] += 1;
break;
}
}
}
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
}
impl<'a> TryFrom<&'a [u8]> for Nonce {
type Error = ();
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
if value.len() != NONCE_LENGTH {
return Err(());
}
let mut nonce = [0u8; NONCE_LENGTH];
nonce.copy_from_slice(value);
Ok(Self(nonce))
}
}
pub type Salt = [u8; ArgonSalt::RECOMMENDED_LENGTH];
pub fn generate_salt() -> Salt {
let mut salt = Salt::default();
#[allow(
clippy::unwrap_used,
reason = "Rng failure is unrecoverable and should panic"
)]
let mut rng = StdRng::try_from_rng(&mut SysRng).unwrap();
rng.fill_bytes(&mut salt);
salt
}
#[cfg(test)]
mod tests {
use std::ops::Deref as _;
use super::*;
use crate::{
crypto::derive_key,
safe_cell::{SafeCell, SafeCellHandle as _},
};
#[test]
pub fn derive_seal_key_deterministic() {
static PASSWORD: &[u8] = b"password";
let password = SafeCell::new(PASSWORD.to_vec());
let password2 = SafeCell::new(PASSWORD.to_vec());
let salt = generate_salt();
let mut key1 = derive_key(password, &salt);
let mut key2 = derive_key(password2, &salt);
let key1_reader = key1.0.read();
let key2_reader = key2.0.read();
assert_eq!(key1_reader.deref(), key2_reader.deref());
}
#[test]
pub fn successful_derive() {
static PASSWORD: &[u8] = b"password";
let password = SafeCell::new(PASSWORD.to_vec());
let salt = generate_salt();
let mut key = derive_key(password, &salt);
let key_reader = key.0.read();
let key_ref = key_reader.deref();
assert_ne!(key_ref.as_slice(), &[0u8; 32][..]);
}
#[test]
// We should fuzz this
pub fn test_nonce_increment() {
let mut nonce = Nonce([0u8; NONCE_LENGTH]);
nonce.increment();
assert_eq!(
nonce.0,
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
]
);
}
}

View File

@@ -0,0 +1 @@
pub mod v1;

View File

@@ -0,0 +1,78 @@
use crate::{crypto::KeyCell, safe_cell::SafeCellHandle as _};
use chacha20poly1305::Key;
use hmac::Mac as _;
pub const USERAGENT_INTEGRITY_DERIVE_TAG: &[u8] = "arbiter/useragent/integrity-key/v1".as_bytes();
pub const USERAGENT_INTEGRITY_TAG: &[u8] = "arbiter/useragent/pubkey-entry/v1".as_bytes();
/// Computes an integrity tag for a specific domain and payload shape.
pub fn compute_integrity_tag<'a, I>(
integrity_key: &mut KeyCell,
purpose_tag: &[u8],
data_parts: I,
) -> [u8; 32]
where
I: IntoIterator<Item = &'a [u8]>,
{
type HmacSha256 = hmac::Hmac<sha2::Sha256>;
let mut output_tag = [0u8; 32];
integrity_key.0.read_inline(|integrity_key_bytes: &Key| {
let mut mac = <HmacSha256 as hmac::Mac>::new_from_slice(integrity_key_bytes.as_ref())
.expect("HMAC key initialization must not fail for 32-byte key");
mac.update(purpose_tag);
for data_part in data_parts {
mac.update(data_part);
}
output_tag.copy_from_slice(&mac.finalize().into_bytes());
});
output_tag
}
#[cfg(test)]
mod tests {
use crate::{
crypto::{derive_key, encryption::v1::generate_salt},
safe_cell::{SafeCell, SafeCellHandle as _},
};
use super::{USERAGENT_INTEGRITY_TAG, compute_integrity_tag};
#[test]
pub fn integrity_tag_deterministic() {
let salt = generate_salt();
let mut integrity_key = derive_key(SafeCell::new(b"password".to_vec()), &salt);
let key_type = 1i32.to_be_bytes();
let t1 = compute_integrity_tag(
&mut integrity_key,
USERAGENT_INTEGRITY_TAG,
[key_type.as_slice(), b"pubkey".as_ref()],
);
let t2 = compute_integrity_tag(
&mut integrity_key,
USERAGENT_INTEGRITY_TAG,
[key_type.as_slice(), b"pubkey".as_ref()],
);
assert_eq!(t1, t2);
}
#[test]
pub fn integrity_tag_changes_with_payload() {
let salt = generate_salt();
let mut integrity_key = derive_key(SafeCell::new(b"password".to_vec()), &salt);
let key_type_1 = 1i32.to_be_bytes();
let key_type_2 = 2i32.to_be_bytes();
let t1 = compute_integrity_tag(
&mut integrity_key,
USERAGENT_INTEGRITY_TAG,
[key_type_1.as_slice(), b"pubkey".as_ref()],
);
let t2 = compute_integrity_tag(
&mut integrity_key,
USERAGENT_INTEGRITY_TAG,
[key_type_2.as_slice(), b"pubkey".as_ref()],
);
assert_ne!(t1, t2);
}
}

View File

@@ -1,52 +1,21 @@
use std::ops::Deref as _; use std::ops::Deref as _;
use argon2::{Algorithm, Argon2, password_hash::Salt as ArgonSalt}; use argon2::{Algorithm, Argon2};
use chacha20poly1305::{ use chacha20poly1305::{
AeadInPlace, Key, KeyInit as _, XChaCha20Poly1305, XNonce, AeadInPlace, Key, KeyInit as _, XChaCha20Poly1305, XNonce,
aead::{AeadMut, Error, Payload}, aead::{AeadMut, Error, Payload},
}; };
use rand::{ use rand::{
Rng as _, SeedableRng, Rng as _, SeedableRng as _,
rngs::{StdRng, SysRng}, rngs::{StdRng, SysRng},
}; };
use crate::safe_cell::{SafeCell, SafeCellHandle as _}; use crate::safe_cell::{SafeCell, SafeCellHandle as _};
pub const ROOT_KEY_TAG: &[u8] = "arbiter/seal/v1".as_bytes(); pub mod encryption;
pub const TAG: &[u8] = "arbiter/private-key/v1".as_bytes(); pub mod integrity;
pub const NONCE_LENGTH: usize = 24; use encryption::v1::{Nonce, Salt};
#[derive(Default)]
pub struct Nonce([u8; NONCE_LENGTH]);
impl Nonce {
pub fn increment(&mut self) {
for i in (0..self.0.len()).rev() {
if self.0[i] == 0xFF {
self.0[i] = 0;
} else {
self.0[i] += 1;
break;
}
}
}
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
}
impl<'a> TryFrom<&'a [u8]> for Nonce {
type Error = ();
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
if value.len() != NONCE_LENGTH {
return Err(());
}
let mut nonce = [0u8; NONCE_LENGTH];
nonce.copy_from_slice(value);
Ok(Self(nonce))
}
}
pub struct KeyCell(pub SafeCell<Key>); pub struct KeyCell(pub SafeCell<Key>);
impl From<SafeCell<Key>> for KeyCell { impl From<SafeCell<Key>> for KeyCell {
@@ -133,22 +102,9 @@ impl KeyCell {
} }
} }
pub type Salt = [u8; ArgonSalt::RECOMMENDED_LENGTH];
pub fn generate_salt() -> Salt {
let mut salt = Salt::default();
#[allow(
clippy::unwrap_used,
reason = "Rng failure is unrecoverable and should panic"
)]
let mut rng = StdRng::try_from_rng(&mut SysRng).unwrap();
rng.fill_bytes(&mut salt);
salt
}
/// User password might be of different length, have not enough entropy, etc... /// User password might be of different length, have not enough entropy, etc...
/// Derive a fixed-length key from the password using Argon2id, which is designed for password hashing and key derivation. /// Derive a fixed-length key from the password using Argon2id, which is designed for password hashing and key derivation.
pub fn derive_seal_key(mut password: SafeCell<Vec<u8>>, salt: &Salt) -> KeyCell { pub fn derive_key(mut password: SafeCell<Vec<u8>>, salt: &Salt) -> KeyCell {
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let params = argon2::Params::new(262_144, 3, 4, None).unwrap(); let params = argon2::Params::new(262_144, 3, 4, None).unwrap();
let hasher = Argon2::new(Algorithm::Argon2id, argon2::Version::V0x13, params); let hasher = Argon2::new(Algorithm::Argon2id, argon2::Version::V0x13, params);
@@ -171,37 +127,11 @@ pub fn derive_seal_key(mut password: SafeCell<Vec<u8>>, salt: &Salt) -> KeyCell
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::{
use crate::safe_cell::SafeCell; derive_key,
encryption::v1::{Nonce, generate_salt},
#[test] };
pub fn derive_seal_key_deterministic() { use crate::safe_cell::{SafeCell, SafeCellHandle as _};
static PASSWORD: &[u8] = b"password";
let password = SafeCell::new(PASSWORD.to_vec());
let password2 = SafeCell::new(PASSWORD.to_vec());
let salt = generate_salt();
let mut key1 = derive_seal_key(password, &salt);
let mut key2 = derive_seal_key(password2, &salt);
let key1_reader = key1.0.read();
let key2_reader = key2.0.read();
assert_eq!(key1_reader.deref(), key2_reader.deref());
}
#[test]
pub fn successful_derive() {
static PASSWORD: &[u8] = b"password";
let password = SafeCell::new(PASSWORD.to_vec());
let salt = generate_salt();
let mut key = derive_seal_key(password, &salt);
let key_reader = key.0.read();
let key_ref = key_reader.deref();
assert_ne!(key_ref.as_slice(), &[0u8; 32][..]);
}
#[test] #[test]
pub fn encrypt_decrypt() { pub fn encrypt_decrypt() {
@@ -209,7 +139,7 @@ mod tests {
let password = SafeCell::new(PASSWORD.to_vec()); let password = SafeCell::new(PASSWORD.to_vec());
let salt = generate_salt(); let salt = generate_salt();
let mut key = derive_seal_key(password, &salt); let mut key = derive_key(password, &salt);
let nonce = Nonce(*b"unique nonce 123 1231233"); // 24 bytes for XChaCha20Poly1305 let nonce = Nonce(*b"unique nonce 123 1231233"); // 24 bytes for XChaCha20Poly1305
let associated_data = b"associated data"; let associated_data = b"associated data";
let mut buffer = b"secret data".to_vec(); let mut buffer = b"secret data".to_vec();
@@ -226,18 +156,4 @@ mod tests {
let buffer = buffer.read(); let buffer = buffer.read();
assert_eq!(*buffer, b"secret data"); assert_eq!(*buffer, b"secret data");
} }
#[test]
// We should fuzz this
pub fn test_nonce_increment() {
let mut nonce = Nonce([0u8; NONCE_LENGTH]);
nonce.increment();
assert_eq!(
nonce.0,
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
]
);
}
} }

View File

@@ -242,6 +242,7 @@ pub struct UseragentClient {
pub id: i32, pub id: i32,
pub nonce: i32, pub nonce: i32,
pub public_key: Vec<u8>, pub public_key: Vec<u8>,
pub pubkey_integrity_tag: Option<Vec<u8>>,
pub created_at: SqliteTimestamp, pub created_at: SqliteTimestamp,
pub updated_at: SqliteTimestamp, pub updated_at: SqliteTimestamp,
pub key_type: KeyType, pub key_type: KeyType,

View File

@@ -178,6 +178,7 @@ diesel::table! {
id -> Integer, id -> Integer,
nonce -> Integer, nonce -> Integer,
public_key -> Binary, public_key -> Binary,
pubkey_integrity_tag -> Nullable<Binary>,
key_type -> Integer, key_type -> Integer,
created_at -> Integer, created_at -> Integer,
updated_at -> Integer, updated_at -> Integer,

View File

@@ -31,7 +31,7 @@ mod utils;
#[derive(Debug, thiserror::Error, miette::Diagnostic)] #[derive(Debug, thiserror::Error, miette::Diagnostic)]
pub enum PolicyError { pub enum PolicyError {
#[error("Database error")] #[error("Database error")]
Database(#[from] crate::db::DatabaseError), Error(#[from] crate::db::DatabaseError),
#[error("Transaction violates policy: {0:?}")] #[error("Transaction violates policy: {0:?}")]
#[diagnostic(code(arbiter_server::evm::policy_error::violation))] #[diagnostic(code(arbiter_server::evm::policy_error::violation))]
Violations(Vec<EvalViolation>), Violations(Vec<EvalViolation>),

View File

@@ -36,8 +36,8 @@ use super::{DatabaseID, EvalContext, EvalViolation};
// Plain ether transfer // Plain ether transfer
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Meaning { pub struct Meaning {
pub(crate) to: Address, to: Address,
pub(crate) value: U256, value: U256,
} }
impl Display for Meaning { impl Display for Meaning {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -91,7 +91,6 @@ async fn query_relevant_past_transaction(
async fn check_rate_limits( async fn check_rate_limits(
grant: &Grant<Settings>, grant: &Grant<Settings>,
current_transfer_value: U256,
db: &mut impl AsyncConnection<Backend = Sqlite>, db: &mut impl AsyncConnection<Backend = Sqlite>,
) -> QueryResult<Vec<EvalViolation>> { ) -> QueryResult<Vec<EvalViolation>> {
let mut violations = Vec::new(); let mut violations = Vec::new();
@@ -100,12 +99,12 @@ async fn check_rate_limits(
let past_transaction = query_relevant_past_transaction(grant.id, window, db).await?; let past_transaction = query_relevant_past_transaction(grant.id, window, db).await?;
let window_start = chrono::Utc::now() - grant.settings.limit.window; let window_start = chrono::Utc::now() - grant.settings.limit.window;
let prospective_cumulative_volume: U256 = past_transaction let cumulative_volume: U256 = past_transaction
.iter() .iter()
.filter(|(_, timestamp)| timestamp >= &window_start) .filter(|(_, timestamp)| timestamp >= &window_start)
.fold(current_transfer_value, |acc, (value, _)| acc + *value); .fold(U256::default(), |acc, (value, _)| acc + *value);
if prospective_cumulative_volume > grant.settings.limit.max_volume { if cumulative_volume > grant.settings.limit.max_volume {
violations.push(EvalViolation::VolumetricLimitExceeded); violations.push(EvalViolation::VolumetricLimitExceeded);
} }
@@ -142,7 +141,7 @@ impl Policy for EtherTransfer {
violations.push(EvalViolation::InvalidTarget { target: meaning.to }); violations.push(EvalViolation::InvalidTarget { target: meaning.to });
} }
let rate_violations = check_rate_limits(grant, meaning.value, db).await?; let rate_violations = check_rate_limits(grant, db).await?;
violations.extend(rate_violations); violations.extend(rate_violations);
Ok(violations) Ok(violations)

View File

@@ -198,7 +198,7 @@ async fn evaluate_rejects_volume_over_limit() {
grant_id, grant_id,
wallet_access_id: WALLET_ACCESS_ID, wallet_access_id: WALLET_ACCESS_ID,
chain_id: CHAIN_ID as i32, chain_id: CHAIN_ID as i32,
eth_value: utils::u256_to_bytes(U256::from(1_000u64)).to_vec(), eth_value: utils::u256_to_bytes(U256::from(1_001u64)).to_vec(),
signed_at: SqliteTimestamp(Utc::now()), signed_at: SqliteTimestamp(Utc::now()),
}) })
.execute(&mut *conn) .execute(&mut *conn)
@@ -211,7 +211,7 @@ async fn evaluate_rejects_volume_over_limit() {
shared: shared(), shared: shared(),
settings, settings,
}; };
let context = ctx(ALLOWED, U256::from(1u64)); let context = ctx(ALLOWED, U256::from(100u64));
let m = EtherTransfer::analyze(&context).unwrap(); let m = EtherTransfer::analyze(&context).unwrap();
let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn)
.await .await
@@ -233,13 +233,13 @@ async fn evaluate_passes_at_exactly_volume_limit() {
.await .await
.unwrap(); .unwrap();
// Exactly at the limit including current transfer — check is `>`, so this should not violate // Exactly at the limit — the check is `>`, so this should not violate
insert_into(evm_transaction_log::table) insert_into(evm_transaction_log::table)
.values(NewEvmTransactionLog { .values(NewEvmTransactionLog {
grant_id, grant_id,
wallet_access_id: WALLET_ACCESS_ID, wallet_access_id: WALLET_ACCESS_ID,
chain_id: CHAIN_ID as i32, chain_id: CHAIN_ID as i32,
eth_value: utils::u256_to_bytes(U256::from(900u64)).to_vec(), eth_value: utils::u256_to_bytes(U256::from(1_000u64)).to_vec(),
signed_at: SqliteTimestamp(Utc::now()), signed_at: SqliteTimestamp(Utc::now()),
}) })
.execute(&mut *conn) .execute(&mut *conn)

View File

@@ -38,9 +38,9 @@ fn grant_join() -> _ {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Meaning { pub struct Meaning {
pub(crate) token: &'static TokenInfo, token: &'static TokenInfo,
pub(crate) to: Address, to: Address,
pub(crate) value: U256, value: U256,
} }
impl std::fmt::Display for Meaning { impl std::fmt::Display for Meaning {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -101,7 +101,6 @@ async fn query_relevant_past_transfers(
async fn check_volume_rate_limits( async fn check_volume_rate_limits(
grant: &Grant<Settings>, grant: &Grant<Settings>,
current_transfer_value: U256,
db: &mut impl AsyncConnection<Backend = Sqlite>, db: &mut impl AsyncConnection<Backend = Sqlite>,
) -> QueryResult<Vec<EvalViolation>> { ) -> QueryResult<Vec<EvalViolation>> {
let mut violations = Vec::new(); let mut violations = Vec::new();
@@ -114,12 +113,12 @@ async fn check_volume_rate_limits(
for limit in &grant.settings.volume_limits { for limit in &grant.settings.volume_limits {
let window_start = chrono::Utc::now() - limit.window; let window_start = chrono::Utc::now() - limit.window;
let prospective_cumulative_volume: U256 = past_transfers let cumulative_volume: U256 = past_transfers
.iter() .iter()
.filter(|(_, timestamp)| timestamp >= &window_start) .filter(|(_, timestamp)| timestamp >= &window_start)
.fold(current_transfer_value, |acc, (value, _)| acc + *value); .fold(U256::default(), |acc, (value, _)| acc + *value);
if prospective_cumulative_volume > limit.max_volume { if cumulative_volume > limit.max_volume {
violations.push(EvalViolation::VolumetricLimitExceeded); violations.push(EvalViolation::VolumetricLimitExceeded);
break; break;
} }
@@ -164,7 +163,7 @@ impl Policy for TokenTransfer {
violations.push(EvalViolation::InvalidTarget { target: meaning.to }); violations.push(EvalViolation::InvalidTarget { target: meaning.to });
} }
let rate_violations = check_volume_rate_limits(grant, meaning.value, db).await?; let rate_violations = check_volume_rate_limits(grant, db).await?;
violations.extend(rate_violations); violations.extend(rate_violations);
Ok(violations) Ok(violations)

View File

@@ -220,7 +220,7 @@ async fn evaluate_rejects_wrong_restricted_recipient() {
} }
#[tokio::test] #[tokio::test]
async fn evaluate_passes_volume_at_exact_limit() { async fn evaluate_passes_volume_within_limit() {
let db = db::create_test_pool().await; let db = db::create_test_pool().await;
let mut conn = db.get().await.unwrap(); let mut conn = db.get().await.unwrap();
@@ -230,7 +230,7 @@ async fn evaluate_passes_volume_at_exact_limit() {
.await .await
.unwrap(); .unwrap();
// Record a past transfer of 900, with current transfer 100 => exactly 1000 limit // Record a past transfer of 500 (within 1000 limit)
use crate::db::{models::NewEvmTokenTransferLog, schema::evm_token_transfer_log}; use crate::db::{models::NewEvmTokenTransferLog, schema::evm_token_transfer_log};
insert_into(evm_token_transfer_log::table) insert_into(evm_token_transfer_log::table)
.values(NewEvmTokenTransferLog { .values(NewEvmTokenTransferLog {
@@ -239,7 +239,7 @@ async fn evaluate_passes_volume_at_exact_limit() {
chain_id: CHAIN_ID as i32, chain_id: CHAIN_ID as i32,
token_contract: DAI.to_vec(), token_contract: DAI.to_vec(),
recipient_address: RECIPIENT.to_vec(), recipient_address: RECIPIENT.to_vec(),
value: utils::u256_to_bytes(U256::from(900u64)).to_vec(), value: utils::u256_to_bytes(U256::from(500u64)).to_vec(),
}) })
.execute(&mut *conn) .execute(&mut *conn)
.await .await
@@ -282,7 +282,7 @@ async fn evaluate_rejects_volume_over_limit() {
chain_id: CHAIN_ID as i32, chain_id: CHAIN_ID as i32,
token_contract: DAI.to_vec(), token_contract: DAI.to_vec(),
recipient_address: RECIPIENT.to_vec(), recipient_address: RECIPIENT.to_vec(),
value: utils::u256_to_bytes(U256::from(1_000u64)).to_vec(), value: utils::u256_to_bytes(U256::from(1_001u64)).to_vec(),
}) })
.execute(&mut *conn) .execute(&mut *conn)
.await .await
@@ -294,7 +294,7 @@ async fn evaluate_rejects_volume_over_limit() {
shared: shared(), shared: shared(),
settings, settings,
}; };
let calldata = transfer_calldata(RECIPIENT, U256::from(1u64)); let calldata = transfer_calldata(RECIPIENT, U256::from(100u64));
let context = ctx(DAI, calldata); let context = ctx(DAI, calldata);
let m = TokenTransfer::analyze(&context).unwrap(); let m = TokenTransfer::analyze(&context).unwrap();
let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn)

View File

@@ -1,24 +1,32 @@
use arbiter_proto::{ use arbiter_proto::{
proto::client::{ proto::client::{
ClientRequest, ClientResponse, client_request::Payload as ClientRequestPayload, ClientRequest, ClientResponse, VaultState as ProtoVaultState,
client_request::Payload as ClientRequestPayload,
client_response::Payload as ClientResponsePayload, client_response::Payload as ClientResponsePayload,
}, },
transport::{Receiver, Sender, grpc::GrpcBi}, transport::{Receiver, Sender, grpc::GrpcBi},
}; };
use kameo::actor::{ActorRef, Spawn as _}; use kameo::{
actor::{ActorRef, Spawn as _},
error::SendError,
};
use tonic::Status; use tonic::Status;
use tracing::{info, warn}; use tracing::{info, warn};
use crate::{ use crate::{
actors::client::{ClientConnection, session::ClientSession}, actors::{
client::{
self, ClientConnection,
session::{ClientSession, Error, HandleQueryVaultState},
},
keyholder::KeyHolderState,
},
grpc::request_tracker::RequestTracker, grpc::request_tracker::RequestTracker,
}; };
mod auth; mod auth;
mod evm;
mod inbound; mod inbound;
mod outbound; mod outbound;
mod vault;
async fn dispatch_loop( async fn dispatch_loop(
mut bi: GrpcBi<ClientRequest, ClientResponse>, mut bi: GrpcBi<ClientRequest, ClientResponse>,
@@ -81,10 +89,21 @@ async fn dispatch_inner(
payload: ClientRequestPayload, payload: ClientRequestPayload,
) -> Result<ClientResponsePayload, Status> { ) -> Result<ClientResponsePayload, Status> {
match payload { match payload {
ClientRequestPayload::Vault(req) => vault::dispatch(actor, req).await, ClientRequestPayload::QueryVaultState(_) => {
ClientRequestPayload::Evm(req) => evm::dispatch(actor, req).await, let state = match actor.ask(HandleQueryVaultState {}).await {
ClientRequestPayload::Auth(..) => { Ok(KeyHolderState::Unbootstrapped) => ProtoVaultState::Unbootstrapped,
warn!("Unsupported post-auth client auth request"); Ok(KeyHolderState::Sealed) => ProtoVaultState::Sealed,
Ok(KeyHolderState::Unsealed) => ProtoVaultState::Unsealed,
Err(SendError::HandlerError(Error::Internal)) => ProtoVaultState::Error,
Err(err) => {
warn!(error = ?err, "Failed to query vault state");
ProtoVaultState::Error
}
};
Ok(ClientResponsePayload::VaultState(state.into()))
}
payload => {
warn!(?payload, "Unsupported post-auth client request");
Err(Status::invalid_argument("Unsupported client request")) Err(Status::invalid_argument("Unsupported client request"))
} }
} }
@@ -93,21 +112,14 @@ async fn dispatch_inner(
pub async fn start(mut conn: ClientConnection, mut bi: GrpcBi<ClientRequest, ClientResponse>) { pub async fn start(mut conn: ClientConnection, mut bi: GrpcBi<ClientRequest, ClientResponse>) {
let mut request_tracker = RequestTracker::default(); let mut request_tracker = RequestTracker::default();
let client_id = match auth::start(&mut conn, &mut bi, &mut request_tracker).await { if let Err(e) = auth::start(&mut conn, &mut bi, &mut request_tracker).await {
Ok(id) => id, let mut transport = auth::AuthTransportAdapter::new(&mut bi, &mut request_tracker);
Err(err) => { let _ = transport.send(Err(e.clone())).await;
let _ = bi warn!(error = ?e, "Client authentication failed");
.send(Err(Status::unauthenticated(format!( return;
"Authentication failed: {}",
err
))))
.await;
warn!(error = ?err, "Client authentication failed");
return;
}
}; };
let actor = ClientSession::spawn(ClientSession::new(conn, client_id)); let actor = client::session::ClientSession::spawn(client::session::ClientSession::new(conn));
let actor_for_cleanup = actor.clone(); let actor_for_cleanup = actor.clone();
info!("Client authenticated successfully"); info!("Client authenticated successfully");

View File

@@ -1,18 +1,11 @@
use arbiter_proto::{ use arbiter_proto::{
ClientMetadata, ClientMetadata,
proto::{ proto::client::{
client::{ AuthChallenge as ProtoAuthChallenge, AuthChallengeRequest as ProtoAuthChallengeRequest,
ClientRequest, ClientResponse, AuthChallengeSolution as ProtoAuthChallengeSolution, AuthResult as ProtoAuthResult,
auth::{ ClientInfo as ProtoClientInfo, ClientRequest, ClientResponse,
self as proto_auth, AuthChallenge as ProtoAuthChallenge, client_request::Payload as ClientRequestPayload,
AuthChallengeRequest as ProtoAuthChallengeRequest, client_response::Payload as ClientResponsePayload,
AuthChallengeSolution as ProtoAuthChallengeSolution, AuthResult as ProtoAuthResult,
request::Payload as AuthRequestPayload, response::Payload as AuthResponsePayload,
},
client_request::Payload as ClientRequestPayload,
client_response::Payload as ClientResponsePayload,
},
shared::ClientInfo as ProtoClientInfo,
}, },
transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi}, transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi},
}; };
@@ -41,22 +34,22 @@ impl<'a> AuthTransportAdapter<'a> {
} }
} }
fn response_to_proto(response: auth::Outbound) -> AuthResponsePayload { fn response_to_proto(response: auth::Outbound) -> ClientResponsePayload {
match response { match response {
auth::Outbound::AuthChallenge { pubkey, nonce } => { auth::Outbound::AuthChallenge { pubkey, nonce } => {
AuthResponsePayload::Challenge(ProtoAuthChallenge { ClientResponsePayload::AuthChallenge(ProtoAuthChallenge {
pubkey: pubkey.to_bytes().to_vec(), pubkey: pubkey.to_bytes().to_vec(),
nonce, nonce,
}) })
} }
auth::Outbound::AuthSuccess => { auth::Outbound::AuthSuccess => {
AuthResponsePayload::Result(ProtoAuthResult::Success.into()) ClientResponsePayload::AuthResult(ProtoAuthResult::Success.into())
} }
} }
} }
fn error_to_proto(error: auth::Error) -> AuthResponsePayload { fn error_to_proto(error: auth::Error) -> ClientResponsePayload {
AuthResponsePayload::Result( ClientResponsePayload::AuthResult(
match error { match error {
auth::Error::InvalidChallengeSolution => ProtoAuthResult::InvalidSignature, auth::Error::InvalidChallengeSolution => ProtoAuthResult::InvalidSignature,
auth::Error::ApproveError(auth::ApproveError::Denied) => { auth::Error::ApproveError(auth::ApproveError::Denied) => {
@@ -76,20 +69,18 @@ impl<'a> AuthTransportAdapter<'a> {
async fn send_client_response( async fn send_client_response(
&mut self, &mut self,
payload: AuthResponsePayload, payload: ClientResponsePayload,
) -> Result<(), TransportError> { ) -> Result<(), TransportError> {
self.bi self.bi
.send(Ok(ClientResponse { .send(Ok(ClientResponse {
request_id: Some(self.request_tracker.current_request_id()), request_id: Some(self.request_tracker.current_request_id()),
payload: Some(ClientResponsePayload::Auth(proto_auth::Response { payload: Some(payload),
payload: Some(payload),
})),
})) }))
.await .await
} }
async fn send_auth_result(&mut self, result: ProtoAuthResult) -> Result<(), TransportError> { async fn send_auth_result(&mut self, result: ProtoAuthResult) -> Result<(), TransportError> {
self.send_client_response(AuthResponsePayload::Result(result.into())) self.send_client_response(ClientResponsePayload::AuthResult(result.into()))
.await .await
} }
} }
@@ -128,25 +119,9 @@ impl Receiver<auth::Inbound> for AuthTransportAdapter<'_> {
} }
}; };
let payload = request.payload?; let payload = request.payload?;
let ClientRequestPayload::Auth(auth_request) = payload else {
let _ = self
.bi
.send(Err(Status::invalid_argument(
"Unsupported client auth request",
)))
.await;
return None;
};
let Some(payload) = auth_request.payload else {
let _ = self
.bi
.send(Err(Status::invalid_argument("Missing client auth request payload")))
.await;
return None;
};
match payload { match payload {
AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest { ClientRequestPayload::AuthChallengeRequest(ProtoAuthChallengeRequest {
pubkey, pubkey,
client_info, client_info,
}) => { }) => {
@@ -170,7 +145,7 @@ impl Receiver<auth::Inbound> for AuthTransportAdapter<'_> {
metadata: client_metadata_from_proto(client_info), metadata: client_metadata_from_proto(client_info),
}) })
} }
AuthRequestPayload::ChallengeSolution(ProtoAuthChallengeSolution { ClientRequestPayload::AuthChallengeSolution(ProtoAuthChallengeSolution {
signature, signature,
}) => { }) => {
let Ok(signature) = ed25519_dalek::Signature::try_from(signature.as_slice()) else { let Ok(signature) = ed25519_dalek::Signature::try_from(signature.as_slice()) else {
@@ -181,6 +156,15 @@ impl Receiver<auth::Inbound> for AuthTransportAdapter<'_> {
}; };
Some(auth::Inbound::AuthChallengeSolution { signature }) Some(auth::Inbound::AuthChallengeSolution { signature })
} }
_ => {
let _ = self
.bi
.send(Err(Status::invalid_argument(
"Unsupported client auth request",
)))
.await;
None
}
} }
} }
} }
@@ -199,7 +183,8 @@ pub async fn start(
conn: &mut ClientConnection, conn: &mut ClientConnection,
bi: &mut GrpcBi<ClientRequest, ClientResponse>, bi: &mut GrpcBi<ClientRequest, ClientResponse>,
request_tracker: &mut RequestTracker, request_tracker: &mut RequestTracker,
) -> Result<i32, auth::Error> { ) -> Result<(), auth::Error> {
let mut transport = AuthTransportAdapter::new(bi, request_tracker); let mut transport = AuthTransportAdapter::new(bi, request_tracker);
client::auth::authenticate(conn, &mut transport).await client::auth::authenticate(conn, &mut transport).await?;
Ok(())
} }

View File

@@ -1,85 +0,0 @@
use arbiter_proto::proto::{
client::{
client_response::Payload as ClientResponsePayload,
evm::{
self as proto_evm, request::Payload as EvmRequestPayload,
response::Payload as EvmResponsePayload,
},
},
evm::{
EvmError as ProtoEvmError, EvmSignTransactionResponse,
evm_sign_transaction_response::Result as EvmSignTransactionResult,
},
};
use kameo::actor::ActorRef;
use tonic::Status;
use tracing::warn;
use crate::{
actors::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError},
grpc::{
Convert, TryConvert,
common::inbound::{RawEvmAddress, RawEvmTransaction},
},
};
fn wrap_response(payload: EvmResponsePayload) -> ClientResponsePayload {
ClientResponsePayload::Evm(proto_evm::Response {
payload: Some(payload),
})
}
pub(super) async fn dispatch(
actor: &ActorRef<ClientSession>,
req: proto_evm::Request,
) -> Result<ClientResponsePayload, Status> {
let Some(payload) = req.payload else {
return Err(Status::invalid_argument("Missing client EVM request payload"));
};
match payload {
EvmRequestPayload::SignTransaction(request) => {
let address = RawEvmAddress(request.wallet_address).try_convert()?;
let transaction = RawEvmTransaction(request.rlp_transaction).try_convert()?;
let response = match actor
.ask(HandleSignTransaction {
wallet_address: address,
transaction,
})
.await
{
Ok(signature) => EvmSignTransactionResponse {
result: Some(EvmSignTransactionResult::Signature(
signature.as_bytes().to_vec(),
)),
},
Err(kameo::error::SendError::HandlerError(SignTransactionRpcError::Vet(
vet_error,
))) => EvmSignTransactionResponse {
result: Some(vet_error.convert()),
},
Err(kameo::error::SendError::HandlerError(
SignTransactionRpcError::Internal,
)) => EvmSignTransactionResponse {
result: Some(EvmSignTransactionResult::Error(
ProtoEvmError::Internal.into(),
)),
},
Err(err) => {
warn!(error = ?err, "Failed to sign EVM transaction");
EvmSignTransactionResponse {
result: Some(EvmSignTransactionResult::Error(
ProtoEvmError::Internal.into(),
)),
}
}
};
Ok(wrap_response(EvmResponsePayload::SignTransaction(response)))
}
EvmRequestPayload::AnalyzeTransaction(_) => {
Err(Status::unimplemented("EVM transaction analysis is not yet implemented"))
}
}
}

View File

@@ -1,47 +0,0 @@
use arbiter_proto::proto::{
client::{
client_response::Payload as ClientResponsePayload,
vault::{
self as proto_vault, request::Payload as VaultRequestPayload,
response::Payload as VaultResponsePayload,
},
},
shared::VaultState as ProtoVaultState,
};
use kameo::{actor::ActorRef, error::SendError};
use tonic::Status;
use tracing::warn;
use crate::{
actors::{
client::session::{ClientSession, Error, HandleQueryVaultState},
keyholder::KeyHolderState,
},
};
pub(super) async fn dispatch(
actor: &ActorRef<ClientSession>,
req: proto_vault::Request,
) -> Result<ClientResponsePayload, Status> {
let Some(payload) = req.payload else {
return Err(Status::invalid_argument("Missing client vault request payload"));
};
match payload {
VaultRequestPayload::QueryState(_) => {
let state = match actor.ask(HandleQueryVaultState {}).await {
Ok(KeyHolderState::Unbootstrapped) => ProtoVaultState::Unbootstrapped,
Ok(KeyHolderState::Sealed) => ProtoVaultState::Sealed,
Ok(KeyHolderState::Unsealed) => ProtoVaultState::Unsealed,
Err(SendError::HandlerError(Error::Internal)) => ProtoVaultState::Error,
Err(err) => {
warn!(error = ?err, "Failed to query vault state");
ProtoVaultState::Error
}
};
Ok(ClientResponsePayload::Vault(proto_vault::Response {
payload: Some(VaultResponsePayload::State(state.into())),
}))
}
}
}

View File

@@ -1,2 +0,0 @@
pub mod inbound;
pub mod outbound;

View File

@@ -1,36 +0,0 @@
use alloy::{consensus::TxEip1559, primitives::Address, rlp::Decodable as _};
use crate::grpc::TryConvert;
pub struct RawEvmAddress(pub Vec<u8>);
impl TryConvert for RawEvmAddress {
type Output = Address;
type Error = tonic::Status;
fn try_convert(self) -> Result<Self::Output, Self::Error> {
let wallet_address = match <[u8; 20]>::try_from(self.0.as_slice()) {
Ok(address) => Address::from(address),
Err(_) => {
return Err(tonic::Status::invalid_argument(
"Invalid EVM wallet address",
));
}
};
Ok(wallet_address)
}
}
pub struct RawEvmTransaction(pub Vec<u8>);
impl TryConvert for RawEvmTransaction {
type Output = TxEip1559;
type Error = tonic::Status;
fn try_convert(self) -> Result<Self::Output, Self::Error> {
let tx = TxEip1559::decode(&mut self.0.as_slice()).map_err(|_| {
tonic::Status::invalid_argument("Invalid EVM transaction format")
})?;
Ok(tx)
}
}

View File

@@ -1,116 +0,0 @@
use alloy::primitives::U256;
use arbiter_proto::proto::{
evm::{EvmError as ProtoEvmError, evm_sign_transaction_response::Result as EvmSignTransactionResult},
shared::evm::{
EvalViolation as ProtoEvalViolation, GasLimitExceededViolation,
NoMatchingGrantError, PolicyViolationsError, SpecificMeaning as ProtoSpecificMeaning,
TokenInfo as ProtoTokenInfo, TransactionEvalError as ProtoTransactionEvalError,
eval_violation::Kind as ProtoEvalViolationKind,
specific_meaning::Meaning as ProtoSpecificMeaningKind,
transaction_eval_error::Kind as ProtoTransactionEvalErrorKind,
},
};
use crate::{
evm::{
PolicyError, VetError,
policies::{EvalViolation, SpecificMeaning},
},
grpc::Convert,
};
fn u256_to_proto_bytes(value: U256) -> Vec<u8> {
value.to_be_bytes::<32>().to_vec()
}
impl Convert for SpecificMeaning {
type Output = ProtoSpecificMeaning;
fn convert(self) -> Self::Output {
let kind = match self {
SpecificMeaning::EtherTransfer(meaning) => ProtoSpecificMeaningKind::EtherTransfer(
arbiter_proto::proto::shared::evm::EtherTransferMeaning {
to: meaning.to.to_vec(),
value: u256_to_proto_bytes(meaning.value),
},
),
SpecificMeaning::TokenTransfer(meaning) => ProtoSpecificMeaningKind::TokenTransfer(
arbiter_proto::proto::shared::evm::TokenTransferMeaning {
token: Some(ProtoTokenInfo {
symbol: meaning.token.symbol.to_string(),
address: meaning.token.contract.to_vec(),
chain_id: meaning.token.chain,
}),
to: meaning.to.to_vec(),
value: u256_to_proto_bytes(meaning.value),
},
),
};
ProtoSpecificMeaning {
meaning: Some(kind),
}
}
}
impl Convert for EvalViolation {
type Output = ProtoEvalViolation;
fn convert(self) -> Self::Output {
let kind = match self {
EvalViolation::InvalidTarget { target } => {
ProtoEvalViolationKind::InvalidTarget(target.to_vec())
}
EvalViolation::GasLimitExceeded {
max_gas_fee_per_gas,
max_priority_fee_per_gas,
} => ProtoEvalViolationKind::GasLimitExceeded(GasLimitExceededViolation {
max_gas_fee_per_gas: max_gas_fee_per_gas.map(u256_to_proto_bytes),
max_priority_fee_per_gas: max_priority_fee_per_gas.map(u256_to_proto_bytes),
}),
EvalViolation::RateLimitExceeded => ProtoEvalViolationKind::RateLimitExceeded(()),
EvalViolation::VolumetricLimitExceeded => {
ProtoEvalViolationKind::VolumetricLimitExceeded(())
}
EvalViolation::InvalidTime => ProtoEvalViolationKind::InvalidTime(()),
EvalViolation::InvalidTransactionType => {
ProtoEvalViolationKind::InvalidTransactionType(())
}
};
ProtoEvalViolation { kind: Some(kind) }
}
}
impl Convert for VetError {
type Output = EvmSignTransactionResult;
fn convert(self) -> Self::Output {
let kind = match self {
VetError::ContractCreationNotSupported => {
ProtoTransactionEvalErrorKind::ContractCreationNotSupported(())
}
VetError::UnsupportedTransactionType => {
ProtoTransactionEvalErrorKind::UnsupportedTransactionType(())
}
VetError::Evaluated(meaning, policy_error) => match policy_error {
PolicyError::NoMatchingGrant => {
ProtoTransactionEvalErrorKind::NoMatchingGrant(NoMatchingGrantError {
meaning: Some(meaning.convert()),
})
}
PolicyError::Violations(violations) => {
ProtoTransactionEvalErrorKind::PolicyViolations(PolicyViolationsError {
meaning: Some(meaning.convert()),
violations: violations.into_iter().map(Convert::convert).collect(),
})
}
PolicyError::Database(_) => {
return EvmSignTransactionResult::Error(ProtoEvmError::Internal.into());
}
},
};
EvmSignTransactionResult::EvalError(ProtoTransactionEvalError { kind: Some(kind) }.into())
}
}

View File

@@ -14,13 +14,10 @@ use crate::{
grpc::user_agent::start, grpc::user_agent::start,
}; };
mod request_tracker;
pub mod client; pub mod client;
mod request_tracker;
pub mod user_agent; pub mod user_agent;
mod common;
pub trait Convert { pub trait Convert {
type Output; type Output;

View File

@@ -2,8 +2,28 @@ use tokio::sync::mpsc;
use arbiter_proto::{ use arbiter_proto::{
proto::{ proto::{
client::ClientInfo as ProtoClientMetadata,
evm::{
EvmError as ProtoEvmError, EvmGrantCreateRequest, EvmGrantCreateResponse,
EvmGrantDeleteRequest, EvmGrantDeleteResponse, EvmGrantList, EvmGrantListResponse,
GrantEntry, WalletCreateResponse, WalletEntry, WalletList, WalletListResponse,
evm_grant_create_response::Result as EvmGrantCreateResult,
evm_grant_delete_response::Result as EvmGrantDeleteResult,
evm_grant_list_response::Result as EvmGrantListResult,
wallet_create_response::Result as WalletCreateResult,
wallet_list_response::Result as WalletListResult,
},
user_agent::{ user_agent::{
UserAgentRequest, UserAgentResponse, BootstrapEncryptedKey as ProtoBootstrapEncryptedKey,
BootstrapResult as ProtoBootstrapResult, ListWalletAccessResponse,
SdkClientConnectionCancel as ProtoSdkClientConnectionCancel,
SdkClientConnectionRequest as ProtoSdkClientConnectionRequest,
SdkClientEntry as ProtoSdkClientEntry, SdkClientError as ProtoSdkClientError,
SdkClientGrantWalletAccess, SdkClientList as ProtoSdkClientList,
SdkClientListResponse as ProtoSdkClientListResponse, SdkClientRevokeWalletAccess, UnsealEncryptedKey as ProtoUnsealEncryptedKey,
UnsealResult as ProtoUnsealResult, UnsealStart, UserAgentRequest, UserAgentResponse,
VaultState as ProtoVaultState,
sdk_client_list_response::Result as ProtoSdkClientListResult,
user_agent_request::Payload as UserAgentRequestPayload, user_agent_request::Payload as UserAgentRequestPayload,
user_agent_response::Payload as UserAgentResponsePayload, user_agent_response::Payload as UserAgentResponsePayload,
}, },
@@ -11,20 +31,33 @@ use arbiter_proto::{
transport::{Error as TransportError, Receiver, Sender, grpc::GrpcBi}, transport::{Error as TransportError, Receiver, Sender, grpc::GrpcBi},
}; };
use async_trait::async_trait; use async_trait::async_trait;
use kameo::actor::{ActorRef, Spawn as _}; use kameo::{
actor::{ActorRef, Spawn as _},
error::SendError,
};
use tonic::Status; use tonic::Status;
use tracing::{error, info, warn}; use tracing::{error, info, warn};
use crate::{ use crate::{
actors::user_agent::{OutOfBand, UserAgentConnection, UserAgentSession}, actors::{
grpc::request_tracker::RequestTracker, keyholder::KeyHolderState,
user_agent::{
OutOfBand, UserAgentConnection, UserAgentSession,
session::connection::{
BootstrapError, HandleBootstrapEncryptedKey, HandleEvmWalletCreate,
HandleEvmWalletList, HandleGrantCreate, HandleGrantDelete,
HandleGrantEvmWalletAccess, HandleGrantList, HandleListWalletAccess,
HandleNewClientApprove, HandleQueryVaultState, HandleRevokeEvmWalletAccess,
HandleSdkClientList, HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError,
},
},
},
db::models::NewEvmWalletAccess,
grpc::{Convert, TryConvert, request_tracker::RequestTracker},
}; };
mod auth; mod auth;
mod evm;
mod inbound; mod inbound;
mod outbound; mod outbound;
mod sdk_client;
mod vault;
pub struct OutOfBandAdapter(mpsc::Sender<OutOfBand>); pub struct OutOfBandAdapter(mpsc::Sender<OutOfBand>);
@@ -52,7 +85,23 @@ async fn dispatch_loop(
return; return;
}; };
let payload = sdk_client::out_of_band_payload(oob); let payload = match oob {
OutOfBand::ClientConnectionRequest { profile } => {
UserAgentResponsePayload::SdkClientConnectionRequest(ProtoSdkClientConnectionRequest {
pubkey: profile.pubkey.to_bytes().to_vec(),
info: Some(ProtoClientMetadata {
name: profile.metadata.name,
description: profile.metadata.description,
version: profile.metadata.version,
}),
})
}
OutOfBand::ClientConnectionCancel { pubkey } => {
UserAgentResponsePayload::SdkClientConnectionCancel(ProtoSdkClientConnectionCancel {
pubkey: pubkey.to_bytes().to_vec(),
})
}
};
if bi.send(Ok(UserAgentResponse { id: None, payload: Some(payload) })).await.is_err() { if bi.send(Ok(UserAgentResponse { id: None, payload: Some(payload) })).await.is_err() {
return; return;
@@ -94,7 +143,7 @@ async fn dispatch_loop(
} }
Ok(None) => {} Ok(None) => {}
Err(status) => { Err(status) => {
error!(?status, "Failed to process user agent request"); error!(?status, "Failed to process user agent request");
let _ = bi.send(Err(status)).await; let _ = bi.send(Err(status)).await;
return; return;
} }
@@ -108,15 +157,288 @@ async fn dispatch_inner(
actor: &ActorRef<UserAgentSession>, actor: &ActorRef<UserAgentSession>,
payload: UserAgentRequestPayload, payload: UserAgentRequestPayload,
) -> Result<Option<UserAgentResponsePayload>, Status> { ) -> Result<Option<UserAgentResponsePayload>, Status> {
match payload { let response = match payload {
UserAgentRequestPayload::Vault(req) => vault::dispatch(actor, req).await, UserAgentRequestPayload::UnsealStart(UnsealStart { client_pubkey }) => {
UserAgentRequestPayload::Evm(req) => evm::dispatch(actor, req).await, let client_pubkey = <[u8; 32]>::try_from(client_pubkey)
UserAgentRequestPayload::SdkClient(req) => sdk_client::dispatch(actor, req).await, .map(x25519_dalek::PublicKey::from)
UserAgentRequestPayload::Auth(..) => { .map_err(|_| Status::invalid_argument("Invalid X25519 public key"))?;
warn!("Unsupported post-auth user agent auth request");
Err(Status::invalid_argument("Unsupported user-agent request")) let response = actor
.ask(HandleUnsealRequest { client_pubkey })
.await
.map_err(|err| {
warn!(error = ?err, "Failed to handle unseal start request");
Status::internal("Failed to start unseal flow")
})?;
UserAgentResponsePayload::UnsealStartResponse(
arbiter_proto::proto::user_agent::UnsealStartResponse {
server_pubkey: response.server_pubkey.as_bytes().to_vec(),
},
)
} }
}
UserAgentRequestPayload::UnsealEncryptedKey(ProtoUnsealEncryptedKey {
nonce,
ciphertext,
associated_data,
}) => {
let result = match actor
.ask(HandleUnsealEncryptedKey {
nonce,
ciphertext,
associated_data,
})
.await
{
Ok(()) => ProtoUnsealResult::Success,
Err(SendError::HandlerError(UnsealError::InvalidKey)) => {
ProtoUnsealResult::InvalidKey
}
Err(err) => {
warn!(error = ?err, "Failed to handle unseal request");
return Err(Status::internal("Failed to unseal vault"));
}
};
UserAgentResponsePayload::UnsealResult(result.into())
}
UserAgentRequestPayload::BootstrapEncryptedKey(ProtoBootstrapEncryptedKey {
nonce,
ciphertext,
associated_data,
}) => {
let result = match actor
.ask(HandleBootstrapEncryptedKey {
nonce,
ciphertext,
associated_data,
})
.await
{
Ok(()) => ProtoBootstrapResult::Success,
Err(SendError::HandlerError(BootstrapError::InvalidKey)) => {
ProtoBootstrapResult::InvalidKey
}
Err(SendError::HandlerError(BootstrapError::AlreadyBootstrapped)) => {
ProtoBootstrapResult::AlreadyBootstrapped
}
Err(err) => {
warn!(error = ?err, "Failed to handle bootstrap request");
return Err(Status::internal("Failed to bootstrap vault"));
}
};
UserAgentResponsePayload::BootstrapResult(result.into())
}
UserAgentRequestPayload::QueryVaultState(_) => {
let state = match actor.ask(HandleQueryVaultState {}).await {
Ok(KeyHolderState::Unbootstrapped) => ProtoVaultState::Unbootstrapped,
Ok(KeyHolderState::Sealed) => ProtoVaultState::Sealed,
Ok(KeyHolderState::Unsealed) => ProtoVaultState::Unsealed,
Err(err) => {
warn!(error = ?err, "Failed to query vault state");
ProtoVaultState::Error
}
};
UserAgentResponsePayload::VaultState(state.into())
}
UserAgentRequestPayload::EvmWalletCreate(_) => {
let result = match actor.ask(HandleEvmWalletCreate {}).await {
Ok((wallet_id, address)) => WalletCreateResult::Wallet(WalletEntry {
id: wallet_id,
address: address.to_vec(),
}),
Err(err) => {
warn!(error = ?err, "Failed to create EVM wallet");
WalletCreateResult::Error(ProtoEvmError::Internal.into())
}
};
UserAgentResponsePayload::EvmWalletCreate(WalletCreateResponse {
result: Some(result),
})
}
UserAgentRequestPayload::EvmWalletList(_) => {
let result = match actor.ask(HandleEvmWalletList {}).await {
Ok(wallets) => WalletListResult::Wallets(WalletList {
wallets: wallets
.into_iter()
.map(|(id, address)| WalletEntry {
address: address.to_vec(),
id,
})
.collect(),
}),
Err(err) => {
warn!(error = ?err, "Failed to list EVM wallets");
WalletListResult::Error(ProtoEvmError::Internal.into())
}
};
UserAgentResponsePayload::EvmWalletList(WalletListResponse {
result: Some(result),
})
}
UserAgentRequestPayload::EvmGrantList(_) => {
let result = match actor.ask(HandleGrantList {}).await {
Ok(grants) => EvmGrantListResult::Grants(EvmGrantList {
grants: grants
.into_iter()
.map(|grant| GrantEntry {
id: grant.id,
wallet_access_id: grant.shared.wallet_access_id,
shared: Some(grant.shared.convert()),
specific: Some(grant.settings.convert()),
})
.collect(),
}),
Err(err) => {
warn!(error = ?err, "Failed to list EVM grants");
EvmGrantListResult::Error(ProtoEvmError::Internal.into())
}
};
UserAgentResponsePayload::EvmGrantList(EvmGrantListResponse {
result: Some(result),
})
}
UserAgentRequestPayload::EvmGrantCreate(EvmGrantCreateRequest { shared, specific }) => {
let basic = shared
.ok_or_else(|| Status::invalid_argument("Missing shared grant settings"))?
.try_convert()?;
let grant = specific
.ok_or_else(|| Status::invalid_argument("Missing specific grant settings"))?
.try_convert()?;
let result = match actor.ask(HandleGrantCreate { basic, grant }).await {
Ok(grant_id) => EvmGrantCreateResult::GrantId(grant_id),
Err(err) => {
warn!(error = ?err, "Failed to create EVM grant");
EvmGrantCreateResult::Error(ProtoEvmError::Internal.into())
}
};
UserAgentResponsePayload::EvmGrantCreate(EvmGrantCreateResponse {
result: Some(result),
})
}
UserAgentRequestPayload::EvmGrantDelete(EvmGrantDeleteRequest { grant_id }) => {
let result = match actor.ask(HandleGrantDelete { grant_id }).await {
Ok(()) => EvmGrantDeleteResult::Ok(()),
Err(err) => {
warn!(error = ?err, "Failed to delete EVM grant");
EvmGrantDeleteResult::Error(ProtoEvmError::Internal.into())
}
};
UserAgentResponsePayload::EvmGrantDelete(EvmGrantDeleteResponse {
result: Some(result),
})
}
UserAgentRequestPayload::SdkClientConnectionResponse(resp) => {
let pubkey_bytes = <[u8; 32]>::try_from(resp.pubkey)
.map_err(|_| Status::invalid_argument("Invalid Ed25519 public key length"))?;
let pubkey = ed25519_dalek::VerifyingKey::from_bytes(&pubkey_bytes)
.map_err(|_| Status::invalid_argument("Invalid Ed25519 public key"))?;
actor
.ask(HandleNewClientApprove {
approved: resp.approved,
pubkey,
})
.await
.map_err(|err| {
warn!(?err, "Failed to process client connection response");
Status::internal("Failed to process response")
})?;
return Ok(None);
}
UserAgentRequestPayload::SdkClientRevoke(_) => todo!(),
UserAgentRequestPayload::SdkClientList(_) => {
let result = match actor.ask(HandleSdkClientList {}).await {
Ok(clients) => ProtoSdkClientListResult::Clients(ProtoSdkClientList {
clients: clients
.into_iter()
.map(|(client, metadata)| ProtoSdkClientEntry {
id: client.id,
pubkey: client.public_key,
info: Some(ProtoClientMetadata {
name: metadata.name,
description: metadata.description,
version: metadata.version,
}),
created_at: client.created_at.0.timestamp() as i32,
})
.collect(),
}),
Err(err) => {
warn!(error = ?err, "Failed to list SDK clients");
ProtoSdkClientListResult::Error(ProtoSdkClientError::Internal.into())
}
};
UserAgentResponsePayload::SdkClientListResponse(ProtoSdkClientListResponse {
result: Some(result),
})
}
UserAgentRequestPayload::GrantWalletAccess(SdkClientGrantWalletAccess { accesses }) => {
let entries: Vec<NewEvmWalletAccess> =
accesses.into_iter().map(|a| a.convert()).collect();
match actor.ask(HandleGrantEvmWalletAccess { entries }).await {
Ok(()) => {
info!("Successfully granted wallet access");
return Ok(None);
}
Err(err) => {
warn!(error = ?err, "Failed to grant wallet access");
return Err(Status::internal("Failed to grant wallet access"));
}
}
}
UserAgentRequestPayload::RevokeWalletAccess(SdkClientRevokeWalletAccess { accesses }) => {
match actor
.ask(HandleRevokeEvmWalletAccess { entries: accesses })
.await
{
Ok(()) => {
info!("Successfully revoked wallet access");
return Ok(None);
}
Err(err) => {
warn!(error = ?err, "Failed to revoke wallet access");
return Err(Status::internal("Failed to revoke wallet access"));
}
}
}
UserAgentRequestPayload::ListWalletAccess(_) => {
let result = match actor.ask(HandleListWalletAccess {}).await {
Ok(accesses) => ListWalletAccessResponse {
accesses: accesses.into_iter().map(|a| a.convert()).collect(),
},
Err(err) => {
warn!(error = ?err, "Failed to list wallet access");
return Err(Status::internal("Failed to list wallet access"));
}
};
UserAgentResponsePayload::ListWalletAccessResponse(result)
}
UserAgentRequestPayload::AuthChallengeRequest(..)
| UserAgentRequestPayload::AuthChallengeSolution(..) => {
warn!(?payload, "Unsupported post-auth user agent request");
return Err(Status::invalid_argument("Unsupported user-agent request"));
}
};
Ok(Some(response))
} }
pub async fn start( pub async fn start(

View File

@@ -1,12 +1,9 @@
use arbiter_proto::{ use arbiter_proto::{
proto::user_agent::{ proto::user_agent::{
UserAgentRequest, UserAgentResponse, auth::{ AuthChallenge as ProtoAuthChallenge, AuthChallengeRequest as ProtoAuthChallengeRequest,
self as proto_auth, AuthChallenge as ProtoAuthChallenge, AuthChallengeSolution as ProtoAuthChallengeSolution, AuthResult as ProtoAuthResult,
AuthChallengeRequest as ProtoAuthChallengeRequest, KeyType as ProtoKeyType, UserAgentRequest, UserAgentResponse,
AuthChallengeSolution as ProtoAuthChallengeSolution, AuthResult as ProtoAuthResult, user_agent_request::Payload as UserAgentRequestPayload,
KeyType as ProtoKeyType, request::Payload as AuthRequestPayload,
response::Payload as AuthResponsePayload,
}, user_agent_request::Payload as UserAgentRequestPayload,
user_agent_response::Payload as UserAgentResponsePayload, user_agent_response::Payload as UserAgentResponsePayload,
}, },
transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi}, transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi},
@@ -39,14 +36,12 @@ impl<'a> AuthTransportAdapter<'a> {
async fn send_user_agent_response( async fn send_user_agent_response(
&mut self, &mut self,
payload: AuthResponsePayload, payload: UserAgentResponsePayload,
) -> Result<(), TransportError> { ) -> Result<(), TransportError> {
self.bi self.bi
.send(Ok(UserAgentResponse { .send(Ok(UserAgentResponse {
id: Some(self.request_tracker.current_request_id()), id: Some(self.request_tracker.current_request_id()),
payload: Some(UserAgentResponsePayload::Auth(proto_auth::Response { payload: Some(payload),
payload: Some(payload),
})),
})) }))
.await .await
} }
@@ -61,17 +56,19 @@ impl Sender<Result<auth::Outbound, auth::Error>> for AuthTransportAdapter<'_> {
use auth::{Error, Outbound}; use auth::{Error, Outbound};
let payload = match item { let payload = match item {
Ok(Outbound::AuthChallenge { nonce }) => { Ok(Outbound::AuthChallenge { nonce }) => {
AuthResponsePayload::Challenge(ProtoAuthChallenge { nonce }) UserAgentResponsePayload::AuthChallenge(ProtoAuthChallenge { nonce })
}
Ok(Outbound::AuthSuccess) => {
UserAgentResponsePayload::AuthResult(ProtoAuthResult::Success.into())
} }
Ok(Outbound::AuthSuccess) => AuthResponsePayload::Result(ProtoAuthResult::Success.into()),
Err(Error::UnregisteredPublicKey) => { Err(Error::UnregisteredPublicKey) => {
AuthResponsePayload::Result(ProtoAuthResult::InvalidKey.into()) UserAgentResponsePayload::AuthResult(ProtoAuthResult::InvalidKey.into())
} }
Err(Error::InvalidChallengeSolution) => { Err(Error::InvalidChallengeSolution) => {
AuthResponsePayload::Result(ProtoAuthResult::InvalidSignature.into()) UserAgentResponsePayload::AuthResult(ProtoAuthResult::InvalidSignature.into())
} }
Err(Error::InvalidBootstrapToken) => { Err(Error::InvalidBootstrapToken) => {
AuthResponsePayload::Result(ProtoAuthResult::TokenInvalid.into()) UserAgentResponsePayload::AuthResult(ProtoAuthResult::TokenInvalid.into())
} }
Err(Error::Internal { details }) => { Err(Error::Internal { details }) => {
return self.bi.send(Err(Status::internal(details))).await; return self.bi.send(Err(Status::internal(details))).await;
@@ -115,26 +112,8 @@ impl Receiver<auth::Inbound> for AuthTransportAdapter<'_> {
return None; return None;
}; };
let UserAgentRequestPayload::Auth(auth_request) = payload else {
let _ = self
.bi
.send(Err(Status::invalid_argument(
"Unsupported user-agent auth request",
)))
.await;
return None;
};
let Some(payload) = auth_request.payload else {
warn!(
event = "received auth request with empty payload",
"grpc.useragent.auth_adapter"
);
return None;
};
match payload { match payload {
AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest { UserAgentRequestPayload::AuthChallengeRequest(ProtoAuthChallengeRequest {
pubkey, pubkey,
bootstrap_token, bootstrap_token,
key_type, key_type,
@@ -171,9 +150,18 @@ impl Receiver<auth::Inbound> for AuthTransportAdapter<'_> {
bootstrap_token, bootstrap_token,
}) })
} }
AuthRequestPayload::ChallengeSolution(ProtoAuthChallengeSolution { UserAgentRequestPayload::AuthChallengeSolution(ProtoAuthChallengeSolution {
signature, signature,
}) => Some(auth::Inbound::AuthChallengeSolution { signature }), }) => Some(auth::Inbound::AuthChallengeSolution { signature }),
_ => {
let _ = self
.bi
.send(Err(Status::invalid_argument(
"Unsupported user-agent auth request",
)))
.await;
None
}
} }
} }
} }

View File

@@ -1,230 +0,0 @@
use arbiter_proto::proto::{
evm::{
EvmError as ProtoEvmError, EvmGrantCreateRequest, EvmGrantCreateResponse,
EvmGrantDeleteRequest, EvmGrantDeleteResponse, EvmGrantList, EvmGrantListResponse,
EvmSignTransactionResponse, GrantEntry, WalletCreateResponse, WalletEntry, WalletList,
WalletListResponse,
evm_grant_create_response::Result as EvmGrantCreateResult,
evm_grant_delete_response::Result as EvmGrantDeleteResult,
evm_grant_list_response::Result as EvmGrantListResult,
evm_sign_transaction_response::Result as EvmSignTransactionResult,
wallet_create_response::Result as WalletCreateResult,
wallet_list_response::Result as WalletListResult,
},
user_agent::{
evm::{
self as proto_evm, SignTransactionRequest as ProtoSignTransactionRequest,
request::Payload as EvmRequestPayload, response::Payload as EvmResponsePayload,
},
user_agent_response::Payload as UserAgentResponsePayload,
},
};
use kameo::actor::ActorRef;
use tonic::Status;
use tracing::warn;
use crate::{
actors::user_agent::{
UserAgentSession,
session::connection::{
HandleEvmWalletCreate, HandleEvmWalletList, HandleGrantCreate, HandleGrantDelete,
HandleGrantList, HandleSignTransaction,
SignTransactionError as SessionSignTransactionError,
},
},
grpc::{
Convert, TryConvert,
common::inbound::{RawEvmAddress, RawEvmTransaction},
},
};
fn wrap_evm_response(payload: EvmResponsePayload) -> UserAgentResponsePayload {
UserAgentResponsePayload::Evm(proto_evm::Response {
payload: Some(payload),
})
}
pub(super) async fn dispatch(
actor: &ActorRef<UserAgentSession>,
req: proto_evm::Request,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let Some(payload) = req.payload else {
return Err(Status::invalid_argument("Missing EVM request payload"));
};
match payload {
EvmRequestPayload::WalletCreate(_) => handle_wallet_create(actor).await,
EvmRequestPayload::WalletList(_) => handle_wallet_list(actor).await,
EvmRequestPayload::GrantCreate(req) => handle_grant_create(actor, req).await,
EvmRequestPayload::GrantDelete(req) => handle_grant_delete(actor, req).await,
EvmRequestPayload::GrantList(_) => handle_grant_list(actor).await,
EvmRequestPayload::SignTransaction(req) => handle_sign_transaction(actor, req).await,
}
}
async fn handle_wallet_create(
actor: &ActorRef<UserAgentSession>,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let result = match actor.ask(HandleEvmWalletCreate {}).await {
Ok((wallet_id, address)) => WalletCreateResult::Wallet(WalletEntry {
id: wallet_id,
address: address.to_vec(),
}),
Err(err) => {
warn!(error = ?err, "Failed to create EVM wallet");
WalletCreateResult::Error(ProtoEvmError::Internal.into())
}
};
Ok(Some(wrap_evm_response(EvmResponsePayload::WalletCreate(
WalletCreateResponse {
result: Some(result),
},
))))
}
async fn handle_wallet_list(
actor: &ActorRef<UserAgentSession>,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let result = match actor.ask(HandleEvmWalletList {}).await {
Ok(wallets) => WalletListResult::Wallets(WalletList {
wallets: wallets
.into_iter()
.map(|(id, address)| WalletEntry {
address: address.to_vec(),
id,
})
.collect(),
}),
Err(err) => {
warn!(error = ?err, "Failed to list EVM wallets");
WalletListResult::Error(ProtoEvmError::Internal.into())
}
};
Ok(Some(wrap_evm_response(EvmResponsePayload::WalletList(
WalletListResponse {
result: Some(result),
},
))))
}
async fn handle_grant_list(
actor: &ActorRef<UserAgentSession>,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let result = match actor.ask(HandleGrantList {}).await {
Ok(grants) => EvmGrantListResult::Grants(EvmGrantList {
grants: grants
.into_iter()
.map(|grant| GrantEntry {
id: grant.id,
wallet_access_id: grant.shared.wallet_access_id,
shared: Some(grant.shared.convert()),
specific: Some(grant.settings.convert()),
})
.collect(),
}),
Err(err) => {
warn!(error = ?err, "Failed to list EVM grants");
EvmGrantListResult::Error(ProtoEvmError::Internal.into())
}
};
Ok(Some(wrap_evm_response(EvmResponsePayload::GrantList(
EvmGrantListResponse {
result: Some(result),
},
))))
}
async fn handle_grant_create(
actor: &ActorRef<UserAgentSession>,
req: EvmGrantCreateRequest,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let basic = req
.shared
.ok_or_else(|| Status::invalid_argument("Missing shared grant settings"))?
.try_convert()?;
let grant = req
.specific
.ok_or_else(|| Status::invalid_argument("Missing specific grant settings"))?
.try_convert()?;
let result = match actor.ask(HandleGrantCreate { basic, grant }).await {
Ok(grant_id) => EvmGrantCreateResult::GrantId(grant_id),
Err(err) => {
warn!(error = ?err, "Failed to create EVM grant");
EvmGrantCreateResult::Error(ProtoEvmError::Internal.into())
}
};
Ok(Some(wrap_evm_response(EvmResponsePayload::GrantCreate(
EvmGrantCreateResponse {
result: Some(result),
},
))))
}
async fn handle_grant_delete(
actor: &ActorRef<UserAgentSession>,
req: EvmGrantDeleteRequest,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let result = match actor.ask(HandleGrantDelete { grant_id: req.grant_id }).await {
Ok(()) => EvmGrantDeleteResult::Ok(()),
Err(err) => {
warn!(error = ?err, "Failed to delete EVM grant");
EvmGrantDeleteResult::Error(ProtoEvmError::Internal.into())
}
};
Ok(Some(wrap_evm_response(EvmResponsePayload::GrantDelete(
EvmGrantDeleteResponse {
result: Some(result),
},
))))
}
async fn handle_sign_transaction(
actor: &ActorRef<UserAgentSession>,
req: ProtoSignTransactionRequest,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let request = req
.request
.ok_or_else(|| Status::invalid_argument("Missing sign transaction request"))?;
let wallet_address = RawEvmAddress(request.wallet_address).try_convert()?;
let transaction = RawEvmTransaction(request.rlp_transaction).try_convert()?;
let response = match actor
.ask(HandleSignTransaction {
client_id: req.client_id,
wallet_address,
transaction,
})
.await
{
Ok(signature) => EvmSignTransactionResponse {
result: Some(EvmSignTransactionResult::Signature(
signature.as_bytes().to_vec(),
)),
},
Err(kameo::error::SendError::HandlerError(
SessionSignTransactionError::Vet(vet_error),
)) => EvmSignTransactionResponse {
result: Some(vet_error.convert()),
},
Err(kameo::error::SendError::HandlerError(
SessionSignTransactionError::Internal,
)) => EvmSignTransactionResponse {
result: Some(EvmSignTransactionResult::Error(
ProtoEvmError::Internal.into(),
)),
},
Err(err) => {
warn!(error = ?err, "Failed to sign EVM transaction");
EvmSignTransactionResponse {
result: Some(EvmSignTransactionResult::Error(
ProtoEvmError::Internal.into(),
)),
}
}
};
Ok(Some(wrap_evm_response(EvmResponsePayload::SignTransaction(
response,
))))
}

View File

@@ -5,9 +5,7 @@ use arbiter_proto::proto::evm::{
TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit, TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit,
specific_grant::Grant as ProtoSpecificGrantType, specific_grant::Grant as ProtoSpecificGrantType,
}; };
use arbiter_proto::proto::user_agent::sdk_client::{ use arbiter_proto::proto::user_agent::{SdkClientWalletAccess, WalletAccess};
WalletAccess, WalletAccessEntry as SdkClientWalletAccess,
};
use chrono::{DateTime, TimeZone, Utc}; use chrono::{DateTime, TimeZone, Utc};
use prost_types::Timestamp as ProtoTimestamp; use prost_types::Timestamp as ProtoTimestamp;
use tonic::Status; use tonic::Status;

View File

@@ -5,9 +5,7 @@ use arbiter_proto::proto::{
TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit, TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit,
specific_grant::Grant as ProtoSpecificGrantType, specific_grant::Grant as ProtoSpecificGrantType,
}, },
user_agent::sdk_client::{ user_agent::{SdkClientWalletAccess as ProtoSdkClientWalletAccess, WalletAccess},
WalletAccess, WalletAccessEntry as ProtoSdkClientWalletAccess,
},
}; };
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use prost_types::Timestamp as ProtoTimestamp; use prost_types::Timestamp as ProtoTimestamp;

View File

@@ -1,190 +0,0 @@
use arbiter_proto::proto::{
user_agent::{
sdk_client::{
self as proto_sdk_client, ConnectionCancel as ProtoSdkClientConnectionCancel,
ConnectionRequest as ProtoSdkClientConnectionRequest,
ConnectionResponse as ProtoSdkClientConnectionResponse, Entry as ProtoSdkClientEntry,
Error as ProtoSdkClientError, GrantWalletAccess as ProtoSdkClientGrantWalletAccess,
List as ProtoSdkClientList, ListResponse as ProtoSdkClientListResponse,
ListWalletAccessResponse, RevokeWalletAccess as ProtoSdkClientRevokeWalletAccess,
list_response::Result as ProtoSdkClientListResult,
request::Payload as SdkClientRequestPayload,
response::Payload as SdkClientResponsePayload,
},
user_agent_response::Payload as UserAgentResponsePayload,
},
shared::ClientInfo as ProtoClientMetadata,
};
use kameo::actor::ActorRef;
use tonic::Status;
use tracing::{info, warn};
use crate::{
actors::user_agent::{
OutOfBand, UserAgentSession,
session::connection::{
HandleGrantEvmWalletAccess, HandleListWalletAccess, HandleNewClientApprove,
HandleRevokeEvmWalletAccess, HandleSdkClientList,
},
},
db::models::NewEvmWalletAccess,
grpc::Convert,
};
fn wrap_sdk_client_response(payload: SdkClientResponsePayload) -> UserAgentResponsePayload {
UserAgentResponsePayload::SdkClient(proto_sdk_client::Response {
payload: Some(payload),
})
}
pub(super) fn out_of_band_payload(oob: OutOfBand) -> UserAgentResponsePayload {
match oob {
OutOfBand::ClientConnectionRequest { profile } => wrap_sdk_client_response(
SdkClientResponsePayload::ConnectionRequest(ProtoSdkClientConnectionRequest {
pubkey: profile.pubkey.to_bytes().to_vec(),
info: Some(ProtoClientMetadata {
name: profile.metadata.name,
description: profile.metadata.description,
version: profile.metadata.version,
}),
}),
),
OutOfBand::ClientConnectionCancel { pubkey } => wrap_sdk_client_response(
SdkClientResponsePayload::ConnectionCancel(ProtoSdkClientConnectionCancel {
pubkey: pubkey.to_bytes().to_vec(),
}),
),
}
}
pub(super) async fn dispatch(
actor: &ActorRef<UserAgentSession>,
req: proto_sdk_client::Request,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let Some(payload) = req.payload else {
return Err(Status::invalid_argument("Missing SDK client request payload"));
};
match payload {
SdkClientRequestPayload::ConnectionResponse(resp) => {
handle_connection_response(actor, resp).await
}
SdkClientRequestPayload::Revoke(_) => {
Err(Status::unimplemented("SdkClientRevoke is not yet implemented"))
}
SdkClientRequestPayload::List(_) => handle_list(actor).await,
SdkClientRequestPayload::GrantWalletAccess(req) => handle_grant_wallet_access(actor, req).await,
SdkClientRequestPayload::RevokeWalletAccess(req) => {
handle_revoke_wallet_access(actor, req).await
}
SdkClientRequestPayload::ListWalletAccess(_) => handle_list_wallet_access(actor).await,
}
}
async fn handle_connection_response(
actor: &ActorRef<UserAgentSession>,
resp: ProtoSdkClientConnectionResponse,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let pubkey_bytes = <[u8; 32]>::try_from(resp.pubkey)
.map_err(|_| Status::invalid_argument("Invalid Ed25519 public key length"))?;
let pubkey = ed25519_dalek::VerifyingKey::from_bytes(&pubkey_bytes)
.map_err(|_| Status::invalid_argument("Invalid Ed25519 public key"))?;
actor
.ask(HandleNewClientApprove {
approved: resp.approved,
pubkey,
})
.await
.map_err(|err| {
warn!(?err, "Failed to process client connection response");
Status::internal("Failed to process response")
})?;
Ok(None)
}
async fn handle_list(
actor: &ActorRef<UserAgentSession>,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let result = match actor.ask(HandleSdkClientList {}).await {
Ok(clients) => ProtoSdkClientListResult::Clients(ProtoSdkClientList {
clients: clients
.into_iter()
.map(|(client, metadata)| ProtoSdkClientEntry {
id: client.id,
pubkey: client.public_key,
info: Some(ProtoClientMetadata {
name: metadata.name,
description: metadata.description,
version: metadata.version,
}),
created_at: client.created_at.0.timestamp() as i32,
})
.collect(),
}),
Err(err) => {
warn!(error = ?err, "Failed to list SDK clients");
ProtoSdkClientListResult::Error(ProtoSdkClientError::Internal.into())
}
};
Ok(Some(wrap_sdk_client_response(SdkClientResponsePayload::List(
ProtoSdkClientListResponse {
result: Some(result),
},
))))
}
async fn handle_grant_wallet_access(
actor: &ActorRef<UserAgentSession>,
req: ProtoSdkClientGrantWalletAccess,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let entries: Vec<NewEvmWalletAccess> = req.accesses.into_iter().map(|a| a.convert()).collect();
match actor.ask(HandleGrantEvmWalletAccess { entries }).await {
Ok(()) => {
info!("Successfully granted wallet access");
Ok(None)
}
Err(err) => {
warn!(error = ?err, "Failed to grant wallet access");
Err(Status::internal("Failed to grant wallet access"))
}
}
}
async fn handle_revoke_wallet_access(
actor: &ActorRef<UserAgentSession>,
req: ProtoSdkClientRevokeWalletAccess,
) -> Result<Option<UserAgentResponsePayload>, Status> {
match actor
.ask(HandleRevokeEvmWalletAccess {
entries: req.accesses,
})
.await
{
Ok(()) => {
info!("Successfully revoked wallet access");
Ok(None)
}
Err(err) => {
warn!(error = ?err, "Failed to revoke wallet access");
Err(Status::internal("Failed to revoke wallet access"))
}
}
}
async fn handle_list_wallet_access(
actor: &ActorRef<UserAgentSession>,
) -> Result<Option<UserAgentResponsePayload>, Status> {
match actor.ask(HandleListWalletAccess {}).await {
Ok(accesses) => Ok(Some(wrap_sdk_client_response(
SdkClientResponsePayload::ListWalletAccess(ListWalletAccessResponse {
accesses: accesses.into_iter().map(|a| a.convert()).collect(),
}),
))),
Err(err) => {
warn!(error = ?err, "Failed to list wallet access");
Err(Status::internal("Failed to list wallet access"))
}
}
}

View File

@@ -1,181 +0,0 @@
use arbiter_proto::proto::user_agent::{
user_agent_response::Payload as UserAgentResponsePayload,
vault::{
self as proto_vault,
bootstrap::{
self as proto_bootstrap, BootstrapEncryptedKey as ProtoBootstrapEncryptedKey,
BootstrapResult as ProtoBootstrapResult,
},
request::Payload as VaultRequestPayload,
response::Payload as VaultResponsePayload,
unseal::{
self as proto_unseal, UnsealEncryptedKey as ProtoUnsealEncryptedKey,
UnsealResult as ProtoUnsealResult, UnsealStart,
request::Payload as UnsealRequestPayload,
response::Payload as UnsealResponsePayload,
},
},
};
use arbiter_proto::proto::shared::VaultState as ProtoVaultState;
use kameo::{actor::ActorRef, error::SendError};
use tonic::Status;
use tracing::warn;
use crate::{
actors::{
keyholder::KeyHolderState,
user_agent::{
UserAgentSession,
session::connection::{
BootstrapError, HandleBootstrapEncryptedKey, HandleQueryVaultState,
HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError,
},
},
},
};
fn wrap_vault_response(payload: VaultResponsePayload) -> UserAgentResponsePayload {
UserAgentResponsePayload::Vault(proto_vault::Response {
payload: Some(payload),
})
}
fn wrap_unseal_response(payload: UnsealResponsePayload) -> UserAgentResponsePayload {
wrap_vault_response(VaultResponsePayload::Unseal(proto_unseal::Response {
payload: Some(payload),
}))
}
fn wrap_bootstrap_response(result: ProtoBootstrapResult) -> UserAgentResponsePayload {
wrap_vault_response(VaultResponsePayload::Bootstrap(proto_bootstrap::Response {
result: result.into(),
}))
}
pub(super) async fn dispatch(
actor: &ActorRef<UserAgentSession>,
req: proto_vault::Request,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let Some(payload) = req.payload else {
return Err(Status::invalid_argument("Missing vault request payload"));
};
match payload {
VaultRequestPayload::QueryState(_) => handle_query_vault_state(actor).await,
VaultRequestPayload::Unseal(req) => dispatch_unseal_request(actor, req).await,
VaultRequestPayload::Bootstrap(req) => handle_bootstrap_request(actor, req).await,
}
}
async fn dispatch_unseal_request(
actor: &ActorRef<UserAgentSession>,
req: proto_unseal::Request,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let Some(payload) = req.payload else {
return Err(Status::invalid_argument("Missing unseal request payload"));
};
match payload {
UnsealRequestPayload::Start(req) => handle_unseal_start(actor, req).await,
UnsealRequestPayload::EncryptedKey(req) => handle_unseal_encrypted_key(actor, req).await,
}
}
async fn handle_unseal_start(
actor: &ActorRef<UserAgentSession>,
req: UnsealStart,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let client_pubkey = <[u8; 32]>::try_from(req.client_pubkey)
.map(x25519_dalek::PublicKey::from)
.map_err(|_| Status::invalid_argument("Invalid X25519 public key"))?;
let response = actor
.ask(HandleUnsealRequest { client_pubkey })
.await
.map_err(|err| {
warn!(error = ?err, "Failed to handle unseal start request");
Status::internal("Failed to start unseal flow")
})?;
Ok(Some(wrap_unseal_response(UnsealResponsePayload::Start(
proto_unseal::UnsealStartResponse {
server_pubkey: response.server_pubkey.as_bytes().to_vec(),
},
))))
}
async fn handle_unseal_encrypted_key(
actor: &ActorRef<UserAgentSession>,
req: ProtoUnsealEncryptedKey,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let result = match actor
.ask(HandleUnsealEncryptedKey {
nonce: req.nonce,
ciphertext: req.ciphertext,
associated_data: req.associated_data,
})
.await
{
Ok(()) => ProtoUnsealResult::Success,
Err(SendError::HandlerError(UnsealError::InvalidKey)) => ProtoUnsealResult::InvalidKey,
Err(err) => {
warn!(error = ?err, "Failed to handle unseal request");
return Err(Status::internal("Failed to unseal vault"));
}
};
Ok(Some(wrap_unseal_response(UnsealResponsePayload::Result(
result.into(),
))))
}
async fn handle_bootstrap_request(
actor: &ActorRef<UserAgentSession>,
req: proto_bootstrap::Request,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let encrypted_key = req
.encrypted_key
.ok_or_else(|| Status::invalid_argument("Missing bootstrap encrypted key"))?;
handle_bootstrap_encrypted_key(actor, encrypted_key).await
}
async fn handle_bootstrap_encrypted_key(
actor: &ActorRef<UserAgentSession>,
req: ProtoBootstrapEncryptedKey,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let result = match actor
.ask(HandleBootstrapEncryptedKey {
nonce: req.nonce,
ciphertext: req.ciphertext,
associated_data: req.associated_data,
})
.await
{
Ok(()) => ProtoBootstrapResult::Success,
Err(SendError::HandlerError(BootstrapError::InvalidKey)) => ProtoBootstrapResult::InvalidKey,
Err(SendError::HandlerError(BootstrapError::AlreadyBootstrapped)) => {
ProtoBootstrapResult::AlreadyBootstrapped
}
Err(err) => {
warn!(error = ?err, "Failed to handle bootstrap request");
return Err(Status::internal("Failed to bootstrap vault"));
}
};
Ok(Some(wrap_bootstrap_response(result)))
}
async fn handle_query_vault_state(
actor: &ActorRef<UserAgentSession>,
) -> Result<Option<UserAgentResponsePayload>, Status> {
let state = match actor.ask(HandleQueryVaultState {}).await {
Ok(KeyHolderState::Unbootstrapped) => ProtoVaultState::Unbootstrapped,
Ok(KeyHolderState::Sealed) => ProtoVaultState::Sealed,
Ok(KeyHolderState::Unsealed) => ProtoVaultState::Unsealed,
Err(err) => {
warn!(error = ?err, "Failed to query vault state");
ProtoVaultState::Error
}
};
Ok(Some(wrap_vault_response(VaultResponsePayload::State(
state.into(),
))))
}

View File

@@ -3,6 +3,7 @@ use crate::context::ServerContext;
pub mod actors; pub mod actors;
pub mod context; pub mod context;
pub mod crypto;
pub mod db; pub mod db;
pub mod evm; pub mod evm;
pub mod grpc; pub mod grpc;

View File

@@ -1,5 +1,6 @@
use arbiter_server::{ use arbiter_server::{
actors::keyholder::{Error, KeyHolder}, actors::keyholder::{Error, KeyHolder},
crypto::encryption::v1::{Nonce, ROOT_KEY_TAG},
db::{self, models, schema}, db::{self, models, schema},
safe_cell::{SafeCell, SafeCellHandle as _}, safe_cell::{SafeCell, SafeCellHandle as _},
}; };
@@ -25,16 +26,10 @@ async fn test_bootstrap() {
.unwrap(); .unwrap();
assert_eq!(row.schema_version, 1); assert_eq!(row.schema_version, 1);
assert_eq!( assert_eq!(row.tag, ROOT_KEY_TAG);
row.tag,
arbiter_server::actors::keyholder::encryption::v1::ROOT_KEY_TAG
);
assert!(!row.ciphertext.is_empty()); assert!(!row.ciphertext.is_empty());
assert!(!row.salt.is_empty()); assert!(!row.salt.is_empty());
assert_eq!( assert_eq!(row.data_encryption_nonce, Nonce::default().to_vec());
row.data_encryption_nonce,
arbiter_server::actors::keyholder::encryption::v1::Nonce::default().to_vec()
);
} }
#[tokio::test] #[tokio::test]

View File

@@ -1,7 +1,8 @@
use std::collections::HashSet; use std::collections::HashSet;
use arbiter_server::{ use arbiter_server::{
actors::keyholder::{Error, encryption::v1}, actors::keyholder::Error,
crypto::encryption::v1::Nonce,
db::{self, models, schema}, db::{self, models, schema},
safe_cell::{SafeCell, SafeCellHandle as _}, safe_cell::{SafeCell, SafeCellHandle as _},
}; };
@@ -102,7 +103,7 @@ async fn test_nonce_never_reused() {
assert_eq!(nonces.len(), unique.len(), "all nonces must be unique"); assert_eq!(nonces.len(), unique.len(), "all nonces must be unique");
for (i, row) in rows.iter().enumerate() { for (i, row) in rows.iter().enumerate() {
let mut expected = v1::Nonce::default(); let mut expected = Nonce::default();
for _ in 0..=i { for _ in 0..=i {
expected.increment(); expected.increment();
} }

View File

@@ -3,9 +3,11 @@ use arbiter_server::{
actors::{ actors::{
GlobalActors, GlobalActors,
bootstrap::GetToken, bootstrap::GetToken,
keyholder::Bootstrap,
user_agent::{AuthPublicKey, UserAgentConnection, auth}, user_agent::{AuthPublicKey, UserAgentConnection, auth},
}, },
db::{self, schema}, db::{self, schema},
safe_cell::{SafeCell, SafeCellHandle as _},
}; };
use diesel::{ExpressionMethods as _, QueryDsl, insert_into}; use diesel::{ExpressionMethods as _, QueryDsl, insert_into};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
@@ -166,6 +168,57 @@ pub async fn test_challenge_auth() {
task.await.unwrap().unwrap(); task.await.unwrap().unwrap();
} }
#[tokio::test]
#[test_log::test]
pub async fn test_challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() {
let db = db::create_test_pool().await;
let actors = GlobalActors::spawn(db.clone()).await.unwrap();
actors
.key_holder
.ask(Bootstrap {
seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()),
})
.await
.unwrap();
let new_key = ed25519_dalek::SigningKey::generate(&mut rand::rng());
let pubkey_bytes = new_key.verifying_key().to_bytes().to_vec();
{
let mut conn = db.get().await.unwrap();
insert_into(schema::useragent_client::table)
.values((
schema::useragent_client::public_key.eq(pubkey_bytes.clone()),
schema::useragent_client::key_type.eq(1i32),
schema::useragent_client::pubkey_integrity_tag.eq(Some(vec![0u8; 32])),
))
.execute(&mut conn)
.await
.unwrap();
}
let (server_transport, mut test_transport) = ChannelTransport::new();
let db_for_task = db.clone();
let task = tokio::spawn(async move {
let mut props = UserAgentConnection::new(db_for_task, actors);
auth::authenticate(&mut props, server_transport).await
});
test_transport
.send(auth::Inbound::AuthChallengeRequest {
pubkey: AuthPublicKey::Ed25519(new_key.verifying_key()),
bootstrap_token: None,
})
.await
.unwrap();
assert!(matches!(
task.await.unwrap(),
Err(auth::Error::InvalidChallengeSolution)
));
}
#[tokio::test] #[tokio::test]
#[test_log::test] #[test_log::test]
pub async fn test_challenge_auth_rejects_invalid_signature() { pub async fn test_challenge_auth_rejects_invalid_signature() {
@@ -226,8 +279,12 @@ pub async fn test_challenge_auth_rejects_invalid_signature() {
.await .await
.unwrap(); .unwrap();
let expected_err = task.await.unwrap();
println!("Received expected error: {expected_err:#?}");
assert!(matches!( assert!(matches!(
task.await.unwrap(), expected_err,
Err(auth::Error::InvalidChallengeSolution) Err(auth::Error::InvalidChallengeSolution)
)); ));
} }

View File

@@ -2,14 +2,17 @@ use arbiter_server::{
actors::{ actors::{
GlobalActors, GlobalActors,
keyholder::{Bootstrap, Seal}, keyholder::{Bootstrap, Seal},
user_agent::{UserAgentSession, session::connection::{ user_agent::{
HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError, UserAgentSession,
}}, session::connection::{HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError},
},
}, },
db, db,
safe_cell::{SafeCell, SafeCellHandle as _}, safe_cell::{SafeCell, SafeCellHandle as _},
}; };
use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit}; use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit};
use diesel::{ExpressionMethods as _, QueryDsl as _, insert_into};
use diesel_async::RunQueryDsl;
use kameo::actor::Spawn as _; use kameo::actor::Spawn as _;
use x25519_dalek::{EphemeralSecret, PublicKey}; use x25519_dalek::{EphemeralSecret, PublicKey};
@@ -149,3 +152,42 @@ pub async fn test_unseal_retry_after_invalid_key() {
assert!(matches!(response, Ok(()))); assert!(matches!(response, Ok(())));
} }
} }
#[tokio::test]
#[test_log::test]
pub async fn test_unseal_backfills_missing_pubkey_integrity_tags() {
let seal_key = b"test-seal-key";
let (db, user_agent) = setup_sealed_user_agent(seal_key).await;
{
let mut conn = db.get().await.unwrap();
insert_into(arbiter_server::db::schema::useragent_client::table)
.values((
arbiter_server::db::schema::useragent_client::public_key
.eq(vec![1u8, 2u8, 3u8, 4u8]),
arbiter_server::db::schema::useragent_client::key_type.eq(1i32),
arbiter_server::db::schema::useragent_client::pubkey_integrity_tag
.eq(Option::<Vec<u8>>::None),
))
.execute(&mut conn)
.await
.unwrap();
}
let encrypted_key = client_dh_encrypt(&user_agent, seal_key).await;
let response = user_agent.ask(encrypted_key).await;
assert!(matches!(response, Ok(())));
{
let mut conn = db.get().await.unwrap();
let tags: Vec<Option<Vec<u8>>> = arbiter_server::db::schema::useragent_client::table
.select(arbiter_server::db::schema::useragent_client::pubkey_integrity_tag)
.load(&mut conn)
.await
.unwrap();
assert!(
tags.iter()
.all(|tag| matches!(tag, Some(v) if v.len() == 32))
);
}
}

View File

@@ -1,5 +1,6 @@
import 'package:arbiter/proto/shared/client.pb.dart'; import 'package:arbiter/proto/client.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hooks_riverpod/experimental/mutation.dart';
part 'callout_event.freezed.dart'; part 'callout_event.freezed.dart';

View File

@@ -2,7 +2,7 @@ import 'package:arbiter/features/callouts/active_callout.dart';
import 'package:arbiter/features/callouts/callout_event.dart'; import 'package:arbiter/features/callouts/callout_event.dart';
import 'package:arbiter/features/callouts/types/sdk_connect_approve.dart' import 'package:arbiter/features/callouts/types/sdk_connect_approve.dart'
as connect_approve; as connect_approve;
import 'package:arbiter/proto/shared/client.pb.dart'; import 'package:arbiter/proto/client.pb.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'callout_manager.g.dart'; part 'callout_manager.g.dart';

View File

@@ -1,7 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:arbiter/features/callouts/callout_event.dart'; import 'package:arbiter/features/callouts/callout_event.dart';
import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk;
import 'package:arbiter/proto/user_agent.pb.dart'; import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:arbiter/providers/connection/connection_manager.dart'; import 'package:arbiter/providers/connection/connection_manager.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -15,27 +14,20 @@ Stream<CalloutEvent> connectApproveEvents(Ref ref) async* {
await for (final message in connection.outOfBandMessages) { await for (final message in connection.outOfBandMessages) {
switch (message.whichPayload()) { switch (message.whichPayload()) {
case UserAgentResponse_Payload.sdkClient: case UserAgentResponse_Payload.sdkClientConnectionRequest:
final sdkClientMessage = message.sdkClient; final body = message.sdkClientConnectionRequest;
switch (sdkClientMessage.whichPayload()) { final id = base64Encode(body.pubkey);
case ua_sdk.Response_Payload.connectionRequest: yield CalloutEvent.added(
final body = sdkClientMessage.connectionRequest; id: 'connect_approve:$id',
final id = base64Encode(body.pubkey); data: CalloutData.connectApproval(
yield CalloutEvent.added( pubkey: id,
id: 'connect_approve:$id', clientInfo: body.info,
data: CalloutData.connectApproval( ),
pubkey: id, );
clientInfo: body.info,
),
);
case ua_sdk.Response_Payload.connectionCancel: case UserAgentResponse_Payload.sdkClientConnectionCancel:
final id = base64Encode(sdkClientMessage.connectionCancel.pubkey); final id = base64Encode(message.sdkClientConnectionCancel.pubkey);
yield CalloutEvent.cancelled(id: 'connect_approve:$id'); yield CalloutEvent.cancelled(id: 'connect_approve:$id');
default:
break;
}
default: default:
break; break;
@@ -49,14 +41,11 @@ Future<void> sendDecision(Ref ref, String pubkey, bool approved) async {
final bytes = base64Decode(pubkey); final bytes = base64Decode(pubkey);
final req = UserAgentRequest( final req = UserAgentRequest(sdkClientConnectionResponse: SdkClientConnectionResponse(
sdkClient: ua_sdk.Request( approved: approved,
connectionResponse: ua_sdk.ConnectionResponse( pubkey: bytes
approved: approved, ));
pubkey: bytes,
),
),
);
await connection.tell(req); await connection.tell(req);
} }

View File

@@ -47,4 +47,4 @@ final class ConnectApproveEventsProvider
} }
String _$connectApproveEventsHash() => String _$connectApproveEventsHash() =>
r'abab87cc875a9a4834f836c2c0eba4aa7671d82e'; r'6a0998288afc0836a7c1701a983f64c33d318fd6';

View File

@@ -5,7 +5,6 @@ import 'package:arbiter/features/connection/connection.dart';
import 'package:arbiter/features/connection/server_info_storage.dart'; import 'package:arbiter/features/connection/server_info_storage.dart';
import 'package:arbiter/features/identity/pk_manager.dart'; import 'package:arbiter/features/identity/pk_manager.dart';
import 'package:arbiter/proto/arbiter.pbgrpc.dart'; import 'package:arbiter/proto/arbiter.pbgrpc.dart';
import 'package:arbiter/proto/user_agent/auth.pb.dart' as ua_auth;
import 'package:arbiter/proto/user_agent.pb.dart'; import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:grpc/grpc.dart'; import 'package:grpc/grpc.dart';
import 'package:mtcore/markettakers.dart'; import 'package:mtcore/markettakers.dart';
@@ -13,22 +12,22 @@ import 'package:mtcore/markettakers.dart';
class AuthorizationException implements Exception { class AuthorizationException implements Exception {
const AuthorizationException(this.result); const AuthorizationException(this.result);
final ua_auth.AuthResult result; final AuthResult result;
String get message => switch (result) { String get message => switch (result) {
ua_auth.AuthResult.AUTH_RESULT_INVALID_KEY => AuthResult.AUTH_RESULT_INVALID_KEY =>
'Authentication failed: this device key is not registered on the server.', 'Authentication failed: this device key is not registered on the server.',
ua_auth.AuthResult.AUTH_RESULT_INVALID_SIGNATURE => AuthResult.AUTH_RESULT_INVALID_SIGNATURE =>
'Authentication failed: the server rejected the signature for this device key.', 'Authentication failed: the server rejected the signature for this device key.',
ua_auth.AuthResult.AUTH_RESULT_BOOTSTRAP_REQUIRED => AuthResult.AUTH_RESULT_BOOTSTRAP_REQUIRED =>
'Authentication failed: the server requires bootstrap before this device can connect.', 'Authentication failed: the server requires bootstrap before this device can connect.',
ua_auth.AuthResult.AUTH_RESULT_TOKEN_INVALID => AuthResult.AUTH_RESULT_TOKEN_INVALID =>
'Authentication failed: the bootstrap token is invalid.', 'Authentication failed: the bootstrap token is invalid.',
ua_auth.AuthResult.AUTH_RESULT_INTERNAL => AuthResult.AUTH_RESULT_INTERNAL =>
'Authentication failed: the server hit an internal error.', 'Authentication failed: the server hit an internal error.',
ua_auth.AuthResult.AUTH_RESULT_UNSPECIFIED => AuthResult.AUTH_RESULT_UNSPECIFIED =>
'Authentication failed: the server returned an unspecified auth error.', 'Authentication failed: the server returned an unspecified auth error.',
ua_auth.AuthResult.AUTH_RESULT_SUCCESS => 'Authentication succeeded.', AuthResult.AUTH_RESULT_SUCCESS => 'Authentication succeeded.',
_ => 'Authentication failed: ${result.name}.', _ => 'Authentication failed: ${result.name}.',
}; };
@@ -58,76 +57,56 @@ Future<Connection> connectAndAuthorize(
); );
final pubkey = await key.getPublicKey(); final pubkey = await key.getPublicKey();
final req = ua_auth.AuthChallengeRequest( final req = AuthChallengeRequest(
pubkey: pubkey, pubkey: pubkey,
bootstrapToken: bootstrapToken, bootstrapToken: bootstrapToken,
keyType: switch (key.alg) { keyType: switch (key.alg) {
KeyAlgorithm.rsa => ua_auth.KeyType.KEY_TYPE_RSA, KeyAlgorithm.rsa => KeyType.KEY_TYPE_RSA,
KeyAlgorithm.ecdsa => ua_auth.KeyType.KEY_TYPE_ECDSA_SECP256K1, KeyAlgorithm.ecdsa => KeyType.KEY_TYPE_ECDSA_SECP256K1,
KeyAlgorithm.ed25519 => ua_auth.KeyType.KEY_TYPE_ED25519, KeyAlgorithm.ed25519 => KeyType.KEY_TYPE_ED25519,
}, },
); );
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest(auth: ua_auth.Request(challengeRequest: req)), UserAgentRequest(authChallengeRequest: req),
); );
talker.info( talker.info(
"Sent auth challenge request with pubkey ${base64Encode(pubkey)}", "Sent auth challenge request with pubkey ${base64Encode(pubkey)}",
); );
talker.info('Received response from server, checking auth flow...'); talker.info('Received response from server, checking auth flow...');
if (!response.hasAuth()) { if (response.hasAuthResult()) {
throw ConnectionException( if (response.authResult != AuthResult.AUTH_RESULT_SUCCESS) {
'Expected auth response, got ${response.whichPayload()}', throw AuthorizationException(response.authResult);
);
}
final authResponse = response.auth;
if (authResponse.hasResult()) {
if (authResponse.result != ua_auth.AuthResult.AUTH_RESULT_SUCCESS) {
throw AuthorizationException(authResponse.result);
} }
talker.info('Authentication successful, connection established'); talker.info('Authentication successful, connection established');
return connection; return connection;
} }
if (!authResponse.hasChallenge()) { if (!response.hasAuthChallenge()) {
throw ConnectionException( throw ConnectionException(
'Expected auth challenge response, got ${authResponse.whichPayload()}', 'Expected AuthChallengeResponse, got ${response.whichPayload()}',
); );
} }
final challenge = _formatChallenge(authResponse.challenge, pubkey); final challenge = _formatChallenge(response.authChallenge, pubkey);
talker.info( talker.info(
'Received auth challenge, signing with key ${base64Encode(pubkey)}', 'Received auth challenge, signing with key ${base64Encode(pubkey)}',
); );
final signature = await key.sign(challenge); final signature = await key.sign(challenge);
final solutionResponse = await connection.ask( final solutionResponse = await connection.ask(
UserAgentRequest( UserAgentRequest(authChallengeSolution: AuthChallengeSolution(signature: signature)),
auth: ua_auth.Request(
challengeSolution: ua_auth.AuthChallengeSolution(signature: signature),
),
),
); );
talker.info('Sent auth challenge solution, waiting for server response...'); talker.info('Sent auth challenge solution, waiting for server response...');
if (!solutionResponse.hasAuth()) { if (!solutionResponse.hasAuthResult()) {
throw ConnectionException( throw ConnectionException(
'Expected auth solution response, got ${solutionResponse.whichPayload()}', 'Expected AuthChallengeSolutionResponse, got ${solutionResponse.whichPayload()}',
); );
} }
if (solutionResponse.authResult != AuthResult.AUTH_RESULT_SUCCESS) {
final authSolutionResponse = solutionResponse.auth; throw AuthorizationException(solutionResponse.authResult);
if (!authSolutionResponse.hasResult()) {
throw ConnectionException(
'Expected auth solution result, got ${authSolutionResponse.whichPayload()}',
);
}
if (authSolutionResponse.result != ua_auth.AuthResult.AUTH_RESULT_SUCCESS) {
throw AuthorizationException(authSolutionResponse.result);
} }
talker.info('Authentication successful, connection established'); talker.info('Authentication successful, connection established');
@@ -168,7 +147,7 @@ Future<Connection> _connect(StoredServerInfo serverInfo) async {
return Connection(channel: channel, tx: tx, rx: rx); return Connection(channel: channel, tx: tx, rx: rx);
} }
List<int> _formatChallenge(ua_auth.AuthChallenge challenge, List<int> pubkey) { List<int> _formatChallenge(AuthChallenge challenge, List<int> pubkey) {
final encodedPubkey = base64Encode(pubkey); final encodedPubkey = base64Encode(pubkey);
final payload = "${challenge.nonce}:$encodedPubkey"; final payload = "${challenge.nonce}:$encodedPubkey";
return utf8.encode(payload); return utf8.encode(payload);

View File

@@ -1,27 +1,19 @@
import 'package:arbiter/features/connection/connection.dart'; import 'package:arbiter/features/connection/connection.dart';
import 'package:arbiter/proto/evm.pb.dart'; import 'package:arbiter/proto/evm.pb.dart';
import 'package:arbiter/proto/user_agent/evm.pb.dart' as ua_evm;
import 'package:arbiter/proto/user_agent.pb.dart'; import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart';
Future<List<WalletEntry>> listEvmWallets(Connection connection) async { Future<List<WalletEntry>> listEvmWallets(Connection connection) async {
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest(evm: ua_evm.Request(walletList: Empty())), UserAgentRequest(evmWalletList: Empty()),
); );
if (!response.hasEvm()) { if (!response.hasEvmWalletList()) {
throw Exception( throw Exception(
'Expected EVM response, got ${response.whichPayload()}', 'Expected EVM wallet list response, got ${response.whichPayload()}',
); );
} }
final evmResponse = response.evm; final result = response.evmWalletList;
if (!evmResponse.hasWalletList()) {
throw Exception(
'Expected EVM wallet list response, got ${evmResponse.whichPayload()}',
);
}
final result = evmResponse.walletList;
switch (result.whichResult()) { switch (result.whichResult()) {
case WalletListResponse_Result.wallets: case WalletListResponse_Result.wallets:
return result.wallets.wallets.toList(growable: false); return result.wallets.wallets.toList(growable: false);
@@ -34,22 +26,15 @@ Future<List<WalletEntry>> listEvmWallets(Connection connection) async {
Future<void> createEvmWallet(Connection connection) async { Future<void> createEvmWallet(Connection connection) async {
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest(evm: ua_evm.Request(walletCreate: Empty())), UserAgentRequest(evmWalletCreate: Empty()),
); );
if (!response.hasEvm()) { if (!response.hasEvmWalletCreate()) {
throw Exception( throw Exception(
'Expected EVM response, got ${response.whichPayload()}', 'Expected EVM wallet create response, got ${response.whichPayload()}',
); );
} }
final evmResponse = response.evm; final result = response.evmWalletCreate;
if (!evmResponse.hasWalletCreate()) {
throw Exception(
'Expected EVM wallet create response, got ${evmResponse.whichPayload()}',
);
}
final result = evmResponse.walletCreate;
switch (result.whichResult()) { switch (result.whichResult()) {
case WalletCreateResponse_Result.wallet: case WalletCreateResponse_Result.wallet:
return; return;

View File

@@ -1,28 +1,22 @@
import 'package:arbiter/features/connection/connection.dart'; import 'package:arbiter/features/connection/connection.dart';
import 'package:arbiter/proto/evm.pb.dart'; import 'package:arbiter/proto/evm.pb.dart';
import 'package:arbiter/proto/user_agent/evm.pb.dart' as ua_evm;
import 'package:arbiter/proto/user_agent.pb.dart'; import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:fixnum/fixnum.dart';
import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart';
Future<List<GrantEntry>> listEvmGrants(Connection connection) async { Future<List<GrantEntry>> listEvmGrants(Connection connection) async {
final request = EvmGrantListRequest(); final request = EvmGrantListRequest();
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest(evm: ua_evm.Request(grantList: request)), UserAgentRequest(evmGrantList: request),
); );
if (!response.hasEvm()) { if (!response.hasEvmGrantList()) {
throw Exception( throw Exception(
'Expected EVM response, got ${response.whichPayload()}', 'Expected EVM grant list response, got ${response.whichPayload()}',
); );
} }
final evmResponse = response.evm; final result = response.evmGrantList;
if (!evmResponse.hasGrantList()) {
throw Exception(
'Expected EVM grant list response, got ${evmResponse.whichPayload()}',
);
}
final result = evmResponse.grantList;
switch (result.whichResult()) { switch (result.whichResult()) {
case EvmGrantListResponse_Result.grants: case EvmGrantListResponse_Result.grants:
return result.grants.grants.toList(growable: false); return result.grants.grants.toList(growable: false);
@@ -39,56 +33,36 @@ Future<int> createEvmGrant(
required SpecificGrant specific, required SpecificGrant specific,
}) async { }) async {
final request = UserAgentRequest( final request = UserAgentRequest(
evm: ua_evm.Request( evmGrantCreate: EvmGrantCreateRequest(
grantCreate: EvmGrantCreateRequest( shared: sharedSettings,
shared: sharedSettings, specific: specific,
specific: specific,
),
), ),
); );
final resp = await connection.ask(request); final resp = await connection.ask(request);
if (!resp.hasEvm()) { if (!resp.hasEvmGrantCreate()) {
throw Exception( throw Exception(
'Expected EVM response, got ${resp.whichPayload()}', 'Expected EVM grant create response, got ${resp.whichPayload()}',
); );
} }
final evmResponse = resp.evm; final result = resp.evmGrantCreate;
if (!evmResponse.hasGrantCreate()) {
throw Exception(
'Expected EVM grant create response, got ${evmResponse.whichPayload()}',
);
}
final result = evmResponse.grantCreate;
return result.grantId; return result.grantId;
} }
Future<void> deleteEvmGrant(Connection connection, int grantId) async { Future<void> deleteEvmGrant(Connection connection, int grantId) async {
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest( UserAgentRequest(evmGrantDelete: EvmGrantDeleteRequest(grantId: grantId)),
evm: ua_evm.Request(
grantDelete: EvmGrantDeleteRequest(grantId: grantId),
),
),
); );
if (!response.hasEvm()) { if (!response.hasEvmGrantDelete()) {
throw Exception( throw Exception(
'Expected EVM response, got ${response.whichPayload()}', 'Expected EVM grant delete response, got ${response.whichPayload()}',
); );
} }
final evmResponse = response.evm; final result = response.evmGrantDelete;
if (!evmResponse.hasGrantDelete()) {
throw Exception(
'Expected EVM grant delete response, got ${evmResponse.whichPayload()}',
);
}
final result = evmResponse.grantDelete;
switch (result.whichResult()) { switch (result.whichResult()) {
case EvmGrantDeleteResponse_Result.ok: case EvmGrantDeleteResponse_Result.ok:
return; return;
@@ -99,6 +73,13 @@ Future<void> deleteEvmGrant(Connection connection, int grantId) async {
} }
} }
Timestamp _toTimestamp(DateTime value) {
final utc = value.toUtc();
return Timestamp()
..seconds = Int64(utc.millisecondsSinceEpoch ~/ 1000)
..nanos = (utc.microsecondsSinceEpoch % 1000000) * 1000;
}
String _describeGrantError(EvmError error) { String _describeGrantError(EvmError error) {
return switch (error) { return switch (error) {
EvmError.EVM_ERROR_VAULT_SEALED => EvmError.EVM_ERROR_VAULT_SEALED =>

View File

@@ -1,5 +1,4 @@
import 'package:arbiter/features/connection/connection.dart'; import 'package:arbiter/features/connection/connection.dart';
import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk;
import 'package:arbiter/proto/user_agent.pb.dart'; import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart';
@@ -8,47 +7,31 @@ Future<Set<int>> readClientWalletAccess(
required int clientId, required int clientId,
}) async { }) async {
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest( UserAgentRequest(listWalletAccess: Empty()),
sdkClient: ua_sdk.Request(listWalletAccess: Empty()),
),
); );
if (!response.hasSdkClient()) { if (!response.hasListWalletAccessResponse()) {
throw Exception( throw Exception(
'Expected SDK client response, got ${response.whichPayload()}', 'Expected list wallet access response, got ${response.whichPayload()}',
);
}
final sdkClientResponse = response.sdkClient;
if (!sdkClientResponse.hasListWalletAccess()) {
throw Exception(
'Expected list wallet access response, got ${sdkClientResponse.whichPayload()}',
); );
} }
return { return {
for (final entry in sdkClientResponse.listWalletAccess.accesses) for (final entry in response.listWalletAccessResponse.accesses)
if (entry.access.sdkClientId == clientId) entry.access.walletId, if (entry.access.sdkClientId == clientId) entry.access.walletId,
}; };
} }
Future<List<ua_sdk.WalletAccessEntry>> listAllWalletAccesses( Future<List<SdkClientWalletAccess>> listAllWalletAccesses(
Connection connection, Connection connection,
) async { ) async {
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest( UserAgentRequest(listWalletAccess: Empty()),
sdkClient: ua_sdk.Request(listWalletAccess: Empty()),
),
); );
if (!response.hasSdkClient()) { if (!response.hasListWalletAccessResponse()) {
throw Exception( throw Exception(
'Expected SDK client response, got ${response.whichPayload()}', 'Expected list wallet access response, got ${response.whichPayload()}',
); );
} }
final sdkClientResponse = response.sdkClient; return response.listWalletAccessResponse.accesses.toList(growable: false);
if (!sdkClientResponse.hasListWalletAccess()) {
throw Exception(
'Expected list wallet access response, got ${sdkClientResponse.whichPayload()}',
);
}
return sdkClientResponse.listWalletAccess.accesses.toList(growable: false);
} }
Future<void> writeClientWalletAccess( Future<void> writeClientWalletAccess(
@@ -64,13 +47,11 @@ Future<void> writeClientWalletAccess(
if (toGrant.isNotEmpty) { if (toGrant.isNotEmpty) {
await connection.tell( await connection.tell(
UserAgentRequest( UserAgentRequest(
sdkClient: ua_sdk.Request( grantWalletAccess: SdkClientGrantWalletAccess(
grantWalletAccess: ua_sdk.GrantWalletAccess( accesses: [
accesses: [ for (final walletId in toGrant)
for (final walletId in toGrant) WalletAccess(sdkClientId: clientId, walletId: walletId),
ua_sdk.WalletAccess(sdkClientId: clientId, walletId: walletId), ],
],
),
), ),
), ),
); );
@@ -79,12 +60,11 @@ Future<void> writeClientWalletAccess(
if (toRevoke.isNotEmpty) { if (toRevoke.isNotEmpty) {
await connection.tell( await connection.tell(
UserAgentRequest( UserAgentRequest(
sdkClient: ua_sdk.Request( revokeWalletAccess: SdkClientRevokeWalletAccess(
revokeWalletAccess: ua_sdk.RevokeWalletAccess( accesses: [
accesses: [ for (final walletId in toRevoke)
for (final walletId in toRevoke) walletId, walletId
], ],
),
), ),
), ),
); );

View File

@@ -1,13 +1,10 @@
import 'package:arbiter/features/connection/connection.dart'; import 'package:arbiter/features/connection/connection.dart';
import 'package:arbiter/proto/user_agent/vault/bootstrap.pb.dart' as ua_bootstrap;
import 'package:arbiter/proto/user_agent/vault/unseal.pb.dart' as ua_unseal;
import 'package:arbiter/proto/user_agent/vault/vault.pb.dart' as ua_vault;
import 'package:arbiter/proto/user_agent.pb.dart'; import 'package:arbiter/proto/user_agent.pb.dart';
import 'package:cryptography/cryptography.dart'; import 'package:cryptography/cryptography.dart';
const _vaultKeyAssociatedData = 'arbiter.vault.password'; const _vaultKeyAssociatedData = 'arbiter.vault.password';
Future<ua_bootstrap.BootstrapResult> bootstrapVault( Future<BootstrapResult> bootstrapVault(
Connection connection, Connection connection,
String password, String password,
) async { ) async {
@@ -15,76 +12,39 @@ Future<ua_bootstrap.BootstrapResult> bootstrapVault(
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest( UserAgentRequest(
vault: ua_vault.Request( bootstrapEncryptedKey: BootstrapEncryptedKey(
bootstrap: ua_bootstrap.Request( nonce: encryptedKey.nonce,
encryptedKey: ua_bootstrap.BootstrapEncryptedKey( ciphertext: encryptedKey.ciphertext,
nonce: encryptedKey.nonce, associatedData: encryptedKey.associatedData,
ciphertext: encryptedKey.ciphertext,
associatedData: encryptedKey.associatedData,
),
),
), ),
), ),
); );
if (!response.hasVault()) { if (!response.hasBootstrapResult()) {
throw Exception( throw Exception(
'Expected vault response, got ${response.whichPayload()}', 'Expected bootstrap result, got ${response.whichPayload()}',
); );
} }
final vaultResponse = response.vault; return response.bootstrapResult;
if (!vaultResponse.hasBootstrap()) {
throw Exception(
'Expected bootstrap result, got ${vaultResponse.whichPayload()}',
);
}
final bootstrapResponse = vaultResponse.bootstrap;
if (!bootstrapResponse.hasResult()) {
throw Exception('Expected bootstrap result payload.');
}
return bootstrapResponse.result;
} }
Future<ua_unseal.UnsealResult> unsealVault( Future<UnsealResult> unsealVault(Connection connection, String password) async {
Connection connection,
String password,
) async {
final encryptedKey = await _encryptVaultKeyMaterial(connection, password); final encryptedKey = await _encryptVaultKeyMaterial(connection, password);
final response = await connection.ask( final response = await connection.ask(
UserAgentRequest( UserAgentRequest(
vault: ua_vault.Request( unsealEncryptedKey: UnsealEncryptedKey(
unseal: ua_unseal.Request( nonce: encryptedKey.nonce,
encryptedKey: ua_unseal.UnsealEncryptedKey( ciphertext: encryptedKey.ciphertext,
nonce: encryptedKey.nonce, associatedData: encryptedKey.associatedData,
ciphertext: encryptedKey.ciphertext,
associatedData: encryptedKey.associatedData,
),
),
), ),
), ),
); );
if (!response.hasVault()) { if (!response.hasUnsealResult()) {
throw Exception('Expected vault response, got ${response.whichPayload()}'); throw Exception('Expected unseal result, got ${response.whichPayload()}');
} }
final vaultResponse = response.vault; return response.unsealResult;
if (!vaultResponse.hasUnseal()) {
throw Exception(
'Expected unseal result, got ${vaultResponse.whichPayload()}',
);
}
final unsealResponse = vaultResponse.unseal;
if (!unsealResponse.hasResult()) {
throw Exception(
'Expected unseal result payload, got ${unsealResponse.whichPayload()}',
);
}
return unsealResponse.result;
} }
Future<_EncryptedVaultKey> _encryptVaultKeyMaterial( Future<_EncryptedVaultKey> _encryptVaultKeyMaterial(
@@ -97,36 +57,16 @@ Future<_EncryptedVaultKey> _encryptVaultKeyMaterial(
final clientPublicKey = await clientKeyPair.extractPublicKey(); final clientPublicKey = await clientKeyPair.extractPublicKey();
final handshakeResponse = await connection.ask( final handshakeResponse = await connection.ask(
UserAgentRequest( UserAgentRequest(unsealStart: UnsealStart(clientPubkey: clientPublicKey.bytes)),
vault: ua_vault.Request(
unseal: ua_unseal.Request(
start: ua_unseal.UnsealStart(clientPubkey: clientPublicKey.bytes),
),
),
),
); );
if (!handshakeResponse.hasVault()) { if (!handshakeResponse.hasUnsealStartResponse()) {
throw Exception( throw Exception(
'Expected vault response, got ${handshakeResponse.whichPayload()}', 'Expected unseal handshake response, got ${handshakeResponse.whichPayload()}',
);
}
final vaultResponse = handshakeResponse.vault;
if (!vaultResponse.hasUnseal()) {
throw Exception(
'Expected unseal handshake response, got ${vaultResponse.whichPayload()}',
);
}
final unsealResponse = vaultResponse.unseal;
if (!unsealResponse.hasStart()) {
throw Exception(
'Expected unseal handshake payload, got ${unsealResponse.whichPayload()}',
); );
} }
final serverPublicKey = SimplePublicKey( final serverPublicKey = SimplePublicKey(
unsealResponse.start.serverPubkey, handshakeResponse.unsealStartResponse.serverPubkey,
type: KeyPairType.x25519, type: KeyPairType.x25519,
); );
final sharedSecret = await keyExchange.sharedSecretKey( final sharedSecret = await keyExchange.sharedSecretKey(

View File

@@ -13,26 +13,305 @@
import 'dart:core' as $core; import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb; import 'package:protobuf/protobuf.dart' as $pb;
import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0;
import 'client/auth.pb.dart' as $0; import 'client.pbenum.dart';
import 'client/evm.pb.dart' as $2; import 'evm.pb.dart' as $1;
import 'client/vault.pb.dart' as $1;
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
enum ClientRequest_Payload { auth, vault, evm, notSet } export 'client.pbenum.dart';
class ClientInfo extends $pb.GeneratedMessage {
factory ClientInfo({
$core.String? name,
$core.String? description,
$core.String? version,
}) {
final result = create();
if (name != null) result.name = name;
if (description != null) result.description = description;
if (version != null) result.version = version;
return result;
}
ClientInfo._();
factory ClientInfo.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory ClientInfo.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'ClientInfo',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'name')
..aOS(2, _omitFieldNames ? '' : 'description')
..aOS(3, _omitFieldNames ? '' : 'version')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
ClientInfo clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
ClientInfo copyWith(void Function(ClientInfo) updates) =>
super.copyWith((message) => updates(message as ClientInfo)) as ClientInfo;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ClientInfo create() => ClientInfo._();
@$core.override
ClientInfo createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static ClientInfo getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<ClientInfo>(create);
static ClientInfo? _defaultInstance;
@$pb.TagNumber(1)
$core.String get name => $_getSZ(0);
@$pb.TagNumber(1)
set name($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasName() => $_has(0);
@$pb.TagNumber(1)
void clearName() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get description => $_getSZ(1);
@$pb.TagNumber(2)
set description($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasDescription() => $_has(1);
@$pb.TagNumber(2)
void clearDescription() => $_clearField(2);
@$pb.TagNumber(3)
$core.String get version => $_getSZ(2);
@$pb.TagNumber(3)
set version($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasVersion() => $_has(2);
@$pb.TagNumber(3)
void clearVersion() => $_clearField(3);
}
class AuthChallengeRequest extends $pb.GeneratedMessage {
factory AuthChallengeRequest({
$core.List<$core.int>? pubkey,
ClientInfo? clientInfo,
}) {
final result = create();
if (pubkey != null) result.pubkey = pubkey;
if (clientInfo != null) result.clientInfo = clientInfo;
return result;
}
AuthChallengeRequest._();
factory AuthChallengeRequest.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory AuthChallengeRequest.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'AuthChallengeRequest',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY)
..aOM<ClientInfo>(2, _omitFieldNames ? '' : 'clientInfo',
subBuilder: ClientInfo.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallengeRequest clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallengeRequest copyWith(void Function(AuthChallengeRequest) updates) =>
super.copyWith((message) => updates(message as AuthChallengeRequest))
as AuthChallengeRequest;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AuthChallengeRequest create() => AuthChallengeRequest._();
@$core.override
AuthChallengeRequest createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static AuthChallengeRequest getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<AuthChallengeRequest>(create);
static AuthChallengeRequest? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get pubkey => $_getN(0);
@$pb.TagNumber(1)
set pubkey($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasPubkey() => $_has(0);
@$pb.TagNumber(1)
void clearPubkey() => $_clearField(1);
@$pb.TagNumber(2)
ClientInfo get clientInfo => $_getN(1);
@$pb.TagNumber(2)
set clientInfo(ClientInfo value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasClientInfo() => $_has(1);
@$pb.TagNumber(2)
void clearClientInfo() => $_clearField(2);
@$pb.TagNumber(2)
ClientInfo ensureClientInfo() => $_ensure(1);
}
class AuthChallenge extends $pb.GeneratedMessage {
factory AuthChallenge({
$core.List<$core.int>? pubkey,
$core.int? nonce,
}) {
final result = create();
if (pubkey != null) result.pubkey = pubkey;
if (nonce != null) result.nonce = nonce;
return result;
}
AuthChallenge._();
factory AuthChallenge.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory AuthChallenge.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'AuthChallenge',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY)
..aI(2, _omitFieldNames ? '' : 'nonce')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallenge clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallenge copyWith(void Function(AuthChallenge) updates) =>
super.copyWith((message) => updates(message as AuthChallenge))
as AuthChallenge;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AuthChallenge create() => AuthChallenge._();
@$core.override
AuthChallenge createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static AuthChallenge getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<AuthChallenge>(create);
static AuthChallenge? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get pubkey => $_getN(0);
@$pb.TagNumber(1)
set pubkey($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasPubkey() => $_has(0);
@$pb.TagNumber(1)
void clearPubkey() => $_clearField(1);
@$pb.TagNumber(2)
$core.int get nonce => $_getIZ(1);
@$pb.TagNumber(2)
set nonce($core.int value) => $_setSignedInt32(1, value);
@$pb.TagNumber(2)
$core.bool hasNonce() => $_has(1);
@$pb.TagNumber(2)
void clearNonce() => $_clearField(2);
}
class AuthChallengeSolution extends $pb.GeneratedMessage {
factory AuthChallengeSolution({
$core.List<$core.int>? signature,
}) {
final result = create();
if (signature != null) result.signature = signature;
return result;
}
AuthChallengeSolution._();
factory AuthChallengeSolution.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory AuthChallengeSolution.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'AuthChallengeSolution',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallengeSolution clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallengeSolution copyWith(
void Function(AuthChallengeSolution) updates) =>
super.copyWith((message) => updates(message as AuthChallengeSolution))
as AuthChallengeSolution;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AuthChallengeSolution create() => AuthChallengeSolution._();
@$core.override
AuthChallengeSolution createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static AuthChallengeSolution getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<AuthChallengeSolution>(create);
static AuthChallengeSolution? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get signature => $_getN(0);
@$pb.TagNumber(1)
set signature($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasSignature() => $_has(0);
@$pb.TagNumber(1)
void clearSignature() => $_clearField(1);
}
enum ClientRequest_Payload {
authChallengeRequest,
authChallengeSolution,
queryVaultState,
notSet
}
class ClientRequest extends $pb.GeneratedMessage { class ClientRequest extends $pb.GeneratedMessage {
factory ClientRequest({ factory ClientRequest({
$0.Request? auth, AuthChallengeRequest? authChallengeRequest,
$1.Request? vault, AuthChallengeSolution? authChallengeSolution,
$2.Request? evm, $0.Empty? queryVaultState,
$core.int? requestId, $core.int? requestId,
}) { }) {
final result = create(); final result = create();
if (auth != null) result.auth = auth; if (authChallengeRequest != null)
if (vault != null) result.vault = vault; result.authChallengeRequest = authChallengeRequest;
if (evm != null) result.evm = evm; if (authChallengeSolution != null)
result.authChallengeSolution = authChallengeSolution;
if (queryVaultState != null) result.queryVaultState = queryVaultState;
if (requestId != null) result.requestId = requestId; if (requestId != null) result.requestId = requestId;
return result; return result;
} }
@@ -48,9 +327,9 @@ class ClientRequest extends $pb.GeneratedMessage {
static const $core.Map<$core.int, ClientRequest_Payload> static const $core.Map<$core.int, ClientRequest_Payload>
_ClientRequest_PayloadByTag = { _ClientRequest_PayloadByTag = {
1: ClientRequest_Payload.auth, 1: ClientRequest_Payload.authChallengeRequest,
2: ClientRequest_Payload.vault, 2: ClientRequest_Payload.authChallengeSolution,
3: ClientRequest_Payload.evm, 3: ClientRequest_Payload.queryVaultState,
0: ClientRequest_Payload.notSet 0: ClientRequest_Payload.notSet
}; };
static final $pb.BuilderInfo _i = $pb.BuilderInfo( static final $pb.BuilderInfo _i = $pb.BuilderInfo(
@@ -58,12 +337,14 @@ class ClientRequest extends $pb.GeneratedMessage {
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'), package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'),
createEmptyInstance: create) createEmptyInstance: create)
..oo(0, [1, 2, 3]) ..oo(0, [1, 2, 3])
..aOM<$0.Request>(1, _omitFieldNames ? '' : 'auth', ..aOM<AuthChallengeRequest>(
subBuilder: $0.Request.create) 1, _omitFieldNames ? '' : 'authChallengeRequest',
..aOM<$1.Request>(2, _omitFieldNames ? '' : 'vault', subBuilder: AuthChallengeRequest.create)
subBuilder: $1.Request.create) ..aOM<AuthChallengeSolution>(
..aOM<$2.Request>(3, _omitFieldNames ? '' : 'evm', 2, _omitFieldNames ? '' : 'authChallengeSolution',
subBuilder: $2.Request.create) subBuilder: AuthChallengeSolution.create)
..aOM<$0.Empty>(3, _omitFieldNames ? '' : 'queryVaultState',
subBuilder: $0.Empty.create)
..aI(4, _omitFieldNames ? '' : 'requestId') ..aI(4, _omitFieldNames ? '' : 'requestId')
..hasRequiredFields = false; ..hasRequiredFields = false;
@@ -97,37 +378,38 @@ class ClientRequest extends $pb.GeneratedMessage {
void clearPayload() => $_clearField($_whichOneof(0)); void clearPayload() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1) @$pb.TagNumber(1)
$0.Request get auth => $_getN(0); AuthChallengeRequest get authChallengeRequest => $_getN(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set auth($0.Request value) => $_setField(1, value); set authChallengeRequest(AuthChallengeRequest value) => $_setField(1, value);
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasAuth() => $_has(0); $core.bool hasAuthChallengeRequest() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
void clearAuth() => $_clearField(1); void clearAuthChallengeRequest() => $_clearField(1);
@$pb.TagNumber(1) @$pb.TagNumber(1)
$0.Request ensureAuth() => $_ensure(0); AuthChallengeRequest ensureAuthChallengeRequest() => $_ensure(0);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$1.Request get vault => $_getN(1); AuthChallengeSolution get authChallengeSolution => $_getN(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
set vault($1.Request value) => $_setField(2, value); set authChallengeSolution(AuthChallengeSolution value) =>
$_setField(2, value);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.bool hasVault() => $_has(1); $core.bool hasAuthChallengeSolution() => $_has(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
void clearVault() => $_clearField(2); void clearAuthChallengeSolution() => $_clearField(2);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$1.Request ensureVault() => $_ensure(1); AuthChallengeSolution ensureAuthChallengeSolution() => $_ensure(1);
@$pb.TagNumber(3) @$pb.TagNumber(3)
$2.Request get evm => $_getN(2); $0.Empty get queryVaultState => $_getN(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
set evm($2.Request value) => $_setField(3, value); set queryVaultState($0.Empty value) => $_setField(3, value);
@$pb.TagNumber(3) @$pb.TagNumber(3)
$core.bool hasEvm() => $_has(2); $core.bool hasQueryVaultState() => $_has(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
void clearEvm() => $_clearField(3); void clearQueryVaultState() => $_clearField(3);
@$pb.TagNumber(3) @$pb.TagNumber(3)
$2.Request ensureEvm() => $_ensure(2); $0.Empty ensureQueryVaultState() => $_ensure(2);
@$pb.TagNumber(4) @$pb.TagNumber(4)
$core.int get requestId => $_getIZ(3); $core.int get requestId => $_getIZ(3);
@@ -139,19 +421,32 @@ class ClientRequest extends $pb.GeneratedMessage {
void clearRequestId() => $_clearField(4); void clearRequestId() => $_clearField(4);
} }
enum ClientResponse_Payload { auth, vault, evm, notSet } enum ClientResponse_Payload {
authChallenge,
authResult,
evmSignTransaction,
evmAnalyzeTransaction,
vaultState,
notSet
}
class ClientResponse extends $pb.GeneratedMessage { class ClientResponse extends $pb.GeneratedMessage {
factory ClientResponse({ factory ClientResponse({
$0.Response? auth, AuthChallenge? authChallenge,
$1.Response? vault, AuthResult? authResult,
$2.Response? evm, $1.EvmSignTransactionResponse? evmSignTransaction,
$1.EvmAnalyzeTransactionResponse? evmAnalyzeTransaction,
VaultState? vaultState,
$core.int? requestId, $core.int? requestId,
}) { }) {
final result = create(); final result = create();
if (auth != null) result.auth = auth; if (authChallenge != null) result.authChallenge = authChallenge;
if (vault != null) result.vault = vault; if (authResult != null) result.authResult = authResult;
if (evm != null) result.evm = evm; if (evmSignTransaction != null)
result.evmSignTransaction = evmSignTransaction;
if (evmAnalyzeTransaction != null)
result.evmAnalyzeTransaction = evmAnalyzeTransaction;
if (vaultState != null) result.vaultState = vaultState;
if (requestId != null) result.requestId = requestId; if (requestId != null) result.requestId = requestId;
return result; return result;
} }
@@ -167,22 +462,30 @@ class ClientResponse extends $pb.GeneratedMessage {
static const $core.Map<$core.int, ClientResponse_Payload> static const $core.Map<$core.int, ClientResponse_Payload>
_ClientResponse_PayloadByTag = { _ClientResponse_PayloadByTag = {
1: ClientResponse_Payload.auth, 1: ClientResponse_Payload.authChallenge,
2: ClientResponse_Payload.vault, 2: ClientResponse_Payload.authResult,
3: ClientResponse_Payload.evm, 3: ClientResponse_Payload.evmSignTransaction,
4: ClientResponse_Payload.evmAnalyzeTransaction,
6: ClientResponse_Payload.vaultState,
0: ClientResponse_Payload.notSet 0: ClientResponse_Payload.notSet
}; };
static final $pb.BuilderInfo _i = $pb.BuilderInfo( static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'ClientResponse', _omitMessageNames ? '' : 'ClientResponse',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'), package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'),
createEmptyInstance: create) createEmptyInstance: create)
..oo(0, [1, 2, 3]) ..oo(0, [1, 2, 3, 4, 6])
..aOM<$0.Response>(1, _omitFieldNames ? '' : 'auth', ..aOM<AuthChallenge>(1, _omitFieldNames ? '' : 'authChallenge',
subBuilder: $0.Response.create) subBuilder: AuthChallenge.create)
..aOM<$1.Response>(2, _omitFieldNames ? '' : 'vault', ..aE<AuthResult>(2, _omitFieldNames ? '' : 'authResult',
subBuilder: $1.Response.create) enumValues: AuthResult.values)
..aOM<$2.Response>(3, _omitFieldNames ? '' : 'evm', ..aOM<$1.EvmSignTransactionResponse>(
subBuilder: $2.Response.create) 3, _omitFieldNames ? '' : 'evmSignTransaction',
subBuilder: $1.EvmSignTransactionResponse.create)
..aOM<$1.EvmAnalyzeTransactionResponse>(
4, _omitFieldNames ? '' : 'evmAnalyzeTransaction',
subBuilder: $1.EvmAnalyzeTransactionResponse.create)
..aE<VaultState>(6, _omitFieldNames ? '' : 'vaultState',
enumValues: VaultState.values)
..aI(7, _omitFieldNames ? '' : 'requestId') ..aI(7, _omitFieldNames ? '' : 'requestId')
..hasRequiredFields = false; ..hasRequiredFields = false;
@@ -208,52 +511,76 @@ class ClientResponse extends $pb.GeneratedMessage {
@$pb.TagNumber(1) @$pb.TagNumber(1)
@$pb.TagNumber(2) @$pb.TagNumber(2)
@$pb.TagNumber(3) @$pb.TagNumber(3)
@$pb.TagNumber(4)
@$pb.TagNumber(6)
ClientResponse_Payload whichPayload() => ClientResponse_Payload whichPayload() =>
_ClientResponse_PayloadByTag[$_whichOneof(0)]!; _ClientResponse_PayloadByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1) @$pb.TagNumber(1)
@$pb.TagNumber(2) @$pb.TagNumber(2)
@$pb.TagNumber(3) @$pb.TagNumber(3)
@$pb.TagNumber(4)
@$pb.TagNumber(6)
void clearPayload() => $_clearField($_whichOneof(0)); void clearPayload() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1) @$pb.TagNumber(1)
$0.Response get auth => $_getN(0); AuthChallenge get authChallenge => $_getN(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set auth($0.Response value) => $_setField(1, value); set authChallenge(AuthChallenge value) => $_setField(1, value);
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasAuth() => $_has(0); $core.bool hasAuthChallenge() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
void clearAuth() => $_clearField(1); void clearAuthChallenge() => $_clearField(1);
@$pb.TagNumber(1) @$pb.TagNumber(1)
$0.Response ensureAuth() => $_ensure(0); AuthChallenge ensureAuthChallenge() => $_ensure(0);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$1.Response get vault => $_getN(1); AuthResult get authResult => $_getN(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
set vault($1.Response value) => $_setField(2, value); set authResult(AuthResult value) => $_setField(2, value);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.bool hasVault() => $_has(1); $core.bool hasAuthResult() => $_has(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
void clearVault() => $_clearField(2); void clearAuthResult() => $_clearField(2);
@$pb.TagNumber(2)
$1.Response ensureVault() => $_ensure(1);
@$pb.TagNumber(3) @$pb.TagNumber(3)
$2.Response get evm => $_getN(2); $1.EvmSignTransactionResponse get evmSignTransaction => $_getN(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
set evm($2.Response value) => $_setField(3, value); set evmSignTransaction($1.EvmSignTransactionResponse value) =>
$_setField(3, value);
@$pb.TagNumber(3) @$pb.TagNumber(3)
$core.bool hasEvm() => $_has(2); $core.bool hasEvmSignTransaction() => $_has(2);
@$pb.TagNumber(3) @$pb.TagNumber(3)
void clearEvm() => $_clearField(3); void clearEvmSignTransaction() => $_clearField(3);
@$pb.TagNumber(3) @$pb.TagNumber(3)
$2.Response ensureEvm() => $_ensure(2); $1.EvmSignTransactionResponse ensureEvmSignTransaction() => $_ensure(2);
@$pb.TagNumber(4)
$1.EvmAnalyzeTransactionResponse get evmAnalyzeTransaction => $_getN(3);
@$pb.TagNumber(4)
set evmAnalyzeTransaction($1.EvmAnalyzeTransactionResponse value) =>
$_setField(4, value);
@$pb.TagNumber(4)
$core.bool hasEvmAnalyzeTransaction() => $_has(3);
@$pb.TagNumber(4)
void clearEvmAnalyzeTransaction() => $_clearField(4);
@$pb.TagNumber(4)
$1.EvmAnalyzeTransactionResponse ensureEvmAnalyzeTransaction() => $_ensure(3);
@$pb.TagNumber(6)
VaultState get vaultState => $_getN(4);
@$pb.TagNumber(6)
set vaultState(VaultState value) => $_setField(6, value);
@$pb.TagNumber(6)
$core.bool hasVaultState() => $_has(4);
@$pb.TagNumber(6)
void clearVaultState() => $_clearField(6);
@$pb.TagNumber(7) @$pb.TagNumber(7)
$core.int get requestId => $_getIZ(3); $core.int get requestId => $_getIZ(5);
@$pb.TagNumber(7) @$pb.TagNumber(7)
set requestId($core.int value) => $_setSignedInt32(3, value); set requestId($core.int value) => $_setSignedInt32(5, value);
@$pb.TagNumber(7) @$pb.TagNumber(7)
$core.bool hasRequestId() => $_has(3); $core.bool hasRequestId() => $_has(5);
@$pb.TagNumber(7) @$pb.TagNumber(7)
void clearRequestId() => $_clearField(7); void clearRequestId() => $_clearField(7);
} }

View File

@@ -9,3 +9,72 @@
// ignore_for_file: curly_braces_in_flow_control_structures // ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes // ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports // ignore_for_file: non_constant_identifier_names, prefer_relative_imports
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class AuthResult extends $pb.ProtobufEnum {
static const AuthResult AUTH_RESULT_UNSPECIFIED =
AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED');
static const AuthResult AUTH_RESULT_SUCCESS =
AuthResult._(1, _omitEnumNames ? '' : 'AUTH_RESULT_SUCCESS');
static const AuthResult AUTH_RESULT_INVALID_KEY =
AuthResult._(2, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_KEY');
static const AuthResult AUTH_RESULT_INVALID_SIGNATURE =
AuthResult._(3, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_SIGNATURE');
static const AuthResult AUTH_RESULT_APPROVAL_DENIED =
AuthResult._(4, _omitEnumNames ? '' : 'AUTH_RESULT_APPROVAL_DENIED');
static const AuthResult AUTH_RESULT_NO_USER_AGENTS_ONLINE = AuthResult._(
5, _omitEnumNames ? '' : 'AUTH_RESULT_NO_USER_AGENTS_ONLINE');
static const AuthResult AUTH_RESULT_INTERNAL =
AuthResult._(6, _omitEnumNames ? '' : 'AUTH_RESULT_INTERNAL');
static const $core.List<AuthResult> values = <AuthResult>[
AUTH_RESULT_UNSPECIFIED,
AUTH_RESULT_SUCCESS,
AUTH_RESULT_INVALID_KEY,
AUTH_RESULT_INVALID_SIGNATURE,
AUTH_RESULT_APPROVAL_DENIED,
AUTH_RESULT_NO_USER_AGENTS_ONLINE,
AUTH_RESULT_INTERNAL,
];
static final $core.List<AuthResult?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 6);
static AuthResult? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const AuthResult._(super.value, super.name);
}
class VaultState extends $pb.ProtobufEnum {
static const VaultState VAULT_STATE_UNSPECIFIED =
VaultState._(0, _omitEnumNames ? '' : 'VAULT_STATE_UNSPECIFIED');
static const VaultState VAULT_STATE_UNBOOTSTRAPPED =
VaultState._(1, _omitEnumNames ? '' : 'VAULT_STATE_UNBOOTSTRAPPED');
static const VaultState VAULT_STATE_SEALED =
VaultState._(2, _omitEnumNames ? '' : 'VAULT_STATE_SEALED');
static const VaultState VAULT_STATE_UNSEALED =
VaultState._(3, _omitEnumNames ? '' : 'VAULT_STATE_UNSEALED');
static const VaultState VAULT_STATE_ERROR =
VaultState._(4, _omitEnumNames ? '' : 'VAULT_STATE_ERROR');
static const $core.List<VaultState> values = <VaultState>[
VAULT_STATE_UNSPECIFIED,
VAULT_STATE_UNBOOTSTRAPPED,
VAULT_STATE_SEALED,
VAULT_STATE_UNSEALED,
VAULT_STATE_ERROR,
];
static final $core.List<VaultState?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 4);
static VaultState? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const VaultState._(super.value, super.name);
}
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

View File

@@ -15,37 +15,160 @@ import 'dart:convert' as $convert;
import 'dart:core' as $core; import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data; import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use authResultDescriptor instead')
const AuthResult$json = {
'1': 'AuthResult',
'2': [
{'1': 'AUTH_RESULT_UNSPECIFIED', '2': 0},
{'1': 'AUTH_RESULT_SUCCESS', '2': 1},
{'1': 'AUTH_RESULT_INVALID_KEY', '2': 2},
{'1': 'AUTH_RESULT_INVALID_SIGNATURE', '2': 3},
{'1': 'AUTH_RESULT_APPROVAL_DENIED', '2': 4},
{'1': 'AUTH_RESULT_NO_USER_AGENTS_ONLINE', '2': 5},
{'1': 'AUTH_RESULT_INTERNAL', '2': 6},
],
};
/// Descriptor for `AuthResult`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List authResultDescriptor = $convert.base64Decode(
'CgpBdXRoUmVzdWx0EhsKF0FVVEhfUkVTVUxUX1VOU1BFQ0lGSUVEEAASFwoTQVVUSF9SRVNVTF'
'RfU1VDQ0VTUxABEhsKF0FVVEhfUkVTVUxUX0lOVkFMSURfS0VZEAISIQodQVVUSF9SRVNVTFRf'
'SU5WQUxJRF9TSUdOQVRVUkUQAxIfChtBVVRIX1JFU1VMVF9BUFBST1ZBTF9ERU5JRUQQBBIlCi'
'FBVVRIX1JFU1VMVF9OT19VU0VSX0FHRU5UU19PTkxJTkUQBRIYChRBVVRIX1JFU1VMVF9JTlRF'
'Uk5BTBAG');
@$core.Deprecated('Use vaultStateDescriptor instead')
const VaultState$json = {
'1': 'VaultState',
'2': [
{'1': 'VAULT_STATE_UNSPECIFIED', '2': 0},
{'1': 'VAULT_STATE_UNBOOTSTRAPPED', '2': 1},
{'1': 'VAULT_STATE_SEALED', '2': 2},
{'1': 'VAULT_STATE_UNSEALED', '2': 3},
{'1': 'VAULT_STATE_ERROR', '2': 4},
],
};
/// Descriptor for `VaultState`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List vaultStateDescriptor = $convert.base64Decode(
'CgpWYXVsdFN0YXRlEhsKF1ZBVUxUX1NUQVRFX1VOU1BFQ0lGSUVEEAASHgoaVkFVTFRfU1RBVE'
'VfVU5CT09UU1RSQVBQRUQQARIWChJWQVVMVF9TVEFURV9TRUFMRUQQAhIYChRWQVVMVF9TVEFU'
'RV9VTlNFQUxFRBADEhUKEVZBVUxUX1NUQVRFX0VSUk9SEAQ=');
@$core.Deprecated('Use clientInfoDescriptor instead')
const ClientInfo$json = {
'1': 'ClientInfo',
'2': [
{'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'},
{
'1': 'description',
'3': 2,
'4': 1,
'5': 9,
'9': 0,
'10': 'description',
'17': true
},
{
'1': 'version',
'3': 3,
'4': 1,
'5': 9,
'9': 1,
'10': 'version',
'17': true
},
],
'8': [
{'1': '_description'},
{'1': '_version'},
],
};
/// Descriptor for `ClientInfo`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List clientInfoDescriptor = $convert.base64Decode(
'CgpDbGllbnRJbmZvEhIKBG5hbWUYASABKAlSBG5hbWUSJQoLZGVzY3JpcHRpb24YAiABKAlIAF'
'ILZGVzY3JpcHRpb26IAQESHQoHdmVyc2lvbhgDIAEoCUgBUgd2ZXJzaW9uiAEBQg4KDF9kZXNj'
'cmlwdGlvbkIKCghfdmVyc2lvbg==');
@$core.Deprecated('Use authChallengeRequestDescriptor instead')
const AuthChallengeRequest$json = {
'1': 'AuthChallengeRequest',
'2': [
{'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'},
{
'1': 'client_info',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.client.ClientInfo',
'10': 'clientInfo'
},
],
};
/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode(
'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRI7CgtjbGllbn'
'RfaW5mbxgCIAEoCzIaLmFyYml0ZXIuY2xpZW50LkNsaWVudEluZm9SCmNsaWVudEluZm8=');
@$core.Deprecated('Use authChallengeDescriptor instead')
const AuthChallenge$json = {
'1': 'AuthChallenge',
'2': [
{'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'},
{'1': 'nonce', '3': 2, '4': 1, '5': 5, '10': 'nonce'},
],
};
/// Descriptor for `AuthChallenge`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List authChallengeDescriptor = $convert.base64Decode(
'Cg1BdXRoQ2hhbGxlbmdlEhYKBnB1YmtleRgBIAEoDFIGcHVia2V5EhQKBW5vbmNlGAIgASgFUg'
'Vub25jZQ==');
@$core.Deprecated('Use authChallengeSolutionDescriptor instead')
const AuthChallengeSolution$json = {
'1': 'AuthChallengeSolution',
'2': [
{'1': 'signature', '3': 1, '4': 1, '5': 12, '10': 'signature'},
],
};
/// Descriptor for `AuthChallengeSolution`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List authChallengeSolutionDescriptor = $convert.base64Decode(
'ChVBdXRoQ2hhbGxlbmdlU29sdXRpb24SHAoJc2lnbmF0dXJlGAEgASgMUglzaWduYXR1cmU=');
@$core.Deprecated('Use clientRequestDescriptor instead') @$core.Deprecated('Use clientRequestDescriptor instead')
const ClientRequest$json = { const ClientRequest$json = {
'1': 'ClientRequest', '1': 'ClientRequest',
'2': [ '2': [
{'1': 'request_id', '3': 4, '4': 1, '5': 5, '10': 'requestId'}, {'1': 'request_id', '3': 4, '4': 1, '5': 5, '10': 'requestId'},
{ {
'1': 'auth', '1': 'auth_challenge_request',
'3': 1, '3': 1,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.arbiter.client.auth.Request', '6': '.arbiter.client.AuthChallengeRequest',
'9': 0, '9': 0,
'10': 'auth' '10': 'authChallengeRequest'
}, },
{ {
'1': 'vault', '1': 'auth_challenge_solution',
'3': 2, '3': 2,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.arbiter.client.vault.Request', '6': '.arbiter.client.AuthChallengeSolution',
'9': 0, '9': 0,
'10': 'vault' '10': 'authChallengeSolution'
}, },
{ {
'1': 'evm', '1': 'query_vault_state',
'3': 3, '3': 3,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.arbiter.client.evm.Request', '6': '.google.protobuf.Empty',
'9': 0, '9': 0,
'10': 'evm' '10': 'queryVaultState'
}, },
], ],
'8': [ '8': [
@@ -55,10 +178,12 @@ const ClientRequest$json = {
/// Descriptor for `ClientRequest`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `ClientRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List clientRequestDescriptor = $convert.base64Decode( final $typed_data.Uint8List clientRequestDescriptor = $convert.base64Decode(
'Cg1DbGllbnRSZXF1ZXN0Eh0KCnJlcXVlc3RfaWQYBCABKAVSCXJlcXVlc3RJZBIyCgRhdXRoGA' 'Cg1DbGllbnRSZXF1ZXN0Eh0KCnJlcXVlc3RfaWQYBCABKAVSCXJlcXVlc3RJZBJcChZhdXRoX2'
'EgASgLMhwuYXJiaXRlci5jbGllbnQuYXV0aC5SZXF1ZXN0SABSBGF1dGgSNQoFdmF1bHQYAiAB' 'NoYWxsZW5nZV9yZXF1ZXN0GAEgASgLMiQuYXJiaXRlci5jbGllbnQuQXV0aENoYWxsZW5nZVJl'
'KAsyHS5hcmJpdGVyLmNsaWVudC52YXVsdC5SZXF1ZXN0SABSBXZhdWx0Ei8KA2V2bRgDIAEoCz' 'cXVlc3RIAFIUYXV0aENoYWxsZW5nZVJlcXVlc3QSXwoXYXV0aF9jaGFsbGVuZ2Vfc29sdXRpb2'
'IbLmFyYml0ZXIuY2xpZW50LmV2bS5SZXF1ZXN0SABSA2V2bUIJCgdwYXlsb2Fk'); '4YAiABKAsyJS5hcmJpdGVyLmNsaWVudC5BdXRoQ2hhbGxlbmdlU29sdXRpb25IAFIVYXV0aENo'
'YWxsZW5nZVNvbHV0aW9uEkQKEXF1ZXJ5X3ZhdWx0X3N0YXRlGAMgASgLMhYuZ29vZ2xlLnByb3'
'RvYnVmLkVtcHR5SABSD3F1ZXJ5VmF1bHRTdGF0ZUIJCgdwYXlsb2Fk');
@$core.Deprecated('Use clientResponseDescriptor instead') @$core.Deprecated('Use clientResponseDescriptor instead')
const ClientResponse$json = { const ClientResponse$json = {
@@ -74,31 +199,49 @@ const ClientResponse$json = {
'17': true '17': true
}, },
{ {
'1': 'auth', '1': 'auth_challenge',
'3': 1, '3': 1,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.arbiter.client.auth.Response', '6': '.arbiter.client.AuthChallenge',
'9': 0, '9': 0,
'10': 'auth' '10': 'authChallenge'
}, },
{ {
'1': 'vault', '1': 'auth_result',
'3': 2, '3': 2,
'4': 1, '4': 1,
'5': 11, '5': 14,
'6': '.arbiter.client.vault.Response', '6': '.arbiter.client.AuthResult',
'9': 0, '9': 0,
'10': 'vault' '10': 'authResult'
}, },
{ {
'1': 'evm', '1': 'evm_sign_transaction',
'3': 3, '3': 3,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.arbiter.client.evm.Response', '6': '.arbiter.evm.EvmSignTransactionResponse',
'9': 0, '9': 0,
'10': 'evm' '10': 'evmSignTransaction'
},
{
'1': 'evm_analyze_transaction',
'3': 4,
'4': 1,
'5': 11,
'6': '.arbiter.evm.EvmAnalyzeTransactionResponse',
'9': 0,
'10': 'evmAnalyzeTransaction'
},
{
'1': 'vault_state',
'3': 6,
'4': 1,
'5': 14,
'6': '.arbiter.client.VaultState',
'9': 0,
'10': 'vaultState'
}, },
], ],
'8': [ '8': [
@@ -109,8 +252,12 @@ const ClientResponse$json = {
/// Descriptor for `ClientResponse`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `ClientResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List clientResponseDescriptor = $convert.base64Decode( final $typed_data.Uint8List clientResponseDescriptor = $convert.base64Decode(
'Cg5DbGllbnRSZXNwb25zZRIiCgpyZXF1ZXN0X2lkGAcgASgFSAFSCXJlcXVlc3RJZIgBARIzCg' 'Cg5DbGllbnRSZXNwb25zZRIiCgpyZXF1ZXN0X2lkGAcgASgFSAFSCXJlcXVlc3RJZIgBARJGCg'
'RhdXRoGAEgASgLMh0uYXJiaXRlci5jbGllbnQuYXV0aC5SZXNwb25zZUgAUgRhdXRoEjYKBXZh' '5hdXRoX2NoYWxsZW5nZRgBIAEoCzIdLmFyYml0ZXIuY2xpZW50LkF1dGhDaGFsbGVuZ2VIAFIN'
'dWx0GAIgASgLMh4uYXJiaXRlci5jbGllbnQudmF1bHQuUmVzcG9uc2VIAFIFdmF1bHQSMAoDZX' 'YXV0aENoYWxsZW5nZRI9CgthdXRoX3Jlc3VsdBgCIAEoDjIaLmFyYml0ZXIuY2xpZW50LkF1dG'
'ZtGAMgASgLMhwuYXJiaXRlci5jbGllbnQuZXZtLlJlc3BvbnNlSABSA2V2bUIJCgdwYXlsb2Fk' 'hSZXN1bHRIAFIKYXV0aFJlc3VsdBJbChRldm1fc2lnbl90cmFuc2FjdGlvbhgDIAEoCzInLmFy'
'Qg0KC19yZXF1ZXN0X2lk'); 'Yml0ZXIuZXZtLkV2bVNpZ25UcmFuc2FjdGlvblJlc3BvbnNlSABSEmV2bVNpZ25UcmFuc2FjdG'
'lvbhJkChdldm1fYW5hbHl6ZV90cmFuc2FjdGlvbhgEIAEoCzIqLmFyYml0ZXIuZXZtLkV2bUFu'
'YWx5emVUcmFuc2FjdGlvblJlc3BvbnNlSABSFWV2bUFuYWx5emVUcmFuc2FjdGlvbhI9Cgt2YX'
'VsdF9zdGF0ZRgGIAEoDjIaLmFyYml0ZXIuY2xpZW50LlZhdWx0U3RhdGVIAFIKdmF1bHRTdGF0'
'ZUIJCgdwYXlsb2FkQg0KC19yZXF1ZXN0X2lk');

View File

@@ -1,395 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/auth.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
import '../shared/client.pb.dart' as $0;
import 'auth.pbenum.dart';
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
export 'auth.pbenum.dart';
class AuthChallengeRequest extends $pb.GeneratedMessage {
factory AuthChallengeRequest({
$core.List<$core.int>? pubkey,
$0.ClientInfo? clientInfo,
}) {
final result = create();
if (pubkey != null) result.pubkey = pubkey;
if (clientInfo != null) result.clientInfo = clientInfo;
return result;
}
AuthChallengeRequest._();
factory AuthChallengeRequest.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory AuthChallengeRequest.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'AuthChallengeRequest',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY)
..aOM<$0.ClientInfo>(2, _omitFieldNames ? '' : 'clientInfo',
subBuilder: $0.ClientInfo.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallengeRequest clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallengeRequest copyWith(void Function(AuthChallengeRequest) updates) =>
super.copyWith((message) => updates(message as AuthChallengeRequest))
as AuthChallengeRequest;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AuthChallengeRequest create() => AuthChallengeRequest._();
@$core.override
AuthChallengeRequest createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static AuthChallengeRequest getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<AuthChallengeRequest>(create);
static AuthChallengeRequest? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get pubkey => $_getN(0);
@$pb.TagNumber(1)
set pubkey($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasPubkey() => $_has(0);
@$pb.TagNumber(1)
void clearPubkey() => $_clearField(1);
@$pb.TagNumber(2)
$0.ClientInfo get clientInfo => $_getN(1);
@$pb.TagNumber(2)
set clientInfo($0.ClientInfo value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasClientInfo() => $_has(1);
@$pb.TagNumber(2)
void clearClientInfo() => $_clearField(2);
@$pb.TagNumber(2)
$0.ClientInfo ensureClientInfo() => $_ensure(1);
}
class AuthChallenge extends $pb.GeneratedMessage {
factory AuthChallenge({
$core.List<$core.int>? pubkey,
$core.int? nonce,
}) {
final result = create();
if (pubkey != null) result.pubkey = pubkey;
if (nonce != null) result.nonce = nonce;
return result;
}
AuthChallenge._();
factory AuthChallenge.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory AuthChallenge.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'AuthChallenge',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY)
..aI(2, _omitFieldNames ? '' : 'nonce')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallenge clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallenge copyWith(void Function(AuthChallenge) updates) =>
super.copyWith((message) => updates(message as AuthChallenge))
as AuthChallenge;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AuthChallenge create() => AuthChallenge._();
@$core.override
AuthChallenge createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static AuthChallenge getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<AuthChallenge>(create);
static AuthChallenge? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get pubkey => $_getN(0);
@$pb.TagNumber(1)
set pubkey($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasPubkey() => $_has(0);
@$pb.TagNumber(1)
void clearPubkey() => $_clearField(1);
@$pb.TagNumber(2)
$core.int get nonce => $_getIZ(1);
@$pb.TagNumber(2)
set nonce($core.int value) => $_setSignedInt32(1, value);
@$pb.TagNumber(2)
$core.bool hasNonce() => $_has(1);
@$pb.TagNumber(2)
void clearNonce() => $_clearField(2);
}
class AuthChallengeSolution extends $pb.GeneratedMessage {
factory AuthChallengeSolution({
$core.List<$core.int>? signature,
}) {
final result = create();
if (signature != null) result.signature = signature;
return result;
}
AuthChallengeSolution._();
factory AuthChallengeSolution.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory AuthChallengeSolution.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'AuthChallengeSolution',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallengeSolution clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
AuthChallengeSolution copyWith(
void Function(AuthChallengeSolution) updates) =>
super.copyWith((message) => updates(message as AuthChallengeSolution))
as AuthChallengeSolution;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AuthChallengeSolution create() => AuthChallengeSolution._();
@$core.override
AuthChallengeSolution createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static AuthChallengeSolution getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<AuthChallengeSolution>(create);
static AuthChallengeSolution? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get signature => $_getN(0);
@$pb.TagNumber(1)
set signature($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasSignature() => $_has(0);
@$pb.TagNumber(1)
void clearSignature() => $_clearField(1);
}
enum Request_Payload { challengeRequest, challengeSolution, notSet }
class Request extends $pb.GeneratedMessage {
factory Request({
AuthChallengeRequest? challengeRequest,
AuthChallengeSolution? challengeSolution,
}) {
final result = create();
if (challengeRequest != null) result.challengeRequest = challengeRequest;
if (challengeSolution != null) result.challengeSolution = challengeSolution;
return result;
}
Request._();
factory Request.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory Request.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = {
1: Request_Payload.challengeRequest,
2: Request_Payload.challengeSolution,
0: Request_Payload.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'Request',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'),
createEmptyInstance: create)
..oo(0, [1, 2])
..aOM<AuthChallengeRequest>(1, _omitFieldNames ? '' : 'challengeRequest',
subBuilder: AuthChallengeRequest.create)
..aOM<AuthChallengeSolution>(2, _omitFieldNames ? '' : 'challengeSolution',
subBuilder: AuthChallengeSolution.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Request clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Request copyWith(void Function(Request) updates) =>
super.copyWith((message) => updates(message as Request)) as Request;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Request create() => Request._();
@$core.override
Request createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static Request getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Request>(create);
static Request? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
void clearPayload() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
AuthChallengeRequest get challengeRequest => $_getN(0);
@$pb.TagNumber(1)
set challengeRequest(AuthChallengeRequest value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasChallengeRequest() => $_has(0);
@$pb.TagNumber(1)
void clearChallengeRequest() => $_clearField(1);
@$pb.TagNumber(1)
AuthChallengeRequest ensureChallengeRequest() => $_ensure(0);
@$pb.TagNumber(2)
AuthChallengeSolution get challengeSolution => $_getN(1);
@$pb.TagNumber(2)
set challengeSolution(AuthChallengeSolution value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasChallengeSolution() => $_has(1);
@$pb.TagNumber(2)
void clearChallengeSolution() => $_clearField(2);
@$pb.TagNumber(2)
AuthChallengeSolution ensureChallengeSolution() => $_ensure(1);
}
enum Response_Payload { challenge, result, notSet }
class Response extends $pb.GeneratedMessage {
factory Response({
AuthChallenge? challenge,
AuthResult? result,
}) {
final result$ = create();
if (challenge != null) result$.challenge = challenge;
if (result != null) result$.result = result;
return result$;
}
Response._();
factory Response.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory Response.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = {
1: Response_Payload.challenge,
2: Response_Payload.result,
0: Response_Payload.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'Response',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'),
createEmptyInstance: create)
..oo(0, [1, 2])
..aOM<AuthChallenge>(1, _omitFieldNames ? '' : 'challenge',
subBuilder: AuthChallenge.create)
..aE<AuthResult>(2, _omitFieldNames ? '' : 'result',
enumValues: AuthResult.values)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Response clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Response copyWith(void Function(Response) updates) =>
super.copyWith((message) => updates(message as Response)) as Response;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Response create() => Response._();
@$core.override
Response createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static Response getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Response>(create);
static Response? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
void clearPayload() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
AuthChallenge get challenge => $_getN(0);
@$pb.TagNumber(1)
set challenge(AuthChallenge value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasChallenge() => $_has(0);
@$pb.TagNumber(1)
void clearChallenge() => $_clearField(1);
@$pb.TagNumber(1)
AuthChallenge ensureChallenge() => $_ensure(0);
@$pb.TagNumber(2)
AuthResult get result => $_getN(1);
@$pb.TagNumber(2)
set result(AuthResult value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasResult() => $_has(1);
@$pb.TagNumber(2)
void clearResult() => $_clearField(2);
}
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View File

@@ -1,52 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/auth.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class AuthResult extends $pb.ProtobufEnum {
static const AuthResult AUTH_RESULT_UNSPECIFIED =
AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED');
static const AuthResult AUTH_RESULT_SUCCESS =
AuthResult._(1, _omitEnumNames ? '' : 'AUTH_RESULT_SUCCESS');
static const AuthResult AUTH_RESULT_INVALID_KEY =
AuthResult._(2, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_KEY');
static const AuthResult AUTH_RESULT_INVALID_SIGNATURE =
AuthResult._(3, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_SIGNATURE');
static const AuthResult AUTH_RESULT_APPROVAL_DENIED =
AuthResult._(4, _omitEnumNames ? '' : 'AUTH_RESULT_APPROVAL_DENIED');
static const AuthResult AUTH_RESULT_NO_USER_AGENTS_ONLINE = AuthResult._(
5, _omitEnumNames ? '' : 'AUTH_RESULT_NO_USER_AGENTS_ONLINE');
static const AuthResult AUTH_RESULT_INTERNAL =
AuthResult._(6, _omitEnumNames ? '' : 'AUTH_RESULT_INTERNAL');
static const $core.List<AuthResult> values = <AuthResult>[
AUTH_RESULT_UNSPECIFIED,
AUTH_RESULT_SUCCESS,
AUTH_RESULT_INVALID_KEY,
AUTH_RESULT_INVALID_SIGNATURE,
AUTH_RESULT_APPROVAL_DENIED,
AUTH_RESULT_NO_USER_AGENTS_ONLINE,
AUTH_RESULT_INTERNAL,
];
static final $core.List<AuthResult?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 6);
static AuthResult? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const AuthResult._(super.value, super.name);
}
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

View File

@@ -1,154 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/auth.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
// ignore_for_file: unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use authResultDescriptor instead')
const AuthResult$json = {
'1': 'AuthResult',
'2': [
{'1': 'AUTH_RESULT_UNSPECIFIED', '2': 0},
{'1': 'AUTH_RESULT_SUCCESS', '2': 1},
{'1': 'AUTH_RESULT_INVALID_KEY', '2': 2},
{'1': 'AUTH_RESULT_INVALID_SIGNATURE', '2': 3},
{'1': 'AUTH_RESULT_APPROVAL_DENIED', '2': 4},
{'1': 'AUTH_RESULT_NO_USER_AGENTS_ONLINE', '2': 5},
{'1': 'AUTH_RESULT_INTERNAL', '2': 6},
],
};
/// Descriptor for `AuthResult`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List authResultDescriptor = $convert.base64Decode(
'CgpBdXRoUmVzdWx0EhsKF0FVVEhfUkVTVUxUX1VOU1BFQ0lGSUVEEAASFwoTQVVUSF9SRVNVTF'
'RfU1VDQ0VTUxABEhsKF0FVVEhfUkVTVUxUX0lOVkFMSURfS0VZEAISIQodQVVUSF9SRVNVTFRf'
'SU5WQUxJRF9TSUdOQVRVUkUQAxIfChtBVVRIX1JFU1VMVF9BUFBST1ZBTF9ERU5JRUQQBBIlCi'
'FBVVRIX1JFU1VMVF9OT19VU0VSX0FHRU5UU19PTkxJTkUQBRIYChRBVVRIX1JFU1VMVF9JTlRF'
'Uk5BTBAG');
@$core.Deprecated('Use authChallengeRequestDescriptor instead')
const AuthChallengeRequest$json = {
'1': 'AuthChallengeRequest',
'2': [
{'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'},
{
'1': 'client_info',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.shared.ClientInfo',
'10': 'clientInfo'
},
],
};
/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode(
'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRI7CgtjbGllbn'
'RfaW5mbxgCIAEoCzIaLmFyYml0ZXIuc2hhcmVkLkNsaWVudEluZm9SCmNsaWVudEluZm8=');
@$core.Deprecated('Use authChallengeDescriptor instead')
const AuthChallenge$json = {
'1': 'AuthChallenge',
'2': [
{'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'},
{'1': 'nonce', '3': 2, '4': 1, '5': 5, '10': 'nonce'},
],
};
/// Descriptor for `AuthChallenge`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List authChallengeDescriptor = $convert.base64Decode(
'Cg1BdXRoQ2hhbGxlbmdlEhYKBnB1YmtleRgBIAEoDFIGcHVia2V5EhQKBW5vbmNlGAIgASgFUg'
'Vub25jZQ==');
@$core.Deprecated('Use authChallengeSolutionDescriptor instead')
const AuthChallengeSolution$json = {
'1': 'AuthChallengeSolution',
'2': [
{'1': 'signature', '3': 1, '4': 1, '5': 12, '10': 'signature'},
],
};
/// Descriptor for `AuthChallengeSolution`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List authChallengeSolutionDescriptor = $convert.base64Decode(
'ChVBdXRoQ2hhbGxlbmdlU29sdXRpb24SHAoJc2lnbmF0dXJlGAEgASgMUglzaWduYXR1cmU=');
@$core.Deprecated('Use requestDescriptor instead')
const Request$json = {
'1': 'Request',
'2': [
{
'1': 'challenge_request',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.client.auth.AuthChallengeRequest',
'9': 0,
'10': 'challengeRequest'
},
{
'1': 'challenge_solution',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.client.auth.AuthChallengeSolution',
'9': 0,
'10': 'challengeSolution'
},
],
'8': [
{'1': 'payload'},
],
};
/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List requestDescriptor = $convert.base64Decode(
'CgdSZXF1ZXN0ElgKEWNoYWxsZW5nZV9yZXF1ZXN0GAEgASgLMikuYXJiaXRlci5jbGllbnQuYX'
'V0aC5BdXRoQ2hhbGxlbmdlUmVxdWVzdEgAUhBjaGFsbGVuZ2VSZXF1ZXN0ElsKEmNoYWxsZW5n'
'ZV9zb2x1dGlvbhgCIAEoCzIqLmFyYml0ZXIuY2xpZW50LmF1dGguQXV0aENoYWxsZW5nZVNvbH'
'V0aW9uSABSEWNoYWxsZW5nZVNvbHV0aW9uQgkKB3BheWxvYWQ=');
@$core.Deprecated('Use responseDescriptor instead')
const Response$json = {
'1': 'Response',
'2': [
{
'1': 'challenge',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.client.auth.AuthChallenge',
'9': 0,
'10': 'challenge'
},
{
'1': 'result',
'3': 2,
'4': 1,
'5': 14,
'6': '.arbiter.client.auth.AuthResult',
'9': 0,
'10': 'result'
},
],
'8': [
{'1': 'payload'},
],
};
/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
'CghSZXNwb25zZRJCCgljaGFsbGVuZ2UYASABKAsyIi5hcmJpdGVyLmNsaWVudC5hdXRoLkF1dG'
'hDaGFsbGVuZ2VIAFIJY2hhbGxlbmdlEjkKBnJlc3VsdBgCIAEoDjIfLmFyYml0ZXIuY2xpZW50'
'LmF1dGguQXV0aFJlc3VsdEgAUgZyZXN1bHRCCQoHcGF5bG9hZA==');

View File

@@ -1,208 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/evm.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
import '../evm.pb.dart' as $0;
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
enum Request_Payload { signTransaction, analyzeTransaction, notSet }
class Request extends $pb.GeneratedMessage {
factory Request({
$0.EvmSignTransactionRequest? signTransaction,
$0.EvmAnalyzeTransactionRequest? analyzeTransaction,
}) {
final result = create();
if (signTransaction != null) result.signTransaction = signTransaction;
if (analyzeTransaction != null)
result.analyzeTransaction = analyzeTransaction;
return result;
}
Request._();
factory Request.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory Request.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = {
1: Request_Payload.signTransaction,
2: Request_Payload.analyzeTransaction,
0: Request_Payload.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'Request',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.evm'),
createEmptyInstance: create)
..oo(0, [1, 2])
..aOM<$0.EvmSignTransactionRequest>(
1, _omitFieldNames ? '' : 'signTransaction',
subBuilder: $0.EvmSignTransactionRequest.create)
..aOM<$0.EvmAnalyzeTransactionRequest>(
2, _omitFieldNames ? '' : 'analyzeTransaction',
subBuilder: $0.EvmAnalyzeTransactionRequest.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Request clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Request copyWith(void Function(Request) updates) =>
super.copyWith((message) => updates(message as Request)) as Request;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Request create() => Request._();
@$core.override
Request createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static Request getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Request>(create);
static Request? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
void clearPayload() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
$0.EvmSignTransactionRequest get signTransaction => $_getN(0);
@$pb.TagNumber(1)
set signTransaction($0.EvmSignTransactionRequest value) =>
$_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasSignTransaction() => $_has(0);
@$pb.TagNumber(1)
void clearSignTransaction() => $_clearField(1);
@$pb.TagNumber(1)
$0.EvmSignTransactionRequest ensureSignTransaction() => $_ensure(0);
@$pb.TagNumber(2)
$0.EvmAnalyzeTransactionRequest get analyzeTransaction => $_getN(1);
@$pb.TagNumber(2)
set analyzeTransaction($0.EvmAnalyzeTransactionRequest value) =>
$_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasAnalyzeTransaction() => $_has(1);
@$pb.TagNumber(2)
void clearAnalyzeTransaction() => $_clearField(2);
@$pb.TagNumber(2)
$0.EvmAnalyzeTransactionRequest ensureAnalyzeTransaction() => $_ensure(1);
}
enum Response_Payload { signTransaction, analyzeTransaction, notSet }
class Response extends $pb.GeneratedMessage {
factory Response({
$0.EvmSignTransactionResponse? signTransaction,
$0.EvmAnalyzeTransactionResponse? analyzeTransaction,
}) {
final result = create();
if (signTransaction != null) result.signTransaction = signTransaction;
if (analyzeTransaction != null)
result.analyzeTransaction = analyzeTransaction;
return result;
}
Response._();
factory Response.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory Response.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = {
1: Response_Payload.signTransaction,
2: Response_Payload.analyzeTransaction,
0: Response_Payload.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'Response',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.evm'),
createEmptyInstance: create)
..oo(0, [1, 2])
..aOM<$0.EvmSignTransactionResponse>(
1, _omitFieldNames ? '' : 'signTransaction',
subBuilder: $0.EvmSignTransactionResponse.create)
..aOM<$0.EvmAnalyzeTransactionResponse>(
2, _omitFieldNames ? '' : 'analyzeTransaction',
subBuilder: $0.EvmAnalyzeTransactionResponse.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Response clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Response copyWith(void Function(Response) updates) =>
super.copyWith((message) => updates(message as Response)) as Response;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Response create() => Response._();
@$core.override
Response createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static Response getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Response>(create);
static Response? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
void clearPayload() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
$0.EvmSignTransactionResponse get signTransaction => $_getN(0);
@$pb.TagNumber(1)
set signTransaction($0.EvmSignTransactionResponse value) =>
$_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasSignTransaction() => $_has(0);
@$pb.TagNumber(1)
void clearSignTransaction() => $_clearField(1);
@$pb.TagNumber(1)
$0.EvmSignTransactionResponse ensureSignTransaction() => $_ensure(0);
@$pb.TagNumber(2)
$0.EvmAnalyzeTransactionResponse get analyzeTransaction => $_getN(1);
@$pb.TagNumber(2)
set analyzeTransaction($0.EvmAnalyzeTransactionResponse value) =>
$_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasAnalyzeTransaction() => $_has(1);
@$pb.TagNumber(2)
void clearAnalyzeTransaction() => $_clearField(2);
@$pb.TagNumber(2)
$0.EvmAnalyzeTransactionResponse ensureAnalyzeTransaction() => $_ensure(1);
}
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View File

@@ -1,11 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/evm.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports

View File

@@ -1,86 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/evm.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
// ignore_for_file: unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use requestDescriptor instead')
const Request$json = {
'1': 'Request',
'2': [
{
'1': 'sign_transaction',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.evm.EvmSignTransactionRequest',
'9': 0,
'10': 'signTransaction'
},
{
'1': 'analyze_transaction',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.evm.EvmAnalyzeTransactionRequest',
'9': 0,
'10': 'analyzeTransaction'
},
],
'8': [
{'1': 'payload'},
],
};
/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List requestDescriptor = $convert.base64Decode(
'CgdSZXF1ZXN0ElMKEHNpZ25fdHJhbnNhY3Rpb24YASABKAsyJi5hcmJpdGVyLmV2bS5Fdm1TaW'
'duVHJhbnNhY3Rpb25SZXF1ZXN0SABSD3NpZ25UcmFuc2FjdGlvbhJcChNhbmFseXplX3RyYW5z'
'YWN0aW9uGAIgASgLMikuYXJiaXRlci5ldm0uRXZtQW5hbHl6ZVRyYW5zYWN0aW9uUmVxdWVzdE'
'gAUhJhbmFseXplVHJhbnNhY3Rpb25CCQoHcGF5bG9hZA==');
@$core.Deprecated('Use responseDescriptor instead')
const Response$json = {
'1': 'Response',
'2': [
{
'1': 'sign_transaction',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.evm.EvmSignTransactionResponse',
'9': 0,
'10': 'signTransaction'
},
{
'1': 'analyze_transaction',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.evm.EvmAnalyzeTransactionResponse',
'9': 0,
'10': 'analyzeTransaction'
},
],
'8': [
{'1': 'payload'},
],
};
/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
'CghSZXNwb25zZRJUChBzaWduX3RyYW5zYWN0aW9uGAEgASgLMicuYXJiaXRlci5ldm0uRXZtU2'
'lnblRyYW5zYWN0aW9uUmVzcG9uc2VIAFIPc2lnblRyYW5zYWN0aW9uEl0KE2FuYWx5emVfdHJh'
'bnNhY3Rpb24YAiABKAsyKi5hcmJpdGVyLmV2bS5Fdm1BbmFseXplVHJhbnNhY3Rpb25SZXNwb2'
'5zZUgAUhJhbmFseXplVHJhbnNhY3Rpb25CCQoHcGF5bG9hZA==');

View File

@@ -1,161 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/vault.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0;
import '../shared/vault.pbenum.dart' as $1;
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
enum Request_Payload { queryState, notSet }
class Request extends $pb.GeneratedMessage {
factory Request({
$0.Empty? queryState,
}) {
final result = create();
if (queryState != null) result.queryState = queryState;
return result;
}
Request._();
factory Request.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory Request.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = {
1: Request_Payload.queryState,
0: Request_Payload.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'Request',
package: const $pb.PackageName(
_omitMessageNames ? '' : 'arbiter.client.vault'),
createEmptyInstance: create)
..oo(0, [1])
..aOM<$0.Empty>(1, _omitFieldNames ? '' : 'queryState',
subBuilder: $0.Empty.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Request clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Request copyWith(void Function(Request) updates) =>
super.copyWith((message) => updates(message as Request)) as Request;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Request create() => Request._();
@$core.override
Request createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static Request getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Request>(create);
static Request? _defaultInstance;
@$pb.TagNumber(1)
Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
void clearPayload() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
$0.Empty get queryState => $_getN(0);
@$pb.TagNumber(1)
set queryState($0.Empty value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasQueryState() => $_has(0);
@$pb.TagNumber(1)
void clearQueryState() => $_clearField(1);
@$pb.TagNumber(1)
$0.Empty ensureQueryState() => $_ensure(0);
}
enum Response_Payload { state, notSet }
class Response extends $pb.GeneratedMessage {
factory Response({
$1.VaultState? state,
}) {
final result = create();
if (state != null) result.state = state;
return result;
}
Response._();
factory Response.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory Response.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = {
1: Response_Payload.state,
0: Response_Payload.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'Response',
package: const $pb.PackageName(
_omitMessageNames ? '' : 'arbiter.client.vault'),
createEmptyInstance: create)
..oo(0, [1])
..aE<$1.VaultState>(1, _omitFieldNames ? '' : 'state',
enumValues: $1.VaultState.values)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Response clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
Response copyWith(void Function(Response) updates) =>
super.copyWith((message) => updates(message as Response)) as Response;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Response create() => Response._();
@$core.override
Response createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static Response getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Response>(create);
static Response? _defaultInstance;
@$pb.TagNumber(1)
Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
void clearPayload() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
$1.VaultState get state => $_getN(0);
@$pb.TagNumber(1)
set state($1.VaultState value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasState() => $_has(0);
@$pb.TagNumber(1)
void clearState() => $_clearField(1);
}
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View File

@@ -1,11 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/vault.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports

View File

@@ -1,64 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from client/vault.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
// ignore_for_file: unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use requestDescriptor instead')
const Request$json = {
'1': 'Request',
'2': [
{
'1': 'query_state',
'3': 1,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'queryState'
},
],
'8': [
{'1': 'payload'},
],
};
/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List requestDescriptor = $convert.base64Decode(
'CgdSZXF1ZXN0EjkKC3F1ZXJ5X3N0YXRlGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SA'
'BSCnF1ZXJ5U3RhdGVCCQoHcGF5bG9hZA==');
@$core.Deprecated('Use responseDescriptor instead')
const Response$json = {
'1': 'Response',
'2': [
{
'1': 'state',
'3': 1,
'4': 1,
'5': 14,
'6': '.arbiter.shared.VaultState',
'9': 0,
'10': 'state'
},
],
'8': [
{'1': 'payload'},
],
};
/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
'CghSZXNwb25zZRIyCgVzdGF0ZRgBIAEoDjIaLmFyYml0ZXIuc2hhcmVkLlZhdWx0U3RhdGVIAF'
'IFc3RhdGVCCQoHcGF5bG9hZA==');

View File

@@ -19,7 +19,6 @@ import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart'
as $0; as $0;
import 'evm.pbenum.dart'; import 'evm.pbenum.dart';
import 'shared/evm.pb.dart' as $2;
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
@@ -816,6 +815,825 @@ class SpecificGrant extends $pb.GeneratedMessage {
TokenTransferSettings ensureTokenTransfer() => $_ensure(1); TokenTransferSettings ensureTokenTransfer() => $_ensure(1);
} }
class EtherTransferMeaning extends $pb.GeneratedMessage {
factory EtherTransferMeaning({
$core.List<$core.int>? to,
$core.List<$core.int>? value,
}) {
final result = create();
if (to != null) result.to = to;
if (value != null) result.value = value;
return result;
}
EtherTransferMeaning._();
factory EtherTransferMeaning.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory EtherTransferMeaning.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'EtherTransferMeaning',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'to', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EtherTransferMeaning clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EtherTransferMeaning copyWith(void Function(EtherTransferMeaning) updates) =>
super.copyWith((message) => updates(message as EtherTransferMeaning))
as EtherTransferMeaning;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EtherTransferMeaning create() => EtherTransferMeaning._();
@$core.override
EtherTransferMeaning createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static EtherTransferMeaning getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<EtherTransferMeaning>(create);
static EtherTransferMeaning? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get to => $_getN(0);
@$pb.TagNumber(1)
set to($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasTo() => $_has(0);
@$pb.TagNumber(1)
void clearTo() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get value => $_getN(1);
@$pb.TagNumber(2)
set value($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasValue() => $_has(1);
@$pb.TagNumber(2)
void clearValue() => $_clearField(2);
}
class TokenInfo extends $pb.GeneratedMessage {
factory TokenInfo({
$core.String? symbol,
$core.List<$core.int>? address,
$fixnum.Int64? chainId,
}) {
final result = create();
if (symbol != null) result.symbol = symbol;
if (address != null) result.address = address;
if (chainId != null) result.chainId = chainId;
return result;
}
TokenInfo._();
factory TokenInfo.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory TokenInfo.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'TokenInfo',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'symbol')
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'address', $pb.PbFieldType.OY)
..a<$fixnum.Int64>(3, _omitFieldNames ? '' : 'chainId', $pb.PbFieldType.OU6,
defaultOrMaker: $fixnum.Int64.ZERO)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TokenInfo clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TokenInfo copyWith(void Function(TokenInfo) updates) =>
super.copyWith((message) => updates(message as TokenInfo)) as TokenInfo;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static TokenInfo create() => TokenInfo._();
@$core.override
TokenInfo createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static TokenInfo getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TokenInfo>(create);
static TokenInfo? _defaultInstance;
@$pb.TagNumber(1)
$core.String get symbol => $_getSZ(0);
@$pb.TagNumber(1)
set symbol($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasSymbol() => $_has(0);
@$pb.TagNumber(1)
void clearSymbol() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get address => $_getN(1);
@$pb.TagNumber(2)
set address($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasAddress() => $_has(1);
@$pb.TagNumber(2)
void clearAddress() => $_clearField(2);
@$pb.TagNumber(3)
$fixnum.Int64 get chainId => $_getI64(2);
@$pb.TagNumber(3)
set chainId($fixnum.Int64 value) => $_setInt64(2, value);
@$pb.TagNumber(3)
$core.bool hasChainId() => $_has(2);
@$pb.TagNumber(3)
void clearChainId() => $_clearField(3);
}
/// Mirror of token_transfers::Meaning
class TokenTransferMeaning extends $pb.GeneratedMessage {
factory TokenTransferMeaning({
TokenInfo? token,
$core.List<$core.int>? to,
$core.List<$core.int>? value,
}) {
final result = create();
if (token != null) result.token = token;
if (to != null) result.to = to;
if (value != null) result.value = value;
return result;
}
TokenTransferMeaning._();
factory TokenTransferMeaning.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory TokenTransferMeaning.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'TokenTransferMeaning',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..aOM<TokenInfo>(1, _omitFieldNames ? '' : 'token',
subBuilder: TokenInfo.create)
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'to', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
3, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TokenTransferMeaning clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TokenTransferMeaning copyWith(void Function(TokenTransferMeaning) updates) =>
super.copyWith((message) => updates(message as TokenTransferMeaning))
as TokenTransferMeaning;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static TokenTransferMeaning create() => TokenTransferMeaning._();
@$core.override
TokenTransferMeaning createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static TokenTransferMeaning getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<TokenTransferMeaning>(create);
static TokenTransferMeaning? _defaultInstance;
@$pb.TagNumber(1)
TokenInfo get token => $_getN(0);
@$pb.TagNumber(1)
set token(TokenInfo value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasToken() => $_has(0);
@$pb.TagNumber(1)
void clearToken() => $_clearField(1);
@$pb.TagNumber(1)
TokenInfo ensureToken() => $_ensure(0);
@$pb.TagNumber(2)
$core.List<$core.int> get to => $_getN(1);
@$pb.TagNumber(2)
set to($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasTo() => $_has(1);
@$pb.TagNumber(2)
void clearTo() => $_clearField(2);
@$pb.TagNumber(3)
$core.List<$core.int> get value => $_getN(2);
@$pb.TagNumber(3)
set value($core.List<$core.int> value) => $_setBytes(2, value);
@$pb.TagNumber(3)
$core.bool hasValue() => $_has(2);
@$pb.TagNumber(3)
void clearValue() => $_clearField(3);
}
enum SpecificMeaning_Meaning { etherTransfer, tokenTransfer, notSet }
/// Mirror of policies::SpecificMeaning
class SpecificMeaning extends $pb.GeneratedMessage {
factory SpecificMeaning({
EtherTransferMeaning? etherTransfer,
TokenTransferMeaning? tokenTransfer,
}) {
final result = create();
if (etherTransfer != null) result.etherTransfer = etherTransfer;
if (tokenTransfer != null) result.tokenTransfer = tokenTransfer;
return result;
}
SpecificMeaning._();
factory SpecificMeaning.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory SpecificMeaning.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, SpecificMeaning_Meaning>
_SpecificMeaning_MeaningByTag = {
1: SpecificMeaning_Meaning.etherTransfer,
2: SpecificMeaning_Meaning.tokenTransfer,
0: SpecificMeaning_Meaning.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'SpecificMeaning',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..oo(0, [1, 2])
..aOM<EtherTransferMeaning>(1, _omitFieldNames ? '' : 'etherTransfer',
subBuilder: EtherTransferMeaning.create)
..aOM<TokenTransferMeaning>(2, _omitFieldNames ? '' : 'tokenTransfer',
subBuilder: TokenTransferMeaning.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
SpecificMeaning clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
SpecificMeaning copyWith(void Function(SpecificMeaning) updates) =>
super.copyWith((message) => updates(message as SpecificMeaning))
as SpecificMeaning;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static SpecificMeaning create() => SpecificMeaning._();
@$core.override
SpecificMeaning createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static SpecificMeaning getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<SpecificMeaning>(create);
static SpecificMeaning? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
SpecificMeaning_Meaning whichMeaning() =>
_SpecificMeaning_MeaningByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
void clearMeaning() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
EtherTransferMeaning get etherTransfer => $_getN(0);
@$pb.TagNumber(1)
set etherTransfer(EtherTransferMeaning value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasEtherTransfer() => $_has(0);
@$pb.TagNumber(1)
void clearEtherTransfer() => $_clearField(1);
@$pb.TagNumber(1)
EtherTransferMeaning ensureEtherTransfer() => $_ensure(0);
@$pb.TagNumber(2)
TokenTransferMeaning get tokenTransfer => $_getN(1);
@$pb.TagNumber(2)
set tokenTransfer(TokenTransferMeaning value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasTokenTransfer() => $_has(1);
@$pb.TagNumber(2)
void clearTokenTransfer() => $_clearField(2);
@$pb.TagNumber(2)
TokenTransferMeaning ensureTokenTransfer() => $_ensure(1);
}
/// --- Eval error types ---
class GasLimitExceededViolation extends $pb.GeneratedMessage {
factory GasLimitExceededViolation({
$core.List<$core.int>? maxGasFeePerGas,
$core.List<$core.int>? maxPriorityFeePerGas,
}) {
final result = create();
if (maxGasFeePerGas != null) result.maxGasFeePerGas = maxGasFeePerGas;
if (maxPriorityFeePerGas != null)
result.maxPriorityFeePerGas = maxPriorityFeePerGas;
return result;
}
GasLimitExceededViolation._();
factory GasLimitExceededViolation.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory GasLimitExceededViolation.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'GasLimitExceededViolation',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'maxGasFeePerGas', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'maxPriorityFeePerGas', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
GasLimitExceededViolation clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
GasLimitExceededViolation copyWith(
void Function(GasLimitExceededViolation) updates) =>
super.copyWith((message) => updates(message as GasLimitExceededViolation))
as GasLimitExceededViolation;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static GasLimitExceededViolation create() => GasLimitExceededViolation._();
@$core.override
GasLimitExceededViolation createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static GasLimitExceededViolation getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<GasLimitExceededViolation>(create);
static GasLimitExceededViolation? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get maxGasFeePerGas => $_getN(0);
@$pb.TagNumber(1)
set maxGasFeePerGas($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasMaxGasFeePerGas() => $_has(0);
@$pb.TagNumber(1)
void clearMaxGasFeePerGas() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get maxPriorityFeePerGas => $_getN(1);
@$pb.TagNumber(2)
set maxPriorityFeePerGas($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasMaxPriorityFeePerGas() => $_has(1);
@$pb.TagNumber(2)
void clearMaxPriorityFeePerGas() => $_clearField(2);
}
enum EvalViolation_Kind {
invalidTarget,
gasLimitExceeded,
rateLimitExceeded,
volumetricLimitExceeded,
invalidTime,
invalidTransactionType,
notSet
}
class EvalViolation extends $pb.GeneratedMessage {
factory EvalViolation({
$core.List<$core.int>? invalidTarget,
GasLimitExceededViolation? gasLimitExceeded,
$1.Empty? rateLimitExceeded,
$1.Empty? volumetricLimitExceeded,
$1.Empty? invalidTime,
$1.Empty? invalidTransactionType,
}) {
final result = create();
if (invalidTarget != null) result.invalidTarget = invalidTarget;
if (gasLimitExceeded != null) result.gasLimitExceeded = gasLimitExceeded;
if (rateLimitExceeded != null) result.rateLimitExceeded = rateLimitExceeded;
if (volumetricLimitExceeded != null)
result.volumetricLimitExceeded = volumetricLimitExceeded;
if (invalidTime != null) result.invalidTime = invalidTime;
if (invalidTransactionType != null)
result.invalidTransactionType = invalidTransactionType;
return result;
}
EvalViolation._();
factory EvalViolation.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory EvalViolation.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, EvalViolation_Kind>
_EvalViolation_KindByTag = {
1: EvalViolation_Kind.invalidTarget,
2: EvalViolation_Kind.gasLimitExceeded,
3: EvalViolation_Kind.rateLimitExceeded,
4: EvalViolation_Kind.volumetricLimitExceeded,
5: EvalViolation_Kind.invalidTime,
6: EvalViolation_Kind.invalidTransactionType,
0: EvalViolation_Kind.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'EvalViolation',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..oo(0, [1, 2, 3, 4, 5, 6])
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'invalidTarget', $pb.PbFieldType.OY)
..aOM<GasLimitExceededViolation>(
2, _omitFieldNames ? '' : 'gasLimitExceeded',
subBuilder: GasLimitExceededViolation.create)
..aOM<$1.Empty>(3, _omitFieldNames ? '' : 'rateLimitExceeded',
subBuilder: $1.Empty.create)
..aOM<$1.Empty>(4, _omitFieldNames ? '' : 'volumetricLimitExceeded',
subBuilder: $1.Empty.create)
..aOM<$1.Empty>(5, _omitFieldNames ? '' : 'invalidTime',
subBuilder: $1.Empty.create)
..aOM<$1.Empty>(6, _omitFieldNames ? '' : 'invalidTransactionType',
subBuilder: $1.Empty.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EvalViolation clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EvalViolation copyWith(void Function(EvalViolation) updates) =>
super.copyWith((message) => updates(message as EvalViolation))
as EvalViolation;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EvalViolation create() => EvalViolation._();
@$core.override
EvalViolation createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static EvalViolation getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<EvalViolation>(create);
static EvalViolation? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
@$pb.TagNumber(4)
@$pb.TagNumber(5)
@$pb.TagNumber(6)
EvalViolation_Kind whichKind() => _EvalViolation_KindByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
@$pb.TagNumber(4)
@$pb.TagNumber(5)
@$pb.TagNumber(6)
void clearKind() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
$core.List<$core.int> get invalidTarget => $_getN(0);
@$pb.TagNumber(1)
set invalidTarget($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasInvalidTarget() => $_has(0);
@$pb.TagNumber(1)
void clearInvalidTarget() => $_clearField(1);
@$pb.TagNumber(2)
GasLimitExceededViolation get gasLimitExceeded => $_getN(1);
@$pb.TagNumber(2)
set gasLimitExceeded(GasLimitExceededViolation value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasGasLimitExceeded() => $_has(1);
@$pb.TagNumber(2)
void clearGasLimitExceeded() => $_clearField(2);
@$pb.TagNumber(2)
GasLimitExceededViolation ensureGasLimitExceeded() => $_ensure(1);
@$pb.TagNumber(3)
$1.Empty get rateLimitExceeded => $_getN(2);
@$pb.TagNumber(3)
set rateLimitExceeded($1.Empty value) => $_setField(3, value);
@$pb.TagNumber(3)
$core.bool hasRateLimitExceeded() => $_has(2);
@$pb.TagNumber(3)
void clearRateLimitExceeded() => $_clearField(3);
@$pb.TagNumber(3)
$1.Empty ensureRateLimitExceeded() => $_ensure(2);
@$pb.TagNumber(4)
$1.Empty get volumetricLimitExceeded => $_getN(3);
@$pb.TagNumber(4)
set volumetricLimitExceeded($1.Empty value) => $_setField(4, value);
@$pb.TagNumber(4)
$core.bool hasVolumetricLimitExceeded() => $_has(3);
@$pb.TagNumber(4)
void clearVolumetricLimitExceeded() => $_clearField(4);
@$pb.TagNumber(4)
$1.Empty ensureVolumetricLimitExceeded() => $_ensure(3);
@$pb.TagNumber(5)
$1.Empty get invalidTime => $_getN(4);
@$pb.TagNumber(5)
set invalidTime($1.Empty value) => $_setField(5, value);
@$pb.TagNumber(5)
$core.bool hasInvalidTime() => $_has(4);
@$pb.TagNumber(5)
void clearInvalidTime() => $_clearField(5);
@$pb.TagNumber(5)
$1.Empty ensureInvalidTime() => $_ensure(4);
@$pb.TagNumber(6)
$1.Empty get invalidTransactionType => $_getN(5);
@$pb.TagNumber(6)
set invalidTransactionType($1.Empty value) => $_setField(6, value);
@$pb.TagNumber(6)
$core.bool hasInvalidTransactionType() => $_has(5);
@$pb.TagNumber(6)
void clearInvalidTransactionType() => $_clearField(6);
@$pb.TagNumber(6)
$1.Empty ensureInvalidTransactionType() => $_ensure(5);
}
/// Transaction was classified but no grant covers it
class NoMatchingGrantError extends $pb.GeneratedMessage {
factory NoMatchingGrantError({
SpecificMeaning? meaning,
}) {
final result = create();
if (meaning != null) result.meaning = meaning;
return result;
}
NoMatchingGrantError._();
factory NoMatchingGrantError.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory NoMatchingGrantError.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'NoMatchingGrantError',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..aOM<SpecificMeaning>(1, _omitFieldNames ? '' : 'meaning',
subBuilder: SpecificMeaning.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
NoMatchingGrantError clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
NoMatchingGrantError copyWith(void Function(NoMatchingGrantError) updates) =>
super.copyWith((message) => updates(message as NoMatchingGrantError))
as NoMatchingGrantError;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static NoMatchingGrantError create() => NoMatchingGrantError._();
@$core.override
NoMatchingGrantError createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static NoMatchingGrantError getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<NoMatchingGrantError>(create);
static NoMatchingGrantError? _defaultInstance;
@$pb.TagNumber(1)
SpecificMeaning get meaning => $_getN(0);
@$pb.TagNumber(1)
set meaning(SpecificMeaning value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasMeaning() => $_has(0);
@$pb.TagNumber(1)
void clearMeaning() => $_clearField(1);
@$pb.TagNumber(1)
SpecificMeaning ensureMeaning() => $_ensure(0);
}
/// Transaction was classified and a grant was found, but constraints were violated
class PolicyViolationsError extends $pb.GeneratedMessage {
factory PolicyViolationsError({
SpecificMeaning? meaning,
$core.Iterable<EvalViolation>? violations,
}) {
final result = create();
if (meaning != null) result.meaning = meaning;
if (violations != null) result.violations.addAll(violations);
return result;
}
PolicyViolationsError._();
factory PolicyViolationsError.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PolicyViolationsError.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PolicyViolationsError',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..aOM<SpecificMeaning>(1, _omitFieldNames ? '' : 'meaning',
subBuilder: SpecificMeaning.create)
..pPM<EvalViolation>(2, _omitFieldNames ? '' : 'violations',
subBuilder: EvalViolation.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PolicyViolationsError clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PolicyViolationsError copyWith(
void Function(PolicyViolationsError) updates) =>
super.copyWith((message) => updates(message as PolicyViolationsError))
as PolicyViolationsError;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PolicyViolationsError create() => PolicyViolationsError._();
@$core.override
PolicyViolationsError createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static PolicyViolationsError getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<PolicyViolationsError>(create);
static PolicyViolationsError? _defaultInstance;
@$pb.TagNumber(1)
SpecificMeaning get meaning => $_getN(0);
@$pb.TagNumber(1)
set meaning(SpecificMeaning value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasMeaning() => $_has(0);
@$pb.TagNumber(1)
void clearMeaning() => $_clearField(1);
@$pb.TagNumber(1)
SpecificMeaning ensureMeaning() => $_ensure(0);
@$pb.TagNumber(2)
$pb.PbList<EvalViolation> get violations => $_getList(1);
}
enum TransactionEvalError_Kind {
contractCreationNotSupported,
unsupportedTransactionType,
noMatchingGrant,
policyViolations,
notSet
}
/// top-level error returned when transaction evaluation fails
class TransactionEvalError extends $pb.GeneratedMessage {
factory TransactionEvalError({
$1.Empty? contractCreationNotSupported,
$1.Empty? unsupportedTransactionType,
NoMatchingGrantError? noMatchingGrant,
PolicyViolationsError? policyViolations,
}) {
final result = create();
if (contractCreationNotSupported != null)
result.contractCreationNotSupported = contractCreationNotSupported;
if (unsupportedTransactionType != null)
result.unsupportedTransactionType = unsupportedTransactionType;
if (noMatchingGrant != null) result.noMatchingGrant = noMatchingGrant;
if (policyViolations != null) result.policyViolations = policyViolations;
return result;
}
TransactionEvalError._();
factory TransactionEvalError.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory TransactionEvalError.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, TransactionEvalError_Kind>
_TransactionEvalError_KindByTag = {
1: TransactionEvalError_Kind.contractCreationNotSupported,
2: TransactionEvalError_Kind.unsupportedTransactionType,
3: TransactionEvalError_Kind.noMatchingGrant,
4: TransactionEvalError_Kind.policyViolations,
0: TransactionEvalError_Kind.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'TransactionEvalError',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create)
..oo(0, [1, 2, 3, 4])
..aOM<$1.Empty>(1, _omitFieldNames ? '' : 'contractCreationNotSupported',
subBuilder: $1.Empty.create)
..aOM<$1.Empty>(2, _omitFieldNames ? '' : 'unsupportedTransactionType',
subBuilder: $1.Empty.create)
..aOM<NoMatchingGrantError>(3, _omitFieldNames ? '' : 'noMatchingGrant',
subBuilder: NoMatchingGrantError.create)
..aOM<PolicyViolationsError>(4, _omitFieldNames ? '' : 'policyViolations',
subBuilder: PolicyViolationsError.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TransactionEvalError clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TransactionEvalError copyWith(void Function(TransactionEvalError) updates) =>
super.copyWith((message) => updates(message as TransactionEvalError))
as TransactionEvalError;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static TransactionEvalError create() => TransactionEvalError._();
@$core.override
TransactionEvalError createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static TransactionEvalError getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<TransactionEvalError>(create);
static TransactionEvalError? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
@$pb.TagNumber(4)
TransactionEvalError_Kind whichKind() =>
_TransactionEvalError_KindByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
@$pb.TagNumber(4)
void clearKind() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
$1.Empty get contractCreationNotSupported => $_getN(0);
@$pb.TagNumber(1)
set contractCreationNotSupported($1.Empty value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasContractCreationNotSupported() => $_has(0);
@$pb.TagNumber(1)
void clearContractCreationNotSupported() => $_clearField(1);
@$pb.TagNumber(1)
$1.Empty ensureContractCreationNotSupported() => $_ensure(0);
@$pb.TagNumber(2)
$1.Empty get unsupportedTransactionType => $_getN(1);
@$pb.TagNumber(2)
set unsupportedTransactionType($1.Empty value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasUnsupportedTransactionType() => $_has(1);
@$pb.TagNumber(2)
void clearUnsupportedTransactionType() => $_clearField(2);
@$pb.TagNumber(2)
$1.Empty ensureUnsupportedTransactionType() => $_ensure(1);
@$pb.TagNumber(3)
NoMatchingGrantError get noMatchingGrant => $_getN(2);
@$pb.TagNumber(3)
set noMatchingGrant(NoMatchingGrantError value) => $_setField(3, value);
@$pb.TagNumber(3)
$core.bool hasNoMatchingGrant() => $_has(2);
@$pb.TagNumber(3)
void clearNoMatchingGrant() => $_clearField(3);
@$pb.TagNumber(3)
NoMatchingGrantError ensureNoMatchingGrant() => $_ensure(2);
@$pb.TagNumber(4)
PolicyViolationsError get policyViolations => $_getN(3);
@$pb.TagNumber(4)
set policyViolations(PolicyViolationsError value) => $_setField(4, value);
@$pb.TagNumber(4)
$core.bool hasPolicyViolations() => $_has(3);
@$pb.TagNumber(4)
void clearPolicyViolations() => $_clearField(4);
@$pb.TagNumber(4)
PolicyViolationsError ensurePolicyViolations() => $_ensure(3);
}
/// --- UserAgent grant management --- /// --- UserAgent grant management ---
class EvmGrantCreateRequest extends $pb.GeneratedMessage { class EvmGrantCreateRequest extends $pb.GeneratedMessage {
factory EvmGrantCreateRequest({ factory EvmGrantCreateRequest({
@@ -1479,7 +2297,7 @@ enum EvmSignTransactionResponse_Result { signature, evalError, error, notSet }
class EvmSignTransactionResponse extends $pb.GeneratedMessage { class EvmSignTransactionResponse extends $pb.GeneratedMessage {
factory EvmSignTransactionResponse({ factory EvmSignTransactionResponse({
$core.List<$core.int>? signature, $core.List<$core.int>? signature,
$2.TransactionEvalError? evalError, TransactionEvalError? evalError,
EvmError? error, EvmError? error,
}) { }) {
final result = create(); final result = create();
@@ -1512,8 +2330,8 @@ class EvmSignTransactionResponse extends $pb.GeneratedMessage {
..oo(0, [1, 2, 3]) ..oo(0, [1, 2, 3])
..a<$core.List<$core.int>>( ..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY) 1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY)
..aOM<$2.TransactionEvalError>(2, _omitFieldNames ? '' : 'evalError', ..aOM<TransactionEvalError>(2, _omitFieldNames ? '' : 'evalError',
subBuilder: $2.TransactionEvalError.create) subBuilder: TransactionEvalError.create)
..aE<EvmError>(3, _omitFieldNames ? '' : 'error', ..aE<EvmError>(3, _omitFieldNames ? '' : 'error',
enumValues: EvmError.values) enumValues: EvmError.values)
..hasRequiredFields = false; ..hasRequiredFields = false;
@@ -1559,15 +2377,15 @@ class EvmSignTransactionResponse extends $pb.GeneratedMessage {
void clearSignature() => $_clearField(1); void clearSignature() => $_clearField(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$2.TransactionEvalError get evalError => $_getN(1); TransactionEvalError get evalError => $_getN(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
set evalError($2.TransactionEvalError value) => $_setField(2, value); set evalError(TransactionEvalError value) => $_setField(2, value);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.bool hasEvalError() => $_has(1); $core.bool hasEvalError() => $_has(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
void clearEvalError() => $_clearField(2); void clearEvalError() => $_clearField(2);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$2.TransactionEvalError ensureEvalError() => $_ensure(1); TransactionEvalError ensureEvalError() => $_ensure(1);
@$pb.TagNumber(3) @$pb.TagNumber(3)
EvmError get error => $_getN(2); EvmError get error => $_getN(2);
@@ -1654,8 +2472,8 @@ enum EvmAnalyzeTransactionResponse_Result { meaning, evalError, error, notSet }
class EvmAnalyzeTransactionResponse extends $pb.GeneratedMessage { class EvmAnalyzeTransactionResponse extends $pb.GeneratedMessage {
factory EvmAnalyzeTransactionResponse({ factory EvmAnalyzeTransactionResponse({
$2.SpecificMeaning? meaning, SpecificMeaning? meaning,
$2.TransactionEvalError? evalError, TransactionEvalError? evalError,
EvmError? error, EvmError? error,
}) { }) {
final result = create(); final result = create();
@@ -1686,10 +2504,10 @@ class EvmAnalyzeTransactionResponse extends $pb.GeneratedMessage {
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'),
createEmptyInstance: create) createEmptyInstance: create)
..oo(0, [1, 2, 3]) ..oo(0, [1, 2, 3])
..aOM<$2.SpecificMeaning>(1, _omitFieldNames ? '' : 'meaning', ..aOM<SpecificMeaning>(1, _omitFieldNames ? '' : 'meaning',
subBuilder: $2.SpecificMeaning.create) subBuilder: SpecificMeaning.create)
..aOM<$2.TransactionEvalError>(2, _omitFieldNames ? '' : 'evalError', ..aOM<TransactionEvalError>(2, _omitFieldNames ? '' : 'evalError',
subBuilder: $2.TransactionEvalError.create) subBuilder: TransactionEvalError.create)
..aE<EvmError>(3, _omitFieldNames ? '' : 'error', ..aE<EvmError>(3, _omitFieldNames ? '' : 'error',
enumValues: EvmError.values) enumValues: EvmError.values)
..hasRequiredFields = false; ..hasRequiredFields = false;
@@ -1727,26 +2545,26 @@ class EvmAnalyzeTransactionResponse extends $pb.GeneratedMessage {
void clearResult() => $_clearField($_whichOneof(0)); void clearResult() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1) @$pb.TagNumber(1)
$2.SpecificMeaning get meaning => $_getN(0); SpecificMeaning get meaning => $_getN(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set meaning($2.SpecificMeaning value) => $_setField(1, value); set meaning(SpecificMeaning value) => $_setField(1, value);
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasMeaning() => $_has(0); $core.bool hasMeaning() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
void clearMeaning() => $_clearField(1); void clearMeaning() => $_clearField(1);
@$pb.TagNumber(1) @$pb.TagNumber(1)
$2.SpecificMeaning ensureMeaning() => $_ensure(0); SpecificMeaning ensureMeaning() => $_ensure(0);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$2.TransactionEvalError get evalError => $_getN(1); TransactionEvalError get evalError => $_getN(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
set evalError($2.TransactionEvalError value) => $_setField(2, value); set evalError(TransactionEvalError value) => $_setField(2, value);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.bool hasEvalError() => $_has(1); $core.bool hasEvalError() => $_has(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
void clearEvalError() => $_clearField(2); void clearEvalError() => $_clearField(2);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$2.TransactionEvalError ensureEvalError() => $_ensure(1); TransactionEvalError ensureEvalError() => $_ensure(1);
@$pb.TagNumber(3) @$pb.TagNumber(3)
EvmError get error => $_getN(2); EvmError get error => $_getN(2);

View File

@@ -327,6 +327,308 @@ final $typed_data.Uint8List specificGrantDescriptor = $convert.base64Decode(
'AiABKAsyIi5hcmJpdGVyLmV2bS5Ub2tlblRyYW5zZmVyU2V0dGluZ3NIAFINdG9rZW5UcmFuc2' 'AiABKAsyIi5hcmJpdGVyLmV2bS5Ub2tlblRyYW5zZmVyU2V0dGluZ3NIAFINdG9rZW5UcmFuc2'
'ZlckIHCgVncmFudA=='); 'ZlckIHCgVncmFudA==');
@$core.Deprecated('Use etherTransferMeaningDescriptor instead')
const EtherTransferMeaning$json = {
'1': 'EtherTransferMeaning',
'2': [
{'1': 'to', '3': 1, '4': 1, '5': 12, '10': 'to'},
{'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'},
],
};
/// Descriptor for `EtherTransferMeaning`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List etherTransferMeaningDescriptor = $convert.base64Decode(
'ChRFdGhlclRyYW5zZmVyTWVhbmluZxIOCgJ0bxgBIAEoDFICdG8SFAoFdmFsdWUYAiABKAxSBX'
'ZhbHVl');
@$core.Deprecated('Use tokenInfoDescriptor instead')
const TokenInfo$json = {
'1': 'TokenInfo',
'2': [
{'1': 'symbol', '3': 1, '4': 1, '5': 9, '10': 'symbol'},
{'1': 'address', '3': 2, '4': 1, '5': 12, '10': 'address'},
{'1': 'chain_id', '3': 3, '4': 1, '5': 4, '10': 'chainId'},
],
};
/// Descriptor for `TokenInfo`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List tokenInfoDescriptor = $convert.base64Decode(
'CglUb2tlbkluZm8SFgoGc3ltYm9sGAEgASgJUgZzeW1ib2wSGAoHYWRkcmVzcxgCIAEoDFIHYW'
'RkcmVzcxIZCghjaGFpbl9pZBgDIAEoBFIHY2hhaW5JZA==');
@$core.Deprecated('Use tokenTransferMeaningDescriptor instead')
const TokenTransferMeaning$json = {
'1': 'TokenTransferMeaning',
'2': [
{
'1': 'token',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.evm.TokenInfo',
'10': 'token'
},
{'1': 'to', '3': 2, '4': 1, '5': 12, '10': 'to'},
{'1': 'value', '3': 3, '4': 1, '5': 12, '10': 'value'},
],
};
/// Descriptor for `TokenTransferMeaning`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List tokenTransferMeaningDescriptor = $convert.base64Decode(
'ChRUb2tlblRyYW5zZmVyTWVhbmluZxIsCgV0b2tlbhgBIAEoCzIWLmFyYml0ZXIuZXZtLlRva2'
'VuSW5mb1IFdG9rZW4SDgoCdG8YAiABKAxSAnRvEhQKBXZhbHVlGAMgASgMUgV2YWx1ZQ==');
@$core.Deprecated('Use specificMeaningDescriptor instead')
const SpecificMeaning$json = {
'1': 'SpecificMeaning',
'2': [
{
'1': 'ether_transfer',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.evm.EtherTransferMeaning',
'9': 0,
'10': 'etherTransfer'
},
{
'1': 'token_transfer',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.evm.TokenTransferMeaning',
'9': 0,
'10': 'tokenTransfer'
},
],
'8': [
{'1': 'meaning'},
],
};
/// Descriptor for `SpecificMeaning`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List specificMeaningDescriptor = $convert.base64Decode(
'Cg9TcGVjaWZpY01lYW5pbmcSSgoOZXRoZXJfdHJhbnNmZXIYASABKAsyIS5hcmJpdGVyLmV2bS'
'5FdGhlclRyYW5zZmVyTWVhbmluZ0gAUg1ldGhlclRyYW5zZmVyEkoKDnRva2VuX3RyYW5zZmVy'
'GAIgASgLMiEuYXJiaXRlci5ldm0uVG9rZW5UcmFuc2Zlck1lYW5pbmdIAFINdG9rZW5UcmFuc2'
'ZlckIJCgdtZWFuaW5n');
@$core.Deprecated('Use gasLimitExceededViolationDescriptor instead')
const GasLimitExceededViolation$json = {
'1': 'GasLimitExceededViolation',
'2': [
{
'1': 'max_gas_fee_per_gas',
'3': 1,
'4': 1,
'5': 12,
'9': 0,
'10': 'maxGasFeePerGas',
'17': true
},
{
'1': 'max_priority_fee_per_gas',
'3': 2,
'4': 1,
'5': 12,
'9': 1,
'10': 'maxPriorityFeePerGas',
'17': true
},
],
'8': [
{'1': '_max_gas_fee_per_gas'},
{'1': '_max_priority_fee_per_gas'},
],
};
/// Descriptor for `GasLimitExceededViolation`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List gasLimitExceededViolationDescriptor = $convert.base64Decode(
'ChlHYXNMaW1pdEV4Y2VlZGVkVmlvbGF0aW9uEjEKE21heF9nYXNfZmVlX3Blcl9nYXMYASABKA'
'xIAFIPbWF4R2FzRmVlUGVyR2FziAEBEjsKGG1heF9wcmlvcml0eV9mZWVfcGVyX2dhcxgCIAEo'
'DEgBUhRtYXhQcmlvcml0eUZlZVBlckdhc4gBAUIWChRfbWF4X2dhc19mZWVfcGVyX2dhc0IbCh'
'lfbWF4X3ByaW9yaXR5X2ZlZV9wZXJfZ2Fz');
@$core.Deprecated('Use evalViolationDescriptor instead')
const EvalViolation$json = {
'1': 'EvalViolation',
'2': [
{
'1': 'invalid_target',
'3': 1,
'4': 1,
'5': 12,
'9': 0,
'10': 'invalidTarget'
},
{
'1': 'gas_limit_exceeded',
'3': 2,
'4': 1,
'5': 11,
'6': '.arbiter.evm.GasLimitExceededViolation',
'9': 0,
'10': 'gasLimitExceeded'
},
{
'1': 'rate_limit_exceeded',
'3': 3,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'rateLimitExceeded'
},
{
'1': 'volumetric_limit_exceeded',
'3': 4,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'volumetricLimitExceeded'
},
{
'1': 'invalid_time',
'3': 5,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'invalidTime'
},
{
'1': 'invalid_transaction_type',
'3': 6,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'invalidTransactionType'
},
],
'8': [
{'1': 'kind'},
],
};
/// Descriptor for `EvalViolation`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List evalViolationDescriptor = $convert.base64Decode(
'Cg1FdmFsVmlvbGF0aW9uEicKDmludmFsaWRfdGFyZ2V0GAEgASgMSABSDWludmFsaWRUYXJnZX'
'QSVgoSZ2FzX2xpbWl0X2V4Y2VlZGVkGAIgASgLMiYuYXJiaXRlci5ldm0uR2FzTGltaXRFeGNl'
'ZWRlZFZpb2xhdGlvbkgAUhBnYXNMaW1pdEV4Y2VlZGVkEkgKE3JhdGVfbGltaXRfZXhjZWVkZW'
'QYAyABKAsyFi5nb29nbGUucHJvdG9idWYuRW1wdHlIAFIRcmF0ZUxpbWl0RXhjZWVkZWQSVAoZ'
'dm9sdW1ldHJpY19saW1pdF9leGNlZWRlZBgEIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eU'
'gAUhd2b2x1bWV0cmljTGltaXRFeGNlZWRlZBI7CgxpbnZhbGlkX3RpbWUYBSABKAsyFi5nb29n'
'bGUucHJvdG9idWYuRW1wdHlIAFILaW52YWxpZFRpbWUSUgoYaW52YWxpZF90cmFuc2FjdGlvbl'
'90eXBlGAYgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSFmludmFsaWRUcmFuc2FjdGlv'
'blR5cGVCBgoEa2luZA==');
@$core.Deprecated('Use noMatchingGrantErrorDescriptor instead')
const NoMatchingGrantError$json = {
'1': 'NoMatchingGrantError',
'2': [
{
'1': 'meaning',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.evm.SpecificMeaning',
'10': 'meaning'
},
],
};
/// Descriptor for `NoMatchingGrantError`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List noMatchingGrantErrorDescriptor = $convert.base64Decode(
'ChROb01hdGNoaW5nR3JhbnRFcnJvchI2CgdtZWFuaW5nGAEgASgLMhwuYXJiaXRlci5ldm0uU3'
'BlY2lmaWNNZWFuaW5nUgdtZWFuaW5n');
@$core.Deprecated('Use policyViolationsErrorDescriptor instead')
const PolicyViolationsError$json = {
'1': 'PolicyViolationsError',
'2': [
{
'1': 'meaning',
'3': 1,
'4': 1,
'5': 11,
'6': '.arbiter.evm.SpecificMeaning',
'10': 'meaning'
},
{
'1': 'violations',
'3': 2,
'4': 3,
'5': 11,
'6': '.arbiter.evm.EvalViolation',
'10': 'violations'
},
],
};
/// Descriptor for `PolicyViolationsError`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List policyViolationsErrorDescriptor = $convert.base64Decode(
'ChVQb2xpY3lWaW9sYXRpb25zRXJyb3ISNgoHbWVhbmluZxgBIAEoCzIcLmFyYml0ZXIuZXZtLl'
'NwZWNpZmljTWVhbmluZ1IHbWVhbmluZxI6Cgp2aW9sYXRpb25zGAIgAygLMhouYXJiaXRlci5l'
'dm0uRXZhbFZpb2xhdGlvblIKdmlvbGF0aW9ucw==');
@$core.Deprecated('Use transactionEvalErrorDescriptor instead')
const TransactionEvalError$json = {
'1': 'TransactionEvalError',
'2': [
{
'1': 'contract_creation_not_supported',
'3': 1,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'contractCreationNotSupported'
},
{
'1': 'unsupported_transaction_type',
'3': 2,
'4': 1,
'5': 11,
'6': '.google.protobuf.Empty',
'9': 0,
'10': 'unsupportedTransactionType'
},
{
'1': 'no_matching_grant',
'3': 3,
'4': 1,
'5': 11,
'6': '.arbiter.evm.NoMatchingGrantError',
'9': 0,
'10': 'noMatchingGrant'
},
{
'1': 'policy_violations',
'3': 4,
'4': 1,
'5': 11,
'6': '.arbiter.evm.PolicyViolationsError',
'9': 0,
'10': 'policyViolations'
},
],
'8': [
{'1': 'kind'},
],
};
/// Descriptor for `TransactionEvalError`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List transactionEvalErrorDescriptor = $convert.base64Decode(
'ChRUcmFuc2FjdGlvbkV2YWxFcnJvchJfCh9jb250cmFjdF9jcmVhdGlvbl9ub3Rfc3VwcG9ydG'
'VkGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSHGNvbnRyYWN0Q3JlYXRpb25Ob3RT'
'dXBwb3J0ZWQSWgocdW5zdXBwb3J0ZWRfdHJhbnNhY3Rpb25fdHlwZRgCIAEoCzIWLmdvb2dsZS'
'5wcm90b2J1Zi5FbXB0eUgAUhp1bnN1cHBvcnRlZFRyYW5zYWN0aW9uVHlwZRJPChFub19tYXRj'
'aGluZ19ncmFudBgDIAEoCzIhLmFyYml0ZXIuZXZtLk5vTWF0Y2hpbmdHcmFudEVycm9ySABSD2'
'5vTWF0Y2hpbmdHcmFudBJRChFwb2xpY3lfdmlvbGF0aW9ucxgEIAEoCzIiLmFyYml0ZXIuZXZt'
'LlBvbGljeVZpb2xhdGlvbnNFcnJvckgAUhBwb2xpY3lWaW9sYXRpb25zQgYKBGtpbmQ=');
@$core.Deprecated('Use evmGrantCreateRequestDescriptor instead') @$core.Deprecated('Use evmGrantCreateRequestDescriptor instead')
const EvmGrantCreateRequest$json = { const EvmGrantCreateRequest$json = {
'1': 'EvmGrantCreateRequest', '1': 'EvmGrantCreateRequest',
@@ -563,7 +865,7 @@ const EvmSignTransactionResponse$json = {
'3': 2, '3': 2,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.arbiter.shared.evm.TransactionEvalError', '6': '.arbiter.evm.TransactionEvalError',
'9': 0, '9': 0,
'10': 'evalError' '10': 'evalError'
}, },
@@ -585,9 +887,9 @@ const EvmSignTransactionResponse$json = {
/// Descriptor for `EvmSignTransactionResponse`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `EvmSignTransactionResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List evmSignTransactionResponseDescriptor = $convert.base64Decode( final $typed_data.Uint8List evmSignTransactionResponseDescriptor = $convert.base64Decode(
'ChpFdm1TaWduVHJhbnNhY3Rpb25SZXNwb25zZRIeCglzaWduYXR1cmUYASABKAxIAFIJc2lnbm' 'ChpFdm1TaWduVHJhbnNhY3Rpb25SZXNwb25zZRIeCglzaWduYXR1cmUYASABKAxIAFIJc2lnbm'
'F0dXJlEkkKCmV2YWxfZXJyb3IYAiABKAsyKC5hcmJpdGVyLnNoYXJlZC5ldm0uVHJhbnNhY3Rp' 'F0dXJlEkIKCmV2YWxfZXJyb3IYAiABKAsyIS5hcmJpdGVyLmV2bS5UcmFuc2FjdGlvbkV2YWxF'
'b25FdmFsRXJyb3JIAFIJZXZhbEVycm9yEi0KBWVycm9yGAMgASgOMhUuYXJiaXRlci5ldm0uRX' 'cnJvckgAUglldmFsRXJyb3ISLQoFZXJyb3IYAyABKA4yFS5hcmJpdGVyLmV2bS5Fdm1FcnJvck'
'ZtRXJyb3JIAFIFZXJyb3JCCAoGcmVzdWx0'); 'gAUgVlcnJvckIICgZyZXN1bHQ=');
@$core.Deprecated('Use evmAnalyzeTransactionRequestDescriptor instead') @$core.Deprecated('Use evmAnalyzeTransactionRequestDescriptor instead')
const EvmAnalyzeTransactionRequest$json = { const EvmAnalyzeTransactionRequest$json = {
@@ -613,7 +915,7 @@ const EvmAnalyzeTransactionResponse$json = {
'3': 1, '3': 1,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.arbiter.shared.evm.SpecificMeaning', '6': '.arbiter.evm.SpecificMeaning',
'9': 0, '9': 0,
'10': 'meaning' '10': 'meaning'
}, },
@@ -622,7 +924,7 @@ const EvmAnalyzeTransactionResponse$json = {
'3': 2, '3': 2,
'4': 1, '4': 1,
'5': 11, '5': 11,
'6': '.arbiter.shared.evm.TransactionEvalError', '6': '.arbiter.evm.TransactionEvalError',
'9': 0, '9': 0,
'10': 'evalError' '10': 'evalError'
}, },
@@ -643,8 +945,7 @@ const EvmAnalyzeTransactionResponse$json = {
/// Descriptor for `EvmAnalyzeTransactionResponse`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `EvmAnalyzeTransactionResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List evmAnalyzeTransactionResponseDescriptor = $convert.base64Decode( final $typed_data.Uint8List evmAnalyzeTransactionResponseDescriptor = $convert.base64Decode(
'Ch1Fdm1BbmFseXplVHJhbnNhY3Rpb25SZXNwb25zZRI/CgdtZWFuaW5nGAEgASgLMiMuYXJiaX' 'Ch1Fdm1BbmFseXplVHJhbnNhY3Rpb25SZXNwb25zZRI4CgdtZWFuaW5nGAEgASgLMhwuYXJiaX'
'Rlci5zaGFyZWQuZXZtLlNwZWNpZmljTWVhbmluZ0gAUgdtZWFuaW5nEkkKCmV2YWxfZXJyb3IY' 'Rlci5ldm0uU3BlY2lmaWNNZWFuaW5nSABSB21lYW5pbmcSQgoKZXZhbF9lcnJvchgCIAEoCzIh'
'AiABKAsyKC5hcmJpdGVyLnNoYXJlZC5ldm0uVHJhbnNhY3Rpb25FdmFsRXJyb3JIAFIJZXZhbE' 'LmFyYml0ZXIuZXZtLlRyYW5zYWN0aW9uRXZhbEVycm9ySABSCWV2YWxFcnJvchItCgVlcnJvch'
'Vycm9yEi0KBWVycm9yGAMgASgOMhUuYXJiaXRlci5ldm0uRXZtRXJyb3JIAFIFZXJyb3JCCAoG' 'gDIAEoDjIVLmFyYml0ZXIuZXZtLkV2bUVycm9ySABSBWVycm9yQggKBnJlc3VsdA==');
'cmVzdWx0');

View File

@@ -1,99 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from shared/client.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
class ClientInfo extends $pb.GeneratedMessage {
factory ClientInfo({
$core.String? name,
$core.String? description,
$core.String? version,
}) {
final result = create();
if (name != null) result.name = name;
if (description != null) result.description = description;
if (version != null) result.version = version;
return result;
}
ClientInfo._();
factory ClientInfo.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory ClientInfo.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'ClientInfo',
package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'name')
..aOS(2, _omitFieldNames ? '' : 'description')
..aOS(3, _omitFieldNames ? '' : 'version')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
ClientInfo clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
ClientInfo copyWith(void Function(ClientInfo) updates) =>
super.copyWith((message) => updates(message as ClientInfo)) as ClientInfo;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ClientInfo create() => ClientInfo._();
@$core.override
ClientInfo createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static ClientInfo getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<ClientInfo>(create);
static ClientInfo? _defaultInstance;
@$pb.TagNumber(1)
$core.String get name => $_getSZ(0);
@$pb.TagNumber(1)
set name($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasName() => $_has(0);
@$pb.TagNumber(1)
void clearName() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get description => $_getSZ(1);
@$pb.TagNumber(2)
set description($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasDescription() => $_has(1);
@$pb.TagNumber(2)
void clearDescription() => $_clearField(2);
@$pb.TagNumber(3)
$core.String get version => $_getSZ(2);
@$pb.TagNumber(3)
set version($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasVersion() => $_has(2);
@$pb.TagNumber(3)
void clearVersion() => $_clearField(3);
}
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View File

@@ -1,11 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from shared/client.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports

View File

@@ -1,52 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from shared/client.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
// ignore_for_file: unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use clientInfoDescriptor instead')
const ClientInfo$json = {
'1': 'ClientInfo',
'2': [
{'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'},
{
'1': 'description',
'3': 2,
'4': 1,
'5': 9,
'9': 0,
'10': 'description',
'17': true
},
{
'1': 'version',
'3': 3,
'4': 1,
'5': 9,
'9': 1,
'10': 'version',
'17': true
},
],
'8': [
{'1': '_description'},
{'1': '_version'},
],
};
/// Descriptor for `ClientInfo`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List clientInfoDescriptor = $convert.base64Decode(
'CgpDbGllbnRJbmZvEhIKBG5hbWUYASABKAlSBG5hbWUSJQoLZGVzY3JpcHRpb24YAiABKAlIAF'
'ILZGVzY3JpcHRpb26IAQESHQoHdmVyc2lvbhgDIAEoCUgBUgd2ZXJzaW9uiAEBQg4KDF9kZXNj'
'cmlwdGlvbkIKCghfdmVyc2lvbg==');

View File

@@ -1,851 +0,0 @@
// This is a generated file - do not edit.
//
// Generated from shared/evm.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_relative_imports
import 'dart:core' as $core;
import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:protobuf/protobuf.dart' as $pb;
import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0;
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
class EtherTransferMeaning extends $pb.GeneratedMessage {
factory EtherTransferMeaning({
$core.List<$core.int>? to,
$core.List<$core.int>? value,
}) {
final result = create();
if (to != null) result.to = to;
if (value != null) result.value = value;
return result;
}
EtherTransferMeaning._();
factory EtherTransferMeaning.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory EtherTransferMeaning.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'EtherTransferMeaning',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'to', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EtherTransferMeaning clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EtherTransferMeaning copyWith(void Function(EtherTransferMeaning) updates) =>
super.copyWith((message) => updates(message as EtherTransferMeaning))
as EtherTransferMeaning;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EtherTransferMeaning create() => EtherTransferMeaning._();
@$core.override
EtherTransferMeaning createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static EtherTransferMeaning getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<EtherTransferMeaning>(create);
static EtherTransferMeaning? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get to => $_getN(0);
@$pb.TagNumber(1)
set to($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasTo() => $_has(0);
@$pb.TagNumber(1)
void clearTo() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get value => $_getN(1);
@$pb.TagNumber(2)
set value($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasValue() => $_has(1);
@$pb.TagNumber(2)
void clearValue() => $_clearField(2);
}
class TokenInfo extends $pb.GeneratedMessage {
factory TokenInfo({
$core.String? symbol,
$core.List<$core.int>? address,
$fixnum.Int64? chainId,
}) {
final result = create();
if (symbol != null) result.symbol = symbol;
if (address != null) result.address = address;
if (chainId != null) result.chainId = chainId;
return result;
}
TokenInfo._();
factory TokenInfo.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory TokenInfo.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'TokenInfo',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'symbol')
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'address', $pb.PbFieldType.OY)
..a<$fixnum.Int64>(3, _omitFieldNames ? '' : 'chainId', $pb.PbFieldType.OU6,
defaultOrMaker: $fixnum.Int64.ZERO)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TokenInfo clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TokenInfo copyWith(void Function(TokenInfo) updates) =>
super.copyWith((message) => updates(message as TokenInfo)) as TokenInfo;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static TokenInfo create() => TokenInfo._();
@$core.override
TokenInfo createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static TokenInfo getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TokenInfo>(create);
static TokenInfo? _defaultInstance;
@$pb.TagNumber(1)
$core.String get symbol => $_getSZ(0);
@$pb.TagNumber(1)
set symbol($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasSymbol() => $_has(0);
@$pb.TagNumber(1)
void clearSymbol() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get address => $_getN(1);
@$pb.TagNumber(2)
set address($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasAddress() => $_has(1);
@$pb.TagNumber(2)
void clearAddress() => $_clearField(2);
@$pb.TagNumber(3)
$fixnum.Int64 get chainId => $_getI64(2);
@$pb.TagNumber(3)
set chainId($fixnum.Int64 value) => $_setInt64(2, value);
@$pb.TagNumber(3)
$core.bool hasChainId() => $_has(2);
@$pb.TagNumber(3)
void clearChainId() => $_clearField(3);
}
/// Mirror of token_transfers::Meaning
class TokenTransferMeaning extends $pb.GeneratedMessage {
factory TokenTransferMeaning({
TokenInfo? token,
$core.List<$core.int>? to,
$core.List<$core.int>? value,
}) {
final result = create();
if (token != null) result.token = token;
if (to != null) result.to = to;
if (value != null) result.value = value;
return result;
}
TokenTransferMeaning._();
factory TokenTransferMeaning.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory TokenTransferMeaning.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'TokenTransferMeaning',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..aOM<TokenInfo>(1, _omitFieldNames ? '' : 'token',
subBuilder: TokenInfo.create)
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'to', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
3, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TokenTransferMeaning clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TokenTransferMeaning copyWith(void Function(TokenTransferMeaning) updates) =>
super.copyWith((message) => updates(message as TokenTransferMeaning))
as TokenTransferMeaning;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static TokenTransferMeaning create() => TokenTransferMeaning._();
@$core.override
TokenTransferMeaning createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static TokenTransferMeaning getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<TokenTransferMeaning>(create);
static TokenTransferMeaning? _defaultInstance;
@$pb.TagNumber(1)
TokenInfo get token => $_getN(0);
@$pb.TagNumber(1)
set token(TokenInfo value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasToken() => $_has(0);
@$pb.TagNumber(1)
void clearToken() => $_clearField(1);
@$pb.TagNumber(1)
TokenInfo ensureToken() => $_ensure(0);
@$pb.TagNumber(2)
$core.List<$core.int> get to => $_getN(1);
@$pb.TagNumber(2)
set to($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasTo() => $_has(1);
@$pb.TagNumber(2)
void clearTo() => $_clearField(2);
@$pb.TagNumber(3)
$core.List<$core.int> get value => $_getN(2);
@$pb.TagNumber(3)
set value($core.List<$core.int> value) => $_setBytes(2, value);
@$pb.TagNumber(3)
$core.bool hasValue() => $_has(2);
@$pb.TagNumber(3)
void clearValue() => $_clearField(3);
}
enum SpecificMeaning_Meaning { etherTransfer, tokenTransfer, notSet }
/// Mirror of policies::SpecificMeaning
class SpecificMeaning extends $pb.GeneratedMessage {
factory SpecificMeaning({
EtherTransferMeaning? etherTransfer,
TokenTransferMeaning? tokenTransfer,
}) {
final result = create();
if (etherTransfer != null) result.etherTransfer = etherTransfer;
if (tokenTransfer != null) result.tokenTransfer = tokenTransfer;
return result;
}
SpecificMeaning._();
factory SpecificMeaning.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory SpecificMeaning.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, SpecificMeaning_Meaning>
_SpecificMeaning_MeaningByTag = {
1: SpecificMeaning_Meaning.etherTransfer,
2: SpecificMeaning_Meaning.tokenTransfer,
0: SpecificMeaning_Meaning.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'SpecificMeaning',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..oo(0, [1, 2])
..aOM<EtherTransferMeaning>(1, _omitFieldNames ? '' : 'etherTransfer',
subBuilder: EtherTransferMeaning.create)
..aOM<TokenTransferMeaning>(2, _omitFieldNames ? '' : 'tokenTransfer',
subBuilder: TokenTransferMeaning.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
SpecificMeaning clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
SpecificMeaning copyWith(void Function(SpecificMeaning) updates) =>
super.copyWith((message) => updates(message as SpecificMeaning))
as SpecificMeaning;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static SpecificMeaning create() => SpecificMeaning._();
@$core.override
SpecificMeaning createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static SpecificMeaning getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<SpecificMeaning>(create);
static SpecificMeaning? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
SpecificMeaning_Meaning whichMeaning() =>
_SpecificMeaning_MeaningByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
void clearMeaning() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
EtherTransferMeaning get etherTransfer => $_getN(0);
@$pb.TagNumber(1)
set etherTransfer(EtherTransferMeaning value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasEtherTransfer() => $_has(0);
@$pb.TagNumber(1)
void clearEtherTransfer() => $_clearField(1);
@$pb.TagNumber(1)
EtherTransferMeaning ensureEtherTransfer() => $_ensure(0);
@$pb.TagNumber(2)
TokenTransferMeaning get tokenTransfer => $_getN(1);
@$pb.TagNumber(2)
set tokenTransfer(TokenTransferMeaning value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasTokenTransfer() => $_has(1);
@$pb.TagNumber(2)
void clearTokenTransfer() => $_clearField(2);
@$pb.TagNumber(2)
TokenTransferMeaning ensureTokenTransfer() => $_ensure(1);
}
class GasLimitExceededViolation extends $pb.GeneratedMessage {
factory GasLimitExceededViolation({
$core.List<$core.int>? maxGasFeePerGas,
$core.List<$core.int>? maxPriorityFeePerGas,
}) {
final result = create();
if (maxGasFeePerGas != null) result.maxGasFeePerGas = maxGasFeePerGas;
if (maxPriorityFeePerGas != null)
result.maxPriorityFeePerGas = maxPriorityFeePerGas;
return result;
}
GasLimitExceededViolation._();
factory GasLimitExceededViolation.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory GasLimitExceededViolation.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'GasLimitExceededViolation',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'maxGasFeePerGas', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'maxPriorityFeePerGas', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
GasLimitExceededViolation clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
GasLimitExceededViolation copyWith(
void Function(GasLimitExceededViolation) updates) =>
super.copyWith((message) => updates(message as GasLimitExceededViolation))
as GasLimitExceededViolation;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static GasLimitExceededViolation create() => GasLimitExceededViolation._();
@$core.override
GasLimitExceededViolation createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static GasLimitExceededViolation getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<GasLimitExceededViolation>(create);
static GasLimitExceededViolation? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get maxGasFeePerGas => $_getN(0);
@$pb.TagNumber(1)
set maxGasFeePerGas($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasMaxGasFeePerGas() => $_has(0);
@$pb.TagNumber(1)
void clearMaxGasFeePerGas() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get maxPriorityFeePerGas => $_getN(1);
@$pb.TagNumber(2)
set maxPriorityFeePerGas($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasMaxPriorityFeePerGas() => $_has(1);
@$pb.TagNumber(2)
void clearMaxPriorityFeePerGas() => $_clearField(2);
}
enum EvalViolation_Kind {
invalidTarget,
gasLimitExceeded,
rateLimitExceeded,
volumetricLimitExceeded,
invalidTime,
invalidTransactionType,
notSet
}
class EvalViolation extends $pb.GeneratedMessage {
factory EvalViolation({
$core.List<$core.int>? invalidTarget,
GasLimitExceededViolation? gasLimitExceeded,
$0.Empty? rateLimitExceeded,
$0.Empty? volumetricLimitExceeded,
$0.Empty? invalidTime,
$0.Empty? invalidTransactionType,
}) {
final result = create();
if (invalidTarget != null) result.invalidTarget = invalidTarget;
if (gasLimitExceeded != null) result.gasLimitExceeded = gasLimitExceeded;
if (rateLimitExceeded != null) result.rateLimitExceeded = rateLimitExceeded;
if (volumetricLimitExceeded != null)
result.volumetricLimitExceeded = volumetricLimitExceeded;
if (invalidTime != null) result.invalidTime = invalidTime;
if (invalidTransactionType != null)
result.invalidTransactionType = invalidTransactionType;
return result;
}
EvalViolation._();
factory EvalViolation.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory EvalViolation.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, EvalViolation_Kind>
_EvalViolation_KindByTag = {
1: EvalViolation_Kind.invalidTarget,
2: EvalViolation_Kind.gasLimitExceeded,
3: EvalViolation_Kind.rateLimitExceeded,
4: EvalViolation_Kind.volumetricLimitExceeded,
5: EvalViolation_Kind.invalidTime,
6: EvalViolation_Kind.invalidTransactionType,
0: EvalViolation_Kind.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'EvalViolation',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..oo(0, [1, 2, 3, 4, 5, 6])
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'invalidTarget', $pb.PbFieldType.OY)
..aOM<GasLimitExceededViolation>(
2, _omitFieldNames ? '' : 'gasLimitExceeded',
subBuilder: GasLimitExceededViolation.create)
..aOM<$0.Empty>(3, _omitFieldNames ? '' : 'rateLimitExceeded',
subBuilder: $0.Empty.create)
..aOM<$0.Empty>(4, _omitFieldNames ? '' : 'volumetricLimitExceeded',
subBuilder: $0.Empty.create)
..aOM<$0.Empty>(5, _omitFieldNames ? '' : 'invalidTime',
subBuilder: $0.Empty.create)
..aOM<$0.Empty>(6, _omitFieldNames ? '' : 'invalidTransactionType',
subBuilder: $0.Empty.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EvalViolation clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EvalViolation copyWith(void Function(EvalViolation) updates) =>
super.copyWith((message) => updates(message as EvalViolation))
as EvalViolation;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EvalViolation create() => EvalViolation._();
@$core.override
EvalViolation createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static EvalViolation getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<EvalViolation>(create);
static EvalViolation? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
@$pb.TagNumber(4)
@$pb.TagNumber(5)
@$pb.TagNumber(6)
EvalViolation_Kind whichKind() => _EvalViolation_KindByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
@$pb.TagNumber(4)
@$pb.TagNumber(5)
@$pb.TagNumber(6)
void clearKind() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
$core.List<$core.int> get invalidTarget => $_getN(0);
@$pb.TagNumber(1)
set invalidTarget($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasInvalidTarget() => $_has(0);
@$pb.TagNumber(1)
void clearInvalidTarget() => $_clearField(1);
@$pb.TagNumber(2)
GasLimitExceededViolation get gasLimitExceeded => $_getN(1);
@$pb.TagNumber(2)
set gasLimitExceeded(GasLimitExceededViolation value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasGasLimitExceeded() => $_has(1);
@$pb.TagNumber(2)
void clearGasLimitExceeded() => $_clearField(2);
@$pb.TagNumber(2)
GasLimitExceededViolation ensureGasLimitExceeded() => $_ensure(1);
@$pb.TagNumber(3)
$0.Empty get rateLimitExceeded => $_getN(2);
@$pb.TagNumber(3)
set rateLimitExceeded($0.Empty value) => $_setField(3, value);
@$pb.TagNumber(3)
$core.bool hasRateLimitExceeded() => $_has(2);
@$pb.TagNumber(3)
void clearRateLimitExceeded() => $_clearField(3);
@$pb.TagNumber(3)
$0.Empty ensureRateLimitExceeded() => $_ensure(2);
@$pb.TagNumber(4)
$0.Empty get volumetricLimitExceeded => $_getN(3);
@$pb.TagNumber(4)
set volumetricLimitExceeded($0.Empty value) => $_setField(4, value);
@$pb.TagNumber(4)
$core.bool hasVolumetricLimitExceeded() => $_has(3);
@$pb.TagNumber(4)
void clearVolumetricLimitExceeded() => $_clearField(4);
@$pb.TagNumber(4)
$0.Empty ensureVolumetricLimitExceeded() => $_ensure(3);
@$pb.TagNumber(5)
$0.Empty get invalidTime => $_getN(4);
@$pb.TagNumber(5)
set invalidTime($0.Empty value) => $_setField(5, value);
@$pb.TagNumber(5)
$core.bool hasInvalidTime() => $_has(4);
@$pb.TagNumber(5)
void clearInvalidTime() => $_clearField(5);
@$pb.TagNumber(5)
$0.Empty ensureInvalidTime() => $_ensure(4);
@$pb.TagNumber(6)
$0.Empty get invalidTransactionType => $_getN(5);
@$pb.TagNumber(6)
set invalidTransactionType($0.Empty value) => $_setField(6, value);
@$pb.TagNumber(6)
$core.bool hasInvalidTransactionType() => $_has(5);
@$pb.TagNumber(6)
void clearInvalidTransactionType() => $_clearField(6);
@$pb.TagNumber(6)
$0.Empty ensureInvalidTransactionType() => $_ensure(5);
}
/// Transaction was classified but no grant covers it
class NoMatchingGrantError extends $pb.GeneratedMessage {
factory NoMatchingGrantError({
SpecificMeaning? meaning,
}) {
final result = create();
if (meaning != null) result.meaning = meaning;
return result;
}
NoMatchingGrantError._();
factory NoMatchingGrantError.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory NoMatchingGrantError.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'NoMatchingGrantError',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..aOM<SpecificMeaning>(1, _omitFieldNames ? '' : 'meaning',
subBuilder: SpecificMeaning.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
NoMatchingGrantError clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
NoMatchingGrantError copyWith(void Function(NoMatchingGrantError) updates) =>
super.copyWith((message) => updates(message as NoMatchingGrantError))
as NoMatchingGrantError;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static NoMatchingGrantError create() => NoMatchingGrantError._();
@$core.override
NoMatchingGrantError createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static NoMatchingGrantError getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<NoMatchingGrantError>(create);
static NoMatchingGrantError? _defaultInstance;
@$pb.TagNumber(1)
SpecificMeaning get meaning => $_getN(0);
@$pb.TagNumber(1)
set meaning(SpecificMeaning value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasMeaning() => $_has(0);
@$pb.TagNumber(1)
void clearMeaning() => $_clearField(1);
@$pb.TagNumber(1)
SpecificMeaning ensureMeaning() => $_ensure(0);
}
/// Transaction was classified and a grant was found, but constraints were violated
class PolicyViolationsError extends $pb.GeneratedMessage {
factory PolicyViolationsError({
SpecificMeaning? meaning,
$core.Iterable<EvalViolation>? violations,
}) {
final result = create();
if (meaning != null) result.meaning = meaning;
if (violations != null) result.violations.addAll(violations);
return result;
}
PolicyViolationsError._();
factory PolicyViolationsError.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PolicyViolationsError.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PolicyViolationsError',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..aOM<SpecificMeaning>(1, _omitFieldNames ? '' : 'meaning',
subBuilder: SpecificMeaning.create)
..pPM<EvalViolation>(2, _omitFieldNames ? '' : 'violations',
subBuilder: EvalViolation.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PolicyViolationsError clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PolicyViolationsError copyWith(
void Function(PolicyViolationsError) updates) =>
super.copyWith((message) => updates(message as PolicyViolationsError))
as PolicyViolationsError;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PolicyViolationsError create() => PolicyViolationsError._();
@$core.override
PolicyViolationsError createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static PolicyViolationsError getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<PolicyViolationsError>(create);
static PolicyViolationsError? _defaultInstance;
@$pb.TagNumber(1)
SpecificMeaning get meaning => $_getN(0);
@$pb.TagNumber(1)
set meaning(SpecificMeaning value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasMeaning() => $_has(0);
@$pb.TagNumber(1)
void clearMeaning() => $_clearField(1);
@$pb.TagNumber(1)
SpecificMeaning ensureMeaning() => $_ensure(0);
@$pb.TagNumber(2)
$pb.PbList<EvalViolation> get violations => $_getList(1);
}
enum TransactionEvalError_Kind {
contractCreationNotSupported,
unsupportedTransactionType,
noMatchingGrant,
policyViolations,
notSet
}
/// top-level error returned when transaction evaluation fails
class TransactionEvalError extends $pb.GeneratedMessage {
factory TransactionEvalError({
$0.Empty? contractCreationNotSupported,
$0.Empty? unsupportedTransactionType,
NoMatchingGrantError? noMatchingGrant,
PolicyViolationsError? policyViolations,
}) {
final result = create();
if (contractCreationNotSupported != null)
result.contractCreationNotSupported = contractCreationNotSupported;
if (unsupportedTransactionType != null)
result.unsupportedTransactionType = unsupportedTransactionType;
if (noMatchingGrant != null) result.noMatchingGrant = noMatchingGrant;
if (policyViolations != null) result.policyViolations = policyViolations;
return result;
}
TransactionEvalError._();
factory TransactionEvalError.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory TransactionEvalError.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, TransactionEvalError_Kind>
_TransactionEvalError_KindByTag = {
1: TransactionEvalError_Kind.contractCreationNotSupported,
2: TransactionEvalError_Kind.unsupportedTransactionType,
3: TransactionEvalError_Kind.noMatchingGrant,
4: TransactionEvalError_Kind.policyViolations,
0: TransactionEvalError_Kind.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'TransactionEvalError',
package:
const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'),
createEmptyInstance: create)
..oo(0, [1, 2, 3, 4])
..aOM<$0.Empty>(1, _omitFieldNames ? '' : 'contractCreationNotSupported',
subBuilder: $0.Empty.create)
..aOM<$0.Empty>(2, _omitFieldNames ? '' : 'unsupportedTransactionType',
subBuilder: $0.Empty.create)
..aOM<NoMatchingGrantError>(3, _omitFieldNames ? '' : 'noMatchingGrant',
subBuilder: NoMatchingGrantError.create)
..aOM<PolicyViolationsError>(4, _omitFieldNames ? '' : 'policyViolations',
subBuilder: PolicyViolationsError.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TransactionEvalError clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TransactionEvalError copyWith(void Function(TransactionEvalError) updates) =>
super.copyWith((message) => updates(message as TransactionEvalError))
as TransactionEvalError;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static TransactionEvalError create() => TransactionEvalError._();
@$core.override
TransactionEvalError createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static TransactionEvalError getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<TransactionEvalError>(create);
static TransactionEvalError? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
@$pb.TagNumber(4)
TransactionEvalError_Kind whichKind() =>
_TransactionEvalError_KindByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
@$pb.TagNumber(4)
void clearKind() => $_clearField($_whichOneof(0));
@$pb.TagNumber(1)
$0.Empty get contractCreationNotSupported => $_getN(0);
@$pb.TagNumber(1)
set contractCreationNotSupported($0.Empty value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasContractCreationNotSupported() => $_has(0);
@$pb.TagNumber(1)
void clearContractCreationNotSupported() => $_clearField(1);
@$pb.TagNumber(1)
$0.Empty ensureContractCreationNotSupported() => $_ensure(0);
@$pb.TagNumber(2)
$0.Empty get unsupportedTransactionType => $_getN(1);
@$pb.TagNumber(2)
set unsupportedTransactionType($0.Empty value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasUnsupportedTransactionType() => $_has(1);
@$pb.TagNumber(2)
void clearUnsupportedTransactionType() => $_clearField(2);
@$pb.TagNumber(2)
$0.Empty ensureUnsupportedTransactionType() => $_ensure(1);
@$pb.TagNumber(3)
NoMatchingGrantError get noMatchingGrant => $_getN(2);
@$pb.TagNumber(3)
set noMatchingGrant(NoMatchingGrantError value) => $_setField(3, value);
@$pb.TagNumber(3)
$core.bool hasNoMatchingGrant() => $_has(2);
@$pb.TagNumber(3)
void clearNoMatchingGrant() => $_clearField(3);
@$pb.TagNumber(3)
NoMatchingGrantError ensureNoMatchingGrant() => $_ensure(2);
@$pb.TagNumber(4)
PolicyViolationsError get policyViolations => $_getN(3);
@$pb.TagNumber(4)
set policyViolations(PolicyViolationsError value) => $_setField(4, value);
@$pb.TagNumber(4)
$core.bool hasPolicyViolations() => $_has(3);
@$pb.TagNumber(4)
void clearPolicyViolations() => $_clearField(4);
@$pb.TagNumber(4)
PolicyViolationsError ensurePolicyViolations() => $_ensure(3);
}
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

Some files were not shown because too many files have changed in this diff Show More