@arcium-hq/client 0.10.4 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.mjs CHANGED
@@ -7,8 +7,8 @@ import { randomBytes as randomBytes$1 } from '@noble/hashes/utils';
7
7
  import { twistedEdwards } from '@noble/curves/abstract/edwards';
8
8
  import fs from 'fs';
9
9
  import * as anchor from '@anchor-lang/core';
10
- import { Program } from '@anchor-lang/core';
11
- import { PublicKey, AddressLookupTableProgram } from '@solana/web3.js';
10
+ import anchor__default, { BorshCoder, convertIdlToCamelCase, Program } from '@anchor-lang/core';
11
+ import { AddressLookupTableProgram, PublicKey } from '@solana/web3.js';
12
12
 
13
13
  /**
14
14
  * Scalar field prime modulus for Curve25519: 2^252 + 27742317777372353535851937790883648493
@@ -1864,7 +1864,7 @@ function createPacker(fields, typeName = 'Packer') {
1864
1864
  var address = "Arcj82pX7HxYKLR92qvgZUAd7vGS1k4hQvAFcPATFdEQ";
1865
1865
  var metadata = {
1866
1866
  name: "arcium",
1867
- version: "0.10.4",
1867
+ version: "0.11.1",
1868
1868
  spec: "0.1.0",
1869
1869
  description: "The Arcium program"
1870
1870
  };
@@ -2155,6 +2155,84 @@ var instructions = [
2155
2155
  }
2156
2156
  ]
2157
2157
  },
2158
+ {
2159
+ name: "bind_recovery_peer_migration",
2160
+ discriminator: [
2161
+ 30,
2162
+ 148,
2163
+ 4,
2164
+ 206,
2165
+ 139,
2166
+ 2,
2167
+ 55,
2168
+ 156
2169
+ ],
2170
+ accounts: [
2171
+ {
2172
+ name: "authority",
2173
+ docs: [
2174
+ "The recovery peer's `authority` — same dual role as in `MigrateArxNode`: it authorizes the",
2175
+ "bind and is the owner of `primary_stake_account`."
2176
+ ],
2177
+ signer: true
2178
+ },
2179
+ {
2180
+ name: "recovery_peer_account",
2181
+ docs: [
2182
+ "Must already be layout-migrated (`migrate_recovery_peer`) so the appended",
2183
+ "`primary_stake_account` field exists; otherwise the zero-copy load fails on the short",
2184
+ "account. Bundle `migrate_recovery_peer` ahead of this instruction in the same transaction."
2185
+ ],
2186
+ writable: true,
2187
+ pda: {
2188
+ seeds: [
2189
+ {
2190
+ kind: "const",
2191
+ value: [
2192
+ 82,
2193
+ 101,
2194
+ 99,
2195
+ 111,
2196
+ 118,
2197
+ 101,
2198
+ 114,
2199
+ 121,
2200
+ 80,
2201
+ 101,
2202
+ 101,
2203
+ 114,
2204
+ 65,
2205
+ 99,
2206
+ 99,
2207
+ 111,
2208
+ 117,
2209
+ 110,
2210
+ 116
2211
+ ]
2212
+ },
2213
+ {
2214
+ kind: "arg",
2215
+ path: "peer_offset"
2216
+ }
2217
+ ]
2218
+ }
2219
+ },
2220
+ {
2221
+ name: "primary_stake_account",
2222
+ writable: true
2223
+ },
2224
+ {
2225
+ name: "arcium_staking_program",
2226
+ address: "ArcStnN9zZZVB5WjgPhLHjYpY7Gb29mzb96ySsb1kxgq"
2227
+ }
2228
+ ],
2229
+ args: [
2230
+ {
2231
+ name: "peer_offset",
2232
+ type: "u32"
2233
+ }
2234
+ ]
2235
+ },
2158
2236
  {
2159
2237
  name: "bump_epoch_cluster",
2160
2238
  discriminator: [
@@ -2268,6 +2346,7 @@ var instructions = [
2268
2346
  },
2269
2347
  {
2270
2348
  name: "mxe",
2349
+ writable: true,
2271
2350
  pda: {
2272
2351
  seeds: [
2273
2352
  {
@@ -2805,6 +2884,7 @@ var instructions = [
2805
2884
  },
2806
2885
  {
2807
2886
  name: "mxe",
2887
+ writable: true,
2808
2888
  pda: {
2809
2889
  seeds: [
2810
2890
  {
@@ -3134,13 +3214,88 @@ var instructions = [
3134
3214
  ],
3135
3215
  accounts: [
3136
3216
  {
3137
- name: "node_authority",
3217
+ name: "staking_pool_signer",
3218
+ docs: [
3219
+ "The `arcium_staking::state::StakingPoolAccount` PDA, signing via CPI. Also the destination",
3220
+ "for the settled lamports (so the staking program immediately owns them for later",
3221
+ "proportional distribution). The `seeds`/`bump` constraint verifies it's the canonical pool",
3222
+ "PDA under `ARCIUM_STAKING_ID` (so only the staking program can call this); `Signer`",
3223
+ "enforces it actually signed."
3224
+ ],
3138
3225
  writable: true,
3139
- signer: true
3226
+ signer: true,
3227
+ pda: {
3228
+ seeds: [
3229
+ {
3230
+ kind: "const",
3231
+ value: [
3232
+ 83,
3233
+ 116,
3234
+ 97,
3235
+ 107,
3236
+ 105,
3237
+ 110,
3238
+ 103,
3239
+ 80,
3240
+ 111,
3241
+ 111,
3242
+ 108,
3243
+ 65,
3244
+ 99,
3245
+ 99,
3246
+ 111,
3247
+ 117,
3248
+ 110,
3249
+ 116
3250
+ ]
3251
+ }
3252
+ ],
3253
+ program: {
3254
+ kind: "const",
3255
+ value: [
3256
+ 146,
3257
+ 110,
3258
+ 184,
3259
+ 172,
3260
+ 179,
3261
+ 131,
3262
+ 118,
3263
+ 35,
3264
+ 207,
3265
+ 122,
3266
+ 30,
3267
+ 190,
3268
+ 228,
3269
+ 134,
3270
+ 232,
3271
+ 140,
3272
+ 222,
3273
+ 89,
3274
+ 53,
3275
+ 150,
3276
+ 174,
3277
+ 187,
3278
+ 151,
3279
+ 58,
3280
+ 208,
3281
+ 108,
3282
+ 237,
3283
+ 119,
3284
+ 97,
3285
+ 204,
3286
+ 184,
3287
+ 186
3288
+ ]
3289
+ }
3290
+ }
3140
3291
  },
3141
3292
  {
3142
- name: "recipient",
3143
- writable: true
3293
+ name: "primary_stake_account",
3294
+ docs: [
3295
+ "The `PrimaryStakingAccount` bound to this node. Passed so the handler can verify",
3296
+ "`node.primary_staking_account == primary_stake_account.key()` — i.e. the staking account",
3297
+ "that's about to claim the fees is the one this node was initialized with."
3298
+ ]
3144
3299
  },
3145
3300
  {
3146
3301
  name: "cluster",
@@ -3219,7 +3374,197 @@ var instructions = [
3219
3374
  name: "node_offset",
3220
3375
  type: "u32"
3221
3376
  }
3222
- ]
3377
+ ],
3378
+ returns: "u64"
3379
+ },
3380
+ {
3381
+ name: "claim_recovery_peer_fees",
3382
+ discriminator: [
3383
+ 132,
3384
+ 120,
3385
+ 187,
3386
+ 164,
3387
+ 106,
3388
+ 57,
3389
+ 202,
3390
+ 8
3391
+ ],
3392
+ accounts: [
3393
+ {
3394
+ name: "staking_pool_signer",
3395
+ docs: [
3396
+ "`arcium_staking::StakingPoolAccount` PDA, signing via CPI and receiving the drained",
3397
+ "lamports. The `seeds`/`bump` constraint verifies it's the canonical pool PDA under",
3398
+ "`ARCIUM_STAKING_ID`; `Signer` enforces `is_signer`."
3399
+ ],
3400
+ writable: true,
3401
+ signer: true,
3402
+ pda: {
3403
+ seeds: [
3404
+ {
3405
+ kind: "const",
3406
+ value: [
3407
+ 83,
3408
+ 116,
3409
+ 97,
3410
+ 107,
3411
+ 105,
3412
+ 110,
3413
+ 103,
3414
+ 80,
3415
+ 111,
3416
+ 111,
3417
+ 108,
3418
+ 65,
3419
+ 99,
3420
+ 99,
3421
+ 111,
3422
+ 117,
3423
+ 110,
3424
+ 116
3425
+ ]
3426
+ }
3427
+ ],
3428
+ program: {
3429
+ kind: "const",
3430
+ value: [
3431
+ 146,
3432
+ 110,
3433
+ 184,
3434
+ 172,
3435
+ 179,
3436
+ 131,
3437
+ 118,
3438
+ 35,
3439
+ 207,
3440
+ 122,
3441
+ 30,
3442
+ 190,
3443
+ 228,
3444
+ 134,
3445
+ 232,
3446
+ 140,
3447
+ 222,
3448
+ 89,
3449
+ 53,
3450
+ 150,
3451
+ 174,
3452
+ 187,
3453
+ 151,
3454
+ 58,
3455
+ 208,
3456
+ 108,
3457
+ 237,
3458
+ 119,
3459
+ 97,
3460
+ 204,
3461
+ 184,
3462
+ 186
3463
+ ]
3464
+ }
3465
+ }
3466
+ },
3467
+ {
3468
+ name: "primary_stake_account",
3469
+ docs: [
3470
+ "`PrimaryStakingAccount` the claiming peer is bound to. Only the key is compared",
3471
+ "against `recovery_peer.primary_stake_account`; the staking program owns the struct."
3472
+ ]
3473
+ },
3474
+ {
3475
+ name: "recovery_peer",
3476
+ pda: {
3477
+ seeds: [
3478
+ {
3479
+ kind: "const",
3480
+ value: [
3481
+ 82,
3482
+ 101,
3483
+ 99,
3484
+ 111,
3485
+ 118,
3486
+ 101,
3487
+ 114,
3488
+ 121,
3489
+ 80,
3490
+ 101,
3491
+ 101,
3492
+ 114,
3493
+ 65,
3494
+ 99,
3495
+ 99,
3496
+ 111,
3497
+ 117,
3498
+ 110,
3499
+ 116
3500
+ ]
3501
+ },
3502
+ {
3503
+ kind: "arg",
3504
+ path: "peer_offset"
3505
+ }
3506
+ ]
3507
+ }
3508
+ },
3509
+ {
3510
+ name: "mxe",
3511
+ writable: true,
3512
+ pda: {
3513
+ seeds: [
3514
+ {
3515
+ kind: "const",
3516
+ value: [
3517
+ 77,
3518
+ 88,
3519
+ 69,
3520
+ 65,
3521
+ 99,
3522
+ 99,
3523
+ 111,
3524
+ 117,
3525
+ 110,
3526
+ 116
3527
+ ]
3528
+ },
3529
+ {
3530
+ kind: "arg",
3531
+ path: "mxe_program"
3532
+ }
3533
+ ]
3534
+ }
3535
+ },
3536
+ {
3537
+ name: "pool",
3538
+ writable: true,
3539
+ pda: {
3540
+ seeds: [
3541
+ {
3542
+ kind: "const",
3543
+ value: [
3544
+ 70,
3545
+ 101,
3546
+ 101,
3547
+ 80,
3548
+ 111,
3549
+ 111,
3550
+ 108
3551
+ ]
3552
+ }
3553
+ ]
3554
+ }
3555
+ }
3556
+ ],
3557
+ args: [
3558
+ {
3559
+ name: "mxe_program",
3560
+ type: "pubkey"
3561
+ },
3562
+ {
3563
+ name: "peer_offset",
3564
+ type: "u32"
3565
+ }
3566
+ ],
3567
+ returns: "u64"
3223
3568
  },
3224
3569
  {
3225
3570
  name: "close_computation_definition",
@@ -4526,6 +4871,14 @@ var instructions = [
4526
4871
  }
4527
4872
  ],
4528
4873
  args: [
4874
+ {
4875
+ name: "_selector",
4876
+ type: {
4877
+ defined: {
4878
+ name: "LeaderSelector"
4879
+ }
4880
+ }
4881
+ }
4529
4882
  ]
4530
4883
  },
4531
4884
  {
@@ -6137,6 +6490,31 @@ var instructions = [
6137
6490
  ]
6138
6491
  }
6139
6492
  },
6493
+ {
6494
+ name: "primary_stake_account",
6495
+ docs: [
6496
+ "The `PrimaryStakingAccount` (owned by the `arcium_staking` program) that this node will be",
6497
+ "bound to for the rest of its life. Reward settlement requires this linkage: fees accrued",
6498
+ "under this node can only be drained via a CPI signed by the staking program's pool PDA",
6499
+ "after matching on this key.",
6500
+ "the staking program's responsibility — if the staker binds garbage they lock themselves",
6501
+ "out of rewards, which is their own problem."
6502
+ ],
6503
+ writable: true
6504
+ },
6505
+ {
6506
+ name: "staker",
6507
+ docs: [
6508
+ "Authority of `primary_stake_account`. Required as a second signer so we can CPI into",
6509
+ "`arcium_staking::bind_primary_stake` and commit the stake to this node. The staking",
6510
+ "program re-derives the stake PDA from this key and rejects the call if it mismatches."
6511
+ ],
6512
+ signer: true
6513
+ },
6514
+ {
6515
+ name: "arcium_staking_program",
6516
+ address: "ArcStnN9zZZVB5WjgPhLHjYpY7Gb29mzb96ySsb1kxgq"
6517
+ },
6140
6518
  {
6141
6519
  name: "system_program",
6142
6520
  address: "11111111111111111111111111111111"
@@ -7004,6 +7382,15 @@ var instructions = [
7004
7382
  }
7005
7383
  ],
7006
7384
  args: [
7385
+ {
7386
+ name: "recovery_peers",
7387
+ type: {
7388
+ array: [
7389
+ "u32",
7390
+ 100
7391
+ ]
7392
+ }
7393
+ }
7007
7394
  ]
7008
7395
  },
7009
7396
  {
@@ -7118,8 +7505,8 @@ var instructions = [
7118
7505
  ]
7119
7506
  },
7120
7507
  {
7121
- kind: "arg",
7122
- path: "_mxe_program"
7508
+ kind: "account",
7509
+ path: "mxe_program"
7123
7510
  }
7124
7511
  ]
7125
7512
  }
@@ -7419,6 +7806,17 @@ var instructions = [
7419
7806
  ]
7420
7807
  }
7421
7808
  },
7809
+ {
7810
+ name: "instructions_sysvar",
7811
+ docs: [
7812
+ "Instructions sysvar — used in the handler to verify the **next** instruction in this",
7813
+ "transaction is `arcium_staking::init_mxe_recovery_stake_state` with the same",
7814
+ "`mxe_program`. This mirrors the reverse check on the staking side and is what",
7815
+ "guarantees that every MXE is created alongside its recovery stake state (replacement",
7816
+ "for the CPI we couldn't do because of the 4KB stack limit on `try_accounts`)."
7817
+ ],
7818
+ address: "Sysvar1nstructions1111111111111111111111111"
7819
+ },
7422
7820
  {
7423
7821
  name: "system_program",
7424
7822
  address: "11111111111111111111111111111111"
@@ -7429,19 +7827,6 @@ var instructions = [
7429
7827
  name: "cluster_offset",
7430
7828
  type: "u32"
7431
7829
  },
7432
- {
7433
- name: "mxe_program",
7434
- type: "pubkey"
7435
- },
7436
- {
7437
- name: "recovery_peers",
7438
- type: {
7439
- array: [
7440
- "u32",
7441
- 100
7442
- ]
7443
- }
7444
- },
7445
7830
  {
7446
7831
  name: "keygen_offset",
7447
7832
  type: "u64"
@@ -7899,6 +8284,31 @@ var instructions = [
7899
8284
  ]
7900
8285
  }
7901
8286
  },
8287
+ {
8288
+ name: "primary_stake_account",
8289
+ docs: [
8290
+ "The `PrimaryStakingAccount` (owned by `arcium_staking`) that the recovery peer is",
8291
+ "binding itself to. Mirrors the stake-first requirement on `InitArxNode`: every",
8292
+ "recovery peer has to point at a real staking account so we have someone to slash",
8293
+ "(or dock rewards from) if the peer misbehaves. Full account-structure validation",
8294
+ "is the staking program's job — here we just make sure the account is owned by it.",
8295
+ "point at any primary stake account they have authority over."
8296
+ ],
8297
+ writable: true
8298
+ },
8299
+ {
8300
+ name: "staker",
8301
+ docs: [
8302
+ "Authority of `primary_stake_account`. Required as a second signer so we can CPI into",
8303
+ "`arcium_staking::bind_primary_stake` and commit the stake to this recovery peer. The",
8304
+ "staking program re-derives the stake PDA from this key and rejects on mismatch."
8305
+ ],
8306
+ signer: true
8307
+ },
8308
+ {
8309
+ name: "arcium_staking_program",
8310
+ address: "ArcStnN9zZZVB5WjgPhLHjYpY7Gb29mzb96ySsb1kxgq"
8311
+ },
7902
8312
  {
7903
8313
  name: "system_program",
7904
8314
  address: "11111111111111111111111111111111"
@@ -8035,6 +8445,171 @@ var instructions = [
8035
8445
  }
8036
8446
  ]
8037
8447
  },
8448
+ {
8449
+ name: "migrate_arx_node",
8450
+ discriminator: [
8451
+ 26,
8452
+ 223,
8453
+ 103,
8454
+ 52,
8455
+ 241,
8456
+ 117,
8457
+ 229,
8458
+ 143
8459
+ ],
8460
+ accounts: [
8461
+ {
8462
+ name: "authority",
8463
+ docs: [
8464
+ "The node's `config.authority`, which both *authorizes* the bind (only the node's own admin",
8465
+ "may link a stake account to it — otherwise anyone could divert a node's rewards to their",
8466
+ "own stake) and doubles as the `staker` (owner of `primary_stake_account`) for the CPI."
8467
+ ],
8468
+ signer: true
8469
+ },
8470
+ {
8471
+ name: "arx_node_acc",
8472
+ writable: true,
8473
+ pda: {
8474
+ seeds: [
8475
+ {
8476
+ kind: "const",
8477
+ value: [
8478
+ 65,
8479
+ 114,
8480
+ 120,
8481
+ 78,
8482
+ 111,
8483
+ 100,
8484
+ 101
8485
+ ]
8486
+ },
8487
+ {
8488
+ kind: "arg",
8489
+ path: "node_offset"
8490
+ }
8491
+ ]
8492
+ }
8493
+ },
8494
+ {
8495
+ name: "primary_stake_account",
8496
+ docs: [
8497
+ "The `PrimaryStakingAccount` (created beforehand via",
8498
+ "`arcium_staking::add_primary_stake_to_legacy_acc`) to bind. Owner-checked here; the staking",
8499
+ "program re-derives `[SEED, authority]` and rejects a mismatch during the bind CPI."
8500
+ ],
8501
+ writable: true
8502
+ },
8503
+ {
8504
+ name: "arcium_staking_program",
8505
+ address: "ArcStnN9zZZVB5WjgPhLHjYpY7Gb29mzb96ySsb1kxgq"
8506
+ }
8507
+ ],
8508
+ args: [
8509
+ {
8510
+ name: "node_offset",
8511
+ type: "u32"
8512
+ }
8513
+ ]
8514
+ },
8515
+ {
8516
+ name: "migrate_cluster",
8517
+ docs: [
8518
+ "One-shot layout migrations for the staking upgrade. Each grows one already-deployed",
8519
+ "account to the current (append-only) layout; idempotent and permissionless. See",
8520
+ "`instructions::migration`."
8521
+ ],
8522
+ discriminator: [
8523
+ 158,
8524
+ 61,
8525
+ 104,
8526
+ 161,
8527
+ 253,
8528
+ 138,
8529
+ 0,
8530
+ 17
8531
+ ],
8532
+ accounts: [
8533
+ {
8534
+ name: "payer",
8535
+ writable: true,
8536
+ signer: true
8537
+ },
8538
+ {
8539
+ name: "cluster",
8540
+ docs: [
8541
+ "because the new program cannot deserialize the old (short) layout via `Account<Cluster>`."
8542
+ ],
8543
+ writable: true
8544
+ },
8545
+ {
8546
+ name: "system_program",
8547
+ address: "11111111111111111111111111111111"
8548
+ }
8549
+ ],
8550
+ args: [
8551
+ ]
8552
+ },
8553
+ {
8554
+ name: "migrate_mxe_account",
8555
+ discriminator: [
8556
+ 96,
8557
+ 162,
8558
+ 117,
8559
+ 100,
8560
+ 242,
8561
+ 143,
8562
+ 16,
8563
+ 80
8564
+ ],
8565
+ accounts: [
8566
+ {
8567
+ name: "payer",
8568
+ writable: true,
8569
+ signer: true
8570
+ },
8571
+ {
8572
+ name: "mxe",
8573
+ writable: true
8574
+ },
8575
+ {
8576
+ name: "system_program",
8577
+ address: "11111111111111111111111111111111"
8578
+ }
8579
+ ],
8580
+ args: [
8581
+ ]
8582
+ },
8583
+ {
8584
+ name: "migrate_recovery_peer",
8585
+ discriminator: [
8586
+ 58,
8587
+ 226,
8588
+ 37,
8589
+ 60,
8590
+ 200,
8591
+ 31,
8592
+ 251,
8593
+ 245
8594
+ ],
8595
+ accounts: [
8596
+ {
8597
+ name: "payer",
8598
+ writable: true,
8599
+ signer: true
8600
+ },
8601
+ {
8602
+ name: "recovery_peer",
8603
+ writable: true
8604
+ },
8605
+ {
8606
+ name: "system_program",
8607
+ address: "11111111111111111111111111111111"
8608
+ }
8609
+ ],
8610
+ args: [
8611
+ ]
8612
+ },
8038
8613
  {
8039
8614
  name: "propose_fee",
8040
8615
  discriminator: [
@@ -8207,6 +8782,42 @@ var instructions = [
8207
8782
  ]
8208
8783
  }
8209
8784
  },
8785
+ {
8786
+ name: "mempool",
8787
+ docs: [
8788
+ "The cluster's mempool account, used only to read its size (from the discriminator) so we",
8789
+ "know the minimum primary stake the invited node must hold.",
8790
+ "`mempool_size_of`."
8791
+ ],
8792
+ pda: {
8793
+ seeds: [
8794
+ {
8795
+ kind: "const",
8796
+ value: [
8797
+ 77,
8798
+ 101,
8799
+ 109,
8800
+ 112,
8801
+ 111,
8802
+ 111,
8803
+ 108
8804
+ ]
8805
+ },
8806
+ {
8807
+ kind: "arg",
8808
+ path: "cluster_offset"
8809
+ }
8810
+ ]
8811
+ }
8812
+ },
8813
+ {
8814
+ name: "primary_stake_account",
8815
+ docs: [
8816
+ "The `PrimaryStakingAccount` (owned by `arcium_staking`) bound to the invited node. We read",
8817
+ "its `primary_stake` (first field) to enforce the per-mempool-size minimum. Verified to be",
8818
+ "owned by the staking program and to match the node's recorded `primary_staking_account`."
8819
+ ]
8820
+ },
8210
8821
  {
8211
8822
  name: "clock",
8212
8823
  writable: true,
@@ -8253,7 +8864,12 @@ var instructions = [
8253
8864
  docs: [
8254
8865
  "Queues a computation.",
8255
8866
  "cu_price_micro: The priority price of a CU, in micro-lamports. Used",
8256
- "to calculate the priority fee and rounded down."
8867
+ "to calculate the priority fee and rounded down.",
8868
+ "callback_cu_limit: The compute unit limit to request for the callback transaction(s)",
8869
+ "via set_compute_unit_limit. 0 means unset (the node uses the default compute budget).",
8870
+ "A non-zero value incurs an additional priority fee of callback_cu_limit * cu_price_micro.",
8871
+ "callback_cu_limit + padding together occupy the 8 bytes that previously held the",
8872
+ "(always-zero) output_delivery_fee: u64, so the instruction layout is unchanged."
8257
8873
  ],
8258
8874
  discriminator: [
8259
8875
  1,
@@ -8586,8 +9202,12 @@ var instructions = [
8586
9202
  type: "u8"
8587
9203
  },
8588
9204
  {
8589
- name: "output_delivery_fee",
8590
- type: "u64"
9205
+ name: "callback_cu_limit",
9206
+ type: "u32"
9207
+ },
9208
+ {
9209
+ name: "padding",
9210
+ type: "u32"
8591
9211
  },
8592
9212
  {
8593
9213
  name: "cu_price_micro",
@@ -9864,7 +10484,63 @@ var instructions = [
9864
10484
  ],
9865
10485
  accounts: [
9866
10486
  {
9867
- name: "current_authority",
10487
+ name: "current_authority",
10488
+ writable: true,
10489
+ signer: true
10490
+ },
10491
+ {
10492
+ name: "cluster_acc",
10493
+ writable: true,
10494
+ pda: {
10495
+ seeds: [
10496
+ {
10497
+ kind: "const",
10498
+ value: [
10499
+ 67,
10500
+ 108,
10501
+ 117,
10502
+ 115,
10503
+ 116,
10504
+ 101,
10505
+ 114
10506
+ ]
10507
+ },
10508
+ {
10509
+ kind: "arg",
10510
+ path: "_id"
10511
+ }
10512
+ ]
10513
+ }
10514
+ }
10515
+ ],
10516
+ args: [
10517
+ {
10518
+ name: "cluster_id",
10519
+ type: "u32"
10520
+ },
10521
+ {
10522
+ name: "new_authority",
10523
+ type: {
10524
+ option: "pubkey"
10525
+ }
10526
+ }
10527
+ ]
10528
+ },
10529
+ {
10530
+ name: "set_cluster_td_info",
10531
+ discriminator: [
10532
+ 182,
10533
+ 126,
10534
+ 92,
10535
+ 101,
10536
+ 25,
10537
+ 252,
10538
+ 84,
10539
+ 180
10540
+ ],
10541
+ accounts: [
10542
+ {
10543
+ name: "authority",
9868
10544
  writable: true,
9869
10545
  signer: true
9870
10546
  },
@@ -9899,28 +10575,32 @@ var instructions = [
9899
10575
  type: "u32"
9900
10576
  },
9901
10577
  {
9902
- name: "new_authority",
10578
+ name: "td_info",
9903
10579
  type: {
9904
- option: "pubkey"
10580
+ option: {
10581
+ defined: {
10582
+ name: "NodeMetadata"
10583
+ }
10584
+ }
9905
10585
  }
9906
10586
  }
9907
10587
  ]
9908
10588
  },
9909
10589
  {
9910
- name: "set_cluster_td_info",
10590
+ name: "set_leader_choice",
9911
10591
  discriminator: [
9912
- 182,
9913
- 126,
9914
- 92,
9915
- 101,
9916
- 25,
9917
- 252,
9918
- 84,
9919
- 180
10592
+ 42,
10593
+ 7,
10594
+ 112,
10595
+ 255,
10596
+ 254,
10597
+ 186,
10598
+ 135,
10599
+ 133
9920
10600
  ],
9921
10601
  accounts: [
9922
10602
  {
9923
- name: "authority",
10603
+ name: "node_authority",
9924
10604
  writable: true,
9925
10605
  signer: true
9926
10606
  },
@@ -9943,7 +10623,53 @@ var instructions = [
9943
10623
  },
9944
10624
  {
9945
10625
  kind: "arg",
9946
- path: "_id"
10626
+ path: "cluster_offset"
10627
+ }
10628
+ ]
10629
+ }
10630
+ },
10631
+ {
10632
+ name: "arx_node_acc",
10633
+ pda: {
10634
+ seeds: [
10635
+ {
10636
+ kind: "const",
10637
+ value: [
10638
+ 65,
10639
+ 114,
10640
+ 120,
10641
+ 78,
10642
+ 111,
10643
+ 100,
10644
+ 101
10645
+ ]
10646
+ },
10647
+ {
10648
+ kind: "arg",
10649
+ path: "node_offset"
10650
+ }
10651
+ ]
10652
+ }
10653
+ },
10654
+ {
10655
+ name: "mempool",
10656
+ pda: {
10657
+ seeds: [
10658
+ {
10659
+ kind: "const",
10660
+ value: [
10661
+ 77,
10662
+ 101,
10663
+ 109,
10664
+ 112,
10665
+ 111,
10666
+ 111,
10667
+ 108
10668
+ ]
10669
+ },
10670
+ {
10671
+ kind: "arg",
10672
+ path: "cluster_offset"
9947
10673
  }
9948
10674
  ]
9949
10675
  }
@@ -9951,16 +10677,18 @@ var instructions = [
9951
10677
  ],
9952
10678
  args: [
9953
10679
  {
9954
- name: "cluster_id",
10680
+ name: "cluster_offset",
9955
10681
  type: "u32"
9956
10682
  },
9957
10683
  {
9958
- name: "td_info",
10684
+ name: "node_offset",
10685
+ type: "u32"
10686
+ },
10687
+ {
10688
+ name: "choice",
9959
10689
  type: {
9960
- option: {
9961
- defined: {
9962
- name: "NodeMetadata"
9963
- }
10690
+ defined: {
10691
+ name: "LeaderChoice"
9964
10692
  }
9965
10693
  }
9966
10694
  }
@@ -10292,6 +11020,156 @@ var instructions = [
10292
11020
  }
10293
11021
  ]
10294
11022
  },
11023
+ {
11024
+ name: "set_node_staking",
11025
+ discriminator: [
11026
+ 158,
11027
+ 40,
11028
+ 109,
11029
+ 244,
11030
+ 217,
11031
+ 195,
11032
+ 35,
11033
+ 140
11034
+ ],
11035
+ accounts: [
11036
+ {
11037
+ name: "staking_pool_signer",
11038
+ docs: [
11039
+ "The `arcium_staking::state::StakingPoolAccount` PDA, signing via CPI. The `seeds`/`bump`",
11040
+ "constraint verifies it's the canonical pool PDA under `ARCIUM_STAKING_ID` (so only the",
11041
+ "staking program can call this)"
11042
+ ],
11043
+ signer: true,
11044
+ pda: {
11045
+ seeds: [
11046
+ {
11047
+ kind: "const",
11048
+ value: [
11049
+ 83,
11050
+ 116,
11051
+ 97,
11052
+ 107,
11053
+ 105,
11054
+ 110,
11055
+ 103,
11056
+ 80,
11057
+ 111,
11058
+ 111,
11059
+ 108,
11060
+ 65,
11061
+ 99,
11062
+ 99,
11063
+ 111,
11064
+ 117,
11065
+ 110,
11066
+ 116
11067
+ ]
11068
+ }
11069
+ ],
11070
+ program: {
11071
+ kind: "const",
11072
+ value: [
11073
+ 146,
11074
+ 110,
11075
+ 184,
11076
+ 172,
11077
+ 179,
11078
+ 131,
11079
+ 118,
11080
+ 35,
11081
+ 207,
11082
+ 122,
11083
+ 30,
11084
+ 190,
11085
+ 228,
11086
+ 134,
11087
+ 232,
11088
+ 140,
11089
+ 222,
11090
+ 89,
11091
+ 53,
11092
+ 150,
11093
+ 174,
11094
+ 187,
11095
+ 151,
11096
+ 58,
11097
+ 208,
11098
+ 108,
11099
+ 237,
11100
+ 119,
11101
+ 97,
11102
+ 204,
11103
+ 184,
11104
+ 186
11105
+ ]
11106
+ }
11107
+ }
11108
+ },
11109
+ {
11110
+ name: "cluster",
11111
+ writable: true,
11112
+ pda: {
11113
+ seeds: [
11114
+ {
11115
+ kind: "const",
11116
+ value: [
11117
+ 67,
11118
+ 108,
11119
+ 117,
11120
+ 115,
11121
+ 116,
11122
+ 101,
11123
+ 114
11124
+ ]
11125
+ },
11126
+ {
11127
+ kind: "arg",
11128
+ path: "cluster_offset"
11129
+ }
11130
+ ]
11131
+ }
11132
+ },
11133
+ {
11134
+ name: "clock",
11135
+ pda: {
11136
+ seeds: [
11137
+ {
11138
+ kind: "const",
11139
+ value: [
11140
+ 67,
11141
+ 108,
11142
+ 111,
11143
+ 99,
11144
+ 107,
11145
+ 65,
11146
+ 99,
11147
+ 99,
11148
+ 111,
11149
+ 117,
11150
+ 110,
11151
+ 116
11152
+ ]
11153
+ }
11154
+ ]
11155
+ }
11156
+ }
11157
+ ],
11158
+ args: [
11159
+ {
11160
+ name: "cluster_offset",
11161
+ type: "u32"
11162
+ },
11163
+ {
11164
+ name: "node_offset",
11165
+ type: "u32"
11166
+ },
11167
+ {
11168
+ name: "stake",
11169
+ type: "u64"
11170
+ }
11171
+ ]
11172
+ },
10295
11173
  {
10296
11174
  name: "submit_aggregated_bls_pubkey",
10297
11175
  discriminator: [
@@ -11621,6 +12499,11 @@ var errors = [
11621
12499
  name: "MaxParallelismReached",
11622
12500
  msg: "Max parallelism reached"
11623
12501
  },
12502
+ {
12503
+ code: 6104,
12504
+ name: "MempoolAlreadyFullSize",
12505
+ msg: "Mempool is already at its full allocated size"
12506
+ },
11624
12507
  {
11625
12508
  code: 6200,
11626
12509
  name: "InvalidComputationOffset",
@@ -11796,6 +12679,16 @@ var errors = [
11796
12679
  name: "InvalidNodeOffset",
11797
12680
  msg: "Node offset is invalid"
11798
12681
  },
12682
+ {
12683
+ code: 6411,
12684
+ name: "InvalidStakingPoolSigner",
12685
+ msg: "The provided staking pool signer is not the staking program's StakingPoolAccount PDA"
12686
+ },
12687
+ {
12688
+ code: 6412,
12689
+ name: "InvalidStakingAccount",
12690
+ msg: "The provided primary stake account is not owned by the staking program or does not match the node's bound staking account"
12691
+ },
11799
12692
  {
11800
12693
  code: 6500,
11801
12694
  name: "ClusterFull",
@@ -11854,7 +12747,7 @@ var errors = [
11854
12747
  {
11855
12748
  code: 6602,
11856
12749
  name: "HeapFull",
11857
- msg: "Heap is full"
12750
+ msg: "Mempool capacity for the current slot reached - retry next slot or reduce queue rate"
11858
12751
  },
11859
12752
  {
11860
12753
  code: 6603,
@@ -11971,6 +12864,11 @@ var errors = [
11971
12864
  name: "RecoveryInitAlreadyInitialized",
11972
12865
  msg: "Recovery already initialized"
11973
12866
  },
12867
+ {
12868
+ code: 6626,
12869
+ name: "InvalidSubsequentIx",
12870
+ msg: "Subsequent instruction in this transaction is not the expected one"
12871
+ },
11974
12872
  {
11975
12873
  code: 6700,
11976
12874
  name: "MxeNotInMigrationState",
@@ -12095,6 +12993,16 @@ var errors = [
12095
12993
  code: 6725,
12096
12994
  name: "CannotCloseMxeDuringMigration",
12097
12995
  msg: "MXE is in migration state, cannot close MXE"
12996
+ },
12997
+ {
12998
+ code: 6726,
12999
+ name: "InvalidMigrationAccount",
13000
+ msg: "Account is not a valid target for this migration (wrong owner or discriminator)"
13001
+ },
13002
+ {
13003
+ code: 6727,
13004
+ name: "InsufficientPrimaryStake",
13005
+ msg: "Node's primary stake is below the minimum for this cluster's mempool size"
12098
13006
  }
12099
13007
  ];
12100
13008
  var types = [
@@ -12895,30 +13803,71 @@ var types = [
12895
13803
  }
12896
13804
  },
12897
13805
  {
12898
- name: "bls_public_key",
13806
+ name: "bls_public_key",
13807
+ docs: [
13808
+ "BLS public key for the cluster (64 bytes compressed G2 point for alt-bn128)",
13809
+ "Set only when all nodes have submitted and agreed on the aggregated pubkey"
13810
+ ],
13811
+ type: {
13812
+ defined: {
13813
+ name: "SetUnset",
13814
+ generics: [
13815
+ {
13816
+ kind: "type",
13817
+ type: {
13818
+ defined: {
13819
+ name: "BN254G2BLSPublicKey"
13820
+ }
13821
+ }
13822
+ }
13823
+ ]
13824
+ }
13825
+ }
13826
+ },
13827
+ {
13828
+ name: "bump",
13829
+ docs: [
13830
+ "PDA bump. Declared by hand rather than via the `#[bump]` macro (which appends the bump",
13831
+ "as the *final* struct field) so it keeps its original offset right after",
13832
+ "`bls_public_key`. Everything below is appended *after* the bump, which means the byte",
13833
+ "layout of every field up to and including `bump` is identical to the pre-staking",
13834
+ "`Cluster` — old deserializers (including external user programs that read this account)",
13835
+ "decode the original prefix and harmlessly ignore the trailing staking fields."
13836
+ ],
13837
+ type: "u8"
13838
+ },
13839
+ {
13840
+ name: "current_epoch_total_rewards",
13841
+ docs: [
13842
+ "Running total of computation rewards accrued during `rewards_epoch`. Drained to zero",
13843
+ "by `claim_node_fees` when nodes settle via `finalize_epoch_rewards`."
13844
+ ],
13845
+ type: "u64"
13846
+ },
13847
+ {
13848
+ name: "rewards_epoch",
13849
+ docs: [
13850
+ "The epoch that `current_epoch_total_rewards` belongs to. If the clock has advanced",
13851
+ "past this epoch and `current_epoch_total_rewards > 0`, the rewards are stale",
13852
+ "(nodes didn't settle in time) — new accruals are silently skipped until nodes",
13853
+ "finalize, which punishes lazy operators."
13854
+ ],
13855
+ type: {
13856
+ defined: {
13857
+ name: "Epoch"
13858
+ }
13859
+ }
13860
+ },
13861
+ {
13862
+ name: "leader_selector",
12899
13863
  docs: [
12900
- "BLS public key for the cluster (64 bytes compressed G2 point for alt-bn128)",
12901
- "Set only when all nodes have submitted and agreed on the aggregated pubkey"
13864
+ "The selector for leader."
12902
13865
  ],
12903
13866
  type: {
12904
13867
  defined: {
12905
- name: "SetUnset",
12906
- generics: [
12907
- {
12908
- kind: "type",
12909
- type: {
12910
- defined: {
12911
- name: "BN254G2BLSPublicKey"
12912
- }
12913
- }
12914
- }
12915
- ]
13868
+ name: "LeaderSelector"
12916
13869
  }
12917
13870
  }
12918
- },
12919
- {
12920
- name: "bump",
12921
- type: "u8"
12922
13871
  }
12923
13872
  ]
12924
13873
  }
@@ -13452,16 +14401,28 @@ var types = [
13452
14401
  {
13453
14402
  name: "priority_fee",
13454
14403
  docs: [
13455
- "The additional fee to enforce priortized execution in the mempool."
14404
+ "The additional fee to enforce prioritized execution in the mempool."
13456
14405
  ],
13457
14406
  type: "u64"
13458
14407
  },
13459
14408
  {
13460
- name: "output_delivery_fee",
14409
+ name: "callback_cu_limit",
13461
14410
  docs: [
13462
- "A fee for output delivery fees (i.e. tx fees)."
14411
+ "The compute unit limit to request for the callback transaction(s), i.e. how many CUs the",
14412
+ "node should request via set_compute_unit_limit. 0 means unset, in which case the node uses",
14413
+ "the default compute budget.",
14414
+ "",
14415
+ "This reuses the low 4 bytes of what was previously `output_delivery_fee: u64` (which was",
14416
+ "always 0), so the serialized layout of ExecutionFee is unchanged."
13463
14417
  ],
13464
- type: "u64"
14418
+ type: "u32"
14419
+ },
14420
+ {
14421
+ name: "padding",
14422
+ docs: [
14423
+ "Padding preserving the original 8-byte (u64) layout of the former `output_delivery_fee`."
14424
+ ],
14425
+ type: "u32"
13465
14426
  }
13466
14427
  ]
13467
14428
  }
@@ -13827,6 +14788,113 @@ var types = [
13827
14788
  ]
13828
14789
  }
13829
14790
  },
14791
+ {
14792
+ name: "LeaderChoice",
14793
+ docs: [
14794
+ "The computation chosen by a node to be executed when the node is leader."
14795
+ ],
14796
+ type: {
14797
+ kind: "struct",
14798
+ fields: [
14799
+ {
14800
+ name: "offset",
14801
+ docs: [
14802
+ "Computation_offset of the chosen computation."
14803
+ ],
14804
+ type: "u64"
14805
+ },
14806
+ {
14807
+ name: "slot_idx",
14808
+ docs: [
14809
+ "The index of the max_heap the computation is in inside the MemPool's Circular Buffer.",
14810
+ "This is the physical index, not the logical one."
14811
+ ],
14812
+ type: "u16"
14813
+ }
14814
+ ]
14815
+ }
14816
+ },
14817
+ {
14818
+ name: "LeaderInfo",
14819
+ docs: [
14820
+ "The information about a node."
14821
+ ],
14822
+ type: {
14823
+ kind: "struct",
14824
+ fields: [
14825
+ {
14826
+ name: "stake",
14827
+ docs: [
14828
+ "The node's stake."
14829
+ ],
14830
+ type: "u64"
14831
+ },
14832
+ {
14833
+ name: "count",
14834
+ docs: [
14835
+ "The number + 1 of times the node has been chosen as leader in this cycle.",
14836
+ "0 if the stake is unset.",
14837
+ "This way works well for performance."
14838
+ ],
14839
+ type: "u64"
14840
+ },
14841
+ {
14842
+ name: "last_counter_plus_one",
14843
+ docs: [
14844
+ "The last time the node has been chosen as leader."
14845
+ ],
14846
+ type: "u64"
14847
+ },
14848
+ {
14849
+ name: "choice",
14850
+ docs: [
14851
+ "The choice of that node."
14852
+ ],
14853
+ type: {
14854
+ defined: {
14855
+ name: "LeaderChoice"
14856
+ }
14857
+ }
14858
+ }
14859
+ ]
14860
+ }
14861
+ },
14862
+ {
14863
+ name: "LeaderSelector",
14864
+ docs: [
14865
+ "To select a Leader.",
14866
+ "Uses the greatest divisors method: https://en.wikipedia.org/wiki/D%27Hondt_method"
14867
+ ],
14868
+ type: {
14869
+ kind: "struct",
14870
+ fields: [
14871
+ {
14872
+ name: "staking_epoch",
14873
+ docs: [
14874
+ "The last epoch the staking was set."
14875
+ ],
14876
+ type: {
14877
+ defined: {
14878
+ name: "Epoch"
14879
+ }
14880
+ }
14881
+ },
14882
+ {
14883
+ name: "info",
14884
+ docs: [
14885
+ "The information about each node."
14886
+ ],
14887
+ type: {
14888
+ vec: {
14889
+ defined: {
14890
+ name: "LeaderInfo"
14891
+ }
14892
+ }
14893
+ }
14894
+ }
14895
+ ]
14896
+ }
14897
+ },
13830
14898
  {
13831
14899
  name: "LocalCircuitSource",
13832
14900
  type: {
@@ -13951,7 +15019,40 @@ var types = [
13951
15019
  },
13952
15020
  {
13953
15021
  name: "bump",
15022
+ docs: [
15023
+ "PDA bump. Declared by hand rather than via the `#[bump]` macro (which appends the bump",
15024
+ "as the *final* struct field) so it keeps its original offset right after `status`.",
15025
+ "The recovery-reward fields below are appended *after* the bump, leaving the byte layout",
15026
+ "of every field up to and including `bump` identical to the pre-staking `MXEAccount` —",
15027
+ "old deserializers (including external user programs) decode the original prefix and",
15028
+ "harmlessly ignore the trailing fields."
15029
+ ],
13954
15030
  type: "u8"
15031
+ },
15032
+ {
15033
+ name: "current_epoch_recovery_rewards",
15034
+ docs: [
15035
+ "Running total of recovery-peer rewards accrued during `recovery_rewards_epoch`.",
15036
+ "Fed by the 20% slice of every computation/failure fee processed on this MXE;",
15037
+ "drained to zero by `claim_recovery_peer_fees` when recovery peers settle via",
15038
+ "`arcium_staking::finalize_recovery_epoch_rewards`. Same stale-epoch guard as",
15039
+ "`Cluster::current_epoch_total_rewards` — if peers don't settle before the epoch",
15040
+ "rolls over, new accruals are silently skipped until the pot is drained."
15041
+ ],
15042
+ type: "u64"
15043
+ },
15044
+ {
15045
+ name: "recovery_rewards_epoch",
15046
+ docs: [
15047
+ "Epoch that `current_epoch_recovery_rewards` is attributed to. Compared against the",
15048
+ "executing cluster's `last_updated_epoch` (the same proxy used by cluster rewards) to",
15049
+ "decide whether a new accrual is for the current round or a stale one."
15050
+ ],
15051
+ type: {
15052
+ defined: {
15053
+ name: "Epoch"
15054
+ }
15055
+ }
13955
15056
  }
13956
15057
  ]
13957
15058
  }
@@ -14286,9 +15387,7 @@ var types = [
14286
15387
  name: "NodeRef",
14287
15388
  docs: [
14288
15389
  "A reference to a node in the cluster.",
14289
- "The offset is to derive the Node Account.",
14290
- "The current_total_rewards is the total rewards the node has received so far in the current",
14291
- "epoch."
15390
+ "The offset is to derive the Node Account."
14292
15391
  ],
14293
15392
  type: {
14294
15393
  kind: "struct",
@@ -14298,11 +15397,22 @@ var types = [
14298
15397
  type: "u32"
14299
15398
  },
14300
15399
  {
14301
- name: "current_total_rewards",
15400
+ name: "_padding",
14302
15401
  docs: [
14303
- "Current total rewards the node has received in the current epoch in lamports."
15402
+ "Reserved padding occupying the 8 bytes that previously held `current_total_rewards: u64`",
15403
+ "(per-node reward tracking, now superseded by the cluster-level",
15404
+ "`current_epoch_total_rewards`). We keep these bytes rather than shrinking `NodeRef`",
15405
+ "because `nodes: Vec<NodeRef>` sits in the *middle* of the `Cluster` struct: removing the",
15406
+ "field would change the encoded element size and desync the borsh decode of every field",
15407
+ "after `nodes` for already-deployed accounts and external deserializers. Do not repurpose",
15408
+ "without a full account migration."
14304
15409
  ],
14305
- type: "u64"
15410
+ type: {
15411
+ array: [
15412
+ "u8",
15413
+ 8
15414
+ ]
15415
+ }
14306
15416
  },
14307
15417
  {
14308
15418
  name: "vote",
@@ -14740,7 +15850,27 @@ var types = [
14740
15850
  },
14741
15851
  {
14742
15852
  name: "bump",
15853
+ docs: [
15854
+ "PDA bump. Declared by hand rather than via the `#[bump]` macro (which appends the bump",
15855
+ "as the *final* struct field) so it keeps its original offset (76) right after",
15856
+ "`peer_offset`. `primary_stake_account` is appended *after* the bump, leaving the byte",
15857
+ "layout of every field up to and including `bump` identical to the pre-staking",
15858
+ "`RecoveryPeerAccount` — old deserializers decode the original prefix and harmlessly",
15859
+ "ignore the trailing field."
15860
+ ],
14743
15861
  type: "u8"
15862
+ },
15863
+ {
15864
+ name: "primary_stake_account",
15865
+ docs: [
15866
+ "The `PrimaryStakingAccount` (owned by `arcium_staking`) this recovery peer is bound",
15867
+ "to. Enforced at init time via an owner check so every recovery peer has skin in the",
15868
+ "game — the same stake-first model we already apply to `ArxNode`. Stored here so",
15869
+ "downstream instructions (and off-chain consumers) can look up the backing stake",
15870
+ "without re-validating the chain of accounts. Appended after `bump` to preserve the",
15871
+ "legacy on-chain layout (see the `bump` field comment)."
15872
+ ],
15873
+ type: "pubkey"
14744
15874
  }
14745
15875
  ]
14746
15876
  }
@@ -15289,6 +16419,26 @@ const MXE_RECOVERY_ACC_SEED = 'MxeRecoveryAccount';
15289
16419
  * @constant {string}
15290
16420
  */
15291
16421
  const RAW_CIRCUIT_ACC_SEED = 'ComputationDefinitionRaw';
16422
+ /**
16423
+ * Seed for RecoveryPeerAccount PDA.
16424
+ * @constant {string}
16425
+ */
16426
+ const RECOVERY_PEER_ACC_SEED = 'RecoveryPeerAccount';
16427
+ /**
16428
+ * Seed for Operator PDA.
16429
+ * @constant {string}
16430
+ */
16431
+ const OPERATOR_ACC_SEED = 'Operator';
16432
+ /**
16433
+ * Seed for FailureClaimAccountHeader PDA.
16434
+ * @constant {string}
16435
+ */
16436
+ const FAILURE_CLAIM_ACC_SEED = 'FailureClaimAccountHeader';
16437
+ /**
16438
+ * Seed for ArciumSignerAccount PDA.
16439
+ * @constant {string}
16440
+ */
16441
+ const ARCIUM_SIGNER_ACC_SEED = 'ArciumSignerAccount';
15292
16442
  /**
15293
16443
  * Maximum number of bytes that can be reallocated per instruction.
15294
16444
  * @constant {number}
@@ -15309,11 +16459,36 @@ const MAX_ACCOUNT_SIZE = 10485760;
15309
16459
  * @constant {number}
15310
16460
  */
15311
16461
  const MAX_EMBIGGEN_IX_PER_TX = 18;
16462
+ /**
16463
+ * Default number of upload transactions sent in parallel.
16464
+ * @constant {number}
16465
+ */
16466
+ const DEFAULT_UPLOAD_TX_BATCH_SIZE = 500;
15312
16467
  /**
15313
16468
  * Size of account discriminator in bytes.
15314
16469
  * @constant {number}
15315
16470
  */
15316
16471
  const DISCRIMINATOR_SIZE = 8;
16472
+ /**
16473
+ * Size of the bump field in a ComputationDefinitionRaw account.
16474
+ * @constant {number}
16475
+ */
16476
+ const RAW_CIRCUIT_ACCOUNT_BUMP_SIZE = 1;
16477
+ /**
16478
+ * Size of ComputationDefinitionRaw account metadata before circuit bytes.
16479
+ * @constant {number}
16480
+ */
16481
+ const RAW_CIRCUIT_ACCOUNT_HEADER_SIZE = DISCRIMINATOR_SIZE + RAW_CIRCUIT_ACCOUNT_BUMP_SIZE;
16482
+ /**
16483
+ * Maximum circuit bytes that fit in one ComputationDefinitionRaw account.
16484
+ * @constant {number}
16485
+ */
16486
+ const MAX_RAW_CIRCUIT_BYTES_PER_ACC = MAX_ACCOUNT_SIZE - RAW_CIRCUIT_ACCOUNT_HEADER_SIZE;
16487
+ /**
16488
+ * Maximum number of raw circuit accounts addressable by the u8 raw circuit index.
16489
+ * @constant {number}
16490
+ */
16491
+ const MAX_RAW_CIRCUIT_ACCOUNTS = 256;
15317
16492
  /**
15318
16493
  * Size of offset buffer in bytes (u32).
15319
16494
  * @constant {number}
@@ -15324,7 +16499,20 @@ const OFFSET_BUFFER_SIZE = 4;
15324
16499
  * @constant {number}
15325
16500
  */
15326
16501
  const COMP_DEF_OFFSET_SIZE = 4;
16502
+ /**
16503
+ * Maximum recovery peer slots supported by key recovery accounts.
16504
+ * @constant {number}
16505
+ */
16506
+ const MAX_RECOVERY_PEERS = 100;
16507
+ /**
16508
+ * Minimum recovery peers required for key recovery.
16509
+ * @constant {number}
16510
+ */
16511
+ const MIN_RECOVERY_PEERS = 4;
15327
16512
 
16513
+ const U64_SEED_SIZE = 8;
16514
+ const MAX_U8 = 0xff;
16515
+ const MAX_U32$1 = 0xffffffff;
15328
16516
  /**
15329
16517
  * Return the public key of the deployed Arcium program on Solana.
15330
16518
  * @returns Arcium program's public key.
@@ -15339,10 +16527,7 @@ function getArciumProgramId() {
15339
16527
  * @returns Derived computation account public key.
15340
16528
  */
15341
16529
  function getComputationAccAddress(clusterOffset, computationOffset) {
15342
- const clOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15343
- clOffsetBuffer.writeUInt32LE(clusterOffset, 0);
15344
- const seeds = [Buffer.from(COMPUTATION_ACC_SEED), clOffsetBuffer, computationOffset.toArrayLike(Buffer, 'le', 8)];
15345
- return generateArciumPDAFrom(seeds)[0];
16530
+ return findArciumPda([stringSeed(COMPUTATION_ACC_SEED), u32Seed(clusterOffset), u64Seed(computationOffset)]);
15346
16531
  }
15347
16532
  /**
15348
16533
  * Derive the mempool account address for a given cluster.
@@ -15350,10 +16535,7 @@ function getComputationAccAddress(clusterOffset, computationOffset) {
15350
16535
  * @returns Derived mempool account public key.
15351
16536
  */
15352
16537
  function getMempoolAccAddress(clusterOffset) {
15353
- const clOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15354
- clOffsetBuffer.writeUInt32LE(clusterOffset, 0);
15355
- const seeds = [Buffer.from(MEMPOOL_ACC_SEED), clOffsetBuffer];
15356
- return generateArciumPDAFrom(seeds)[0];
16538
+ return findArciumPda([stringSeed(MEMPOOL_ACC_SEED), u32Seed(clusterOffset)]);
15357
16539
  }
15358
16540
  /**
15359
16541
  * Derive the executing pool account address for a given cluster.
@@ -15361,26 +16543,21 @@ function getMempoolAccAddress(clusterOffset) {
15361
16543
  * @returns Derived executing pool account public key.
15362
16544
  */
15363
16545
  function getExecutingPoolAccAddress(clusterOffset) {
15364
- const clOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15365
- clOffsetBuffer.writeUInt32LE(clusterOffset, 0);
15366
- const seeds = [Buffer.from(EXEC_POOL_ACC_SEED), clOffsetBuffer];
15367
- return generateArciumPDAFrom(seeds)[0];
16546
+ return findArciumPda([stringSeed(EXEC_POOL_ACC_SEED), u32Seed(clusterOffset)]);
15368
16547
  }
15369
16548
  /**
15370
16549
  * Derive the fee pool account address.
15371
16550
  * @returns Derived fee pool account public key.
15372
16551
  */
15373
16552
  function getFeePoolAccAddress() {
15374
- const seeds = [Buffer.from(POOL_ACC_SEED)];
15375
- return generateArciumPDAFrom(seeds)[0];
16553
+ return findArciumPda([stringSeed(POOL_ACC_SEED)]);
15376
16554
  }
15377
16555
  /**
15378
16556
  * Derive the clock account address.
15379
16557
  * @returns Derived clock account public key.
15380
16558
  */
15381
16559
  function getClockAccAddress() {
15382
- const seeds = [Buffer.from(CLOCK_ACC_SEED)];
15383
- return generateArciumPDAFrom(seeds)[0];
16560
+ return findArciumPda([stringSeed(CLOCK_ACC_SEED)]);
15384
16561
  }
15385
16562
  /**
15386
16563
  * Derive the cluster account address for a given offset.
@@ -15388,10 +16565,7 @@ function getClockAccAddress() {
15388
16565
  * @returns Derived cluster account public key.
15389
16566
  */
15390
16567
  function getClusterAccAddress(clusterOffset) {
15391
- const offsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15392
- offsetBuffer.writeUInt32LE(clusterOffset, 0);
15393
- const seeds = [Buffer.from(CLUSTER_ACC_SEED), offsetBuffer];
15394
- return generateArciumPDAFrom(seeds)[0];
16568
+ return findArciumPda([stringSeed(CLUSTER_ACC_SEED), u32Seed(clusterOffset)]);
15395
16569
  }
15396
16570
  /**
15397
16571
  * Derive the ArxNode account address for a given offset.
@@ -15399,10 +16573,7 @@ function getClusterAccAddress(clusterOffset) {
15399
16573
  * @returns Derived ArxNode account public key.
15400
16574
  */
15401
16575
  function getArxNodeAccAddress(nodeOffset) {
15402
- const offsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15403
- offsetBuffer.writeUInt32LE(nodeOffset, 0);
15404
- const seeds = [Buffer.from(ARX_NODE_ACC_SEED), offsetBuffer];
15405
- return generateArciumPDAFrom(seeds)[0];
16576
+ return findArciumPda([stringSeed(ARX_NODE_ACC_SEED), u32Seed(nodeOffset)]);
15406
16577
  }
15407
16578
  /**
15408
16579
  * Derive the MXE account address for a given MXE program ID.
@@ -15410,8 +16581,7 @@ function getArxNodeAccAddress(nodeOffset) {
15410
16581
  * @returns Derived MXE account public key.
15411
16582
  */
15412
16583
  function getMXEAccAddress(mxeProgramId) {
15413
- const seeds = [Buffer.from(MXE_ACCOUNT_SEED), mxeProgramId.toBuffer()];
15414
- return generateArciumPDAFrom(seeds)[0];
16584
+ return findArciumPda([stringSeed(MXE_ACCOUNT_SEED), pubkeySeed(mxeProgramId)]);
15415
16585
  }
15416
16586
  /**
15417
16587
  * Derive the computation definition account address for a given MXE program ID and offset.
@@ -15420,10 +16590,7 @@ function getMXEAccAddress(mxeProgramId) {
15420
16590
  * @returns Derived computation definition account public key.
15421
16591
  */
15422
16592
  function getCompDefAccAddress(mxeProgramId, compDefOffset) {
15423
- const offsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15424
- offsetBuffer.writeUInt32LE(compDefOffset, 0);
15425
- const seeds = [Buffer.from(COMP_DEF_ACC_SEED), mxeProgramId.toBuffer(), offsetBuffer];
15426
- return generateArciumPDAFrom(seeds)[0];
16593
+ return findArciumPda([stringSeed(COMP_DEF_ACC_SEED), pubkeySeed(mxeProgramId), u32Seed(compDefOffset)]);
15427
16594
  }
15428
16595
  /**
15429
16596
  * Derive the recovery cluster account address for a given MXE program ID.
@@ -15431,8 +16598,7 @@ function getCompDefAccAddress(mxeProgramId, compDefOffset) {
15431
16598
  * @returns Derived recovery cluster account public key.
15432
16599
  */
15433
16600
  function getRecoveryClusterAccAddress(mxeProgramId) {
15434
- const seeds = [Buffer.from(RECOVERY_CLUSTER_ACC_SEED), mxeProgramId.toBuffer()];
15435
- return generateArciumPDAFrom(seeds)[0];
16601
+ return findArciumPda([stringSeed(RECOVERY_CLUSTER_ACC_SEED), pubkeySeed(mxeProgramId)]);
15436
16602
  }
15437
16603
  /**
15438
16604
  * Derive the MXE recovery account address for a key recovery session.
@@ -15440,22 +16606,52 @@ function getRecoveryClusterAccAddress(mxeProgramId) {
15440
16606
  * @returns Derived MXE recovery account public key.
15441
16607
  */
15442
16608
  function getMxeRecoveryAccAddress(originalMxeProgramId) {
15443
- const seeds = [Buffer.from(MXE_RECOVERY_ACC_SEED), originalMxeProgramId.toBuffer()];
15444
- return generateArciumPDAFrom(seeds)[0];
16609
+ return findArciumPda([stringSeed(MXE_RECOVERY_ACC_SEED), pubkeySeed(originalMxeProgramId)]);
16610
+ }
16611
+ /**
16612
+ * Derive the recovery peer account address for a given recovery peer offset.
16613
+ * @param peerOffset - Recovery peer offset as a u32 in `[0, 2^32 - 1]`.
16614
+ * @returns Derived recovery peer account public key.
16615
+ */
16616
+ function getRecoveryPeerAccAddress(peerOffset) {
16617
+ return findArciumPda([stringSeed(RECOVERY_PEER_ACC_SEED), u32Seed(peerOffset)]);
16618
+ }
16619
+ /**
16620
+ * Derive the operator account address for a given operator signer.
16621
+ * @param operatorSigner - Public key of the operator signer.
16622
+ * @returns Derived operator account public key.
16623
+ */
16624
+ function getOperatorAccAddress(operatorSigner) {
16625
+ return findArciumPda([stringSeed(OPERATOR_ACC_SEED), pubkeySeed(operatorSigner)]);
16626
+ }
16627
+ /**
16628
+ * Derive the failure claim account address for a given MXE program and computation offset.
16629
+ * @param mxeProgramId - Public key of the MXE program.
16630
+ * @param computationOffset - Computation offset as an anchor.BN in `[0, 2^64 - 1]`.
16631
+ * @returns Derived failure claim account public key.
16632
+ */
16633
+ function getFailureClaimAccAddress(mxeProgramId, computationOffset) {
16634
+ return findArciumPda([stringSeed(FAILURE_CLAIM_ACC_SEED), pubkeySeed(mxeProgramId), u64Seed(computationOffset)]);
16635
+ }
16636
+ /**
16637
+ * Derive the Arcium signer account address used by an MXE program when invoking the Arcium
16638
+ * program. Unlike most other helpers in this module, this PDA is derived under the MXE
16639
+ * program ID (the caller), not the Arcium program ID - Arcium verifies the seed via
16640
+ * `seeds::program = _mxe_program`.
16641
+ * @param mxeProgramId - Public key of the MXE program that owns the signer PDA.
16642
+ * @returns Derived Arcium signer account public key.
16643
+ */
16644
+ function getArciumSignerAccAddress(mxeProgramId) {
16645
+ return findPda(mxeProgramId, [stringSeed(ARCIUM_SIGNER_ACC_SEED)]);
15445
16646
  }
15446
16647
  /**
15447
16648
  * Derive the raw circuit account address for a given computation definition and index.
15448
16649
  * @param compDefPubkey - Public key of the computation definition account.
15449
- * @param rawCircuitIndex - Index of the raw circuit account (0-based).
16650
+ * @param rawCircuitIndex - Index of the raw circuit account as a u8 in `[0, 255]`.
15450
16651
  * @returns Derived raw circuit account public key.
15451
16652
  */
15452
16653
  function getRawCircuitAccAddress(compDefPubkey, rawCircuitIndex) {
15453
- const seeds = [
15454
- Buffer.from(RAW_CIRCUIT_ACC_SEED),
15455
- compDefPubkey.toBuffer(),
15456
- Buffer.from([rawCircuitIndex]),
15457
- ];
15458
- return generateArciumPDAFrom(seeds)[0];
16654
+ return findArciumPda([stringSeed(RAW_CIRCUIT_ACC_SEED), pubkeySeed(compDefPubkey), u8Seed(rawCircuitIndex)]);
15459
16655
  }
15460
16656
  /**
15461
16657
  * Derive the address lookup table address for an MXE program.
@@ -15465,120 +16661,149 @@ function getRawCircuitAccAddress(compDefPubkey, rawCircuitIndex) {
15465
16661
  */
15466
16662
  function getLookupTableAddress(mxeProgramId, lutOffset) {
15467
16663
  const mxeAccount = getMXEAccAddress(mxeProgramId);
15468
- const lutIndexBuffer = lutOffset.toArrayLike(Buffer, 'le', 8);
15469
- const seeds = [mxeAccount.toBuffer(), lutIndexBuffer];
15470
- return PublicKey.findProgramAddressSync(seeds, AddressLookupTableProgram.programId)[0];
16664
+ return findPda(AddressLookupTableProgram.programId, [pubkeySeed(mxeAccount), u64Seed(lutOffset)]);
15471
16665
  }
15472
- /**
15473
- * Generate a program-derived address (PDA) from the provided seeds and the Arcium program ID.
15474
- * @param seeds - Array of Buffer seeds used for PDA derivation.
15475
- * @returns Tuple containing the derived public key and the bump seed.
15476
- */
15477
- function generateArciumPDAFrom(seeds) {
15478
- const programId = getArciumProgramId();
15479
- return PublicKey.findProgramAddressSync(seeds, programId);
16666
+ function stringSeed(value) {
16667
+ return Buffer.from(value);
16668
+ }
16669
+ function u8Seed(value) {
16670
+ assertIntegerInRange(value, 0, MAX_U8, 'u8 seed');
16671
+ return Buffer.from([value]);
16672
+ }
16673
+ function u32Seed(value) {
16674
+ assertIntegerInRange(value, 0, MAX_U32$1, 'u32 seed');
16675
+ const buffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
16676
+ buffer.writeUInt32LE(value, 0);
16677
+ return buffer;
16678
+ }
16679
+ function u64Seed(value) {
16680
+ if (value.isNeg() || value.byteLength() > U64_SEED_SIZE) {
16681
+ throw new RangeError(`u64 seed must be between 0 and 18446744073709551615 (got ${value.toString()})`);
16682
+ }
16683
+ return value.toArrayLike(Buffer, 'le', U64_SEED_SIZE);
16684
+ }
16685
+ function pubkeySeed(value) {
16686
+ return value.toBuffer();
16687
+ }
16688
+ function findArciumPda(seeds) {
16689
+ return findPda(getArciumProgramId(), seeds);
16690
+ }
16691
+ function findPda(programId, seeds) {
16692
+ return PublicKey.findProgramAddressSync(seeds, programId)[0];
16693
+ }
16694
+ function assertIntegerInRange(value, min, max, label) {
16695
+ if (!Number.isInteger(value) || value < min || value > max) {
16696
+ throw new RangeError(`${label} must be an integer between ${min} and ${max} (got ${value})`);
16697
+ }
15480
16698
  }
15481
16699
 
15482
- const TINY_MEMPOOL_ACC_NAME = 'tinyMempool';
15483
- const TINY_MEMPOOL_DISCRIMINATOR = [
15484
- 176,
15485
- 33,
15486
- 67,
15487
- 108,
15488
- 73,
15489
- 135,
15490
- 110,
15491
- 166,
15492
- ];
15493
- const TINY_EXECPOOL_ACC_NAME = 'tinyExecPool';
15494
- const TINY_EXECPOOL_DISCRIMINATOR = [
15495
- 80,
15496
- 245,
15497
- 5,
15498
- 90,
15499
- 154,
15500
- 189,
15501
- 190,
15502
- 172,
15503
- ];
15504
- const SMALL_MEMPOOL_ACC_NAME = 'smallMempool';
15505
- const SMALL_MEMPOOL_DISCRIMINATOR = [
15506
- 123,
15507
- 153,
15508
- 151,
15509
- 118,
15510
- 126,
15511
- 71,
15512
- 73,
15513
- 92,
15514
- ];
15515
- const SMALL_EXECPOOL_ACC_NAME = 'smallExecPool';
15516
- const SMALL_EXECPOOL_DISCRIMINATOR = [
15517
- 37,
15518
- 147,
15519
- 249,
15520
- 253,
15521
- 217,
15522
- 136,
15523
- 3,
15524
- 87,
16700
+ // Names are validated against the IDL account-name union at compile time, so a
16701
+ // typo or stale tier fails `tsc` rather than only throwing at load.
16702
+ const MEMPOOL_DECODER_ACCOUNT_NAMES = [
16703
+ 'tinyMempool',
16704
+ 'smallMempool',
16705
+ 'mediumMempool',
16706
+ 'largeMempool',
15525
16707
  ];
15526
- const MEDIUM_MEMPOOL_ACC_NAME = 'mediumMempool';
15527
- const MEDIUM_MEMPOOL_DISCRIMINATOR = [
15528
- 10,
15529
- 249,
15530
- 58,
15531
- 39,
15532
- 255,
15533
- 231,
15534
- 199,
15535
- 168,
16708
+ const EXECUTING_POOL_DECODER_ACCOUNT_NAMES = [
16709
+ 'tinyExecPool',
16710
+ 'smallExecPool',
16711
+ 'mediumExecPool',
16712
+ 'largeExecPool',
15536
16713
  ];
15537
- const MEDIUM_EXECPOOL_ACC_NAME = 'mediumExecPool';
15538
- const MEDIUM_EXECPOOL_DISCRIMINATOR = [
15539
- 97,
15540
- 117,
15541
- 128,
15542
- 202,
15543
- 213,
15544
- 76,
15545
- 5,
15546
- 163,
15547
- ];
15548
- const LARGE_MEMPOOL_ACC_NAME = 'largeMempool';
15549
- const LARGE_MEMPOOL_DISCRIMINATOR = [
15550
- 16,
15551
- 168,
15552
- 90,
15553
- 235,
15554
- 249,
15555
- 207,
15556
- 73,
15557
- 223,
15558
- ];
15559
- const LARGE_EXECPOOL_ACC_NAME = 'largeExecPool';
15560
- const LARGE_EXECPOOL_DISCRIMINATOR = [
15561
- 147,
15562
- 145,
15563
- 148,
15564
- 170,
15565
- 30,
15566
- 13,
15567
- 43,
15568
- 216,
15569
- ];
15570
- const MEMPOOL_DISCRIMINATOR_MAP = {
15571
- [TINY_MEMPOOL_DISCRIMINATOR.toString()]: TINY_MEMPOOL_ACC_NAME,
15572
- [SMALL_MEMPOOL_DISCRIMINATOR.toString()]: SMALL_MEMPOOL_ACC_NAME,
15573
- [MEDIUM_MEMPOOL_DISCRIMINATOR.toString()]: MEDIUM_MEMPOOL_ACC_NAME,
15574
- [LARGE_MEMPOOL_DISCRIMINATOR.toString()]: LARGE_MEMPOOL_ACC_NAME,
15575
- };
15576
- const EXECPOOL_DISCRIMINATOR_MAP = {
15577
- [TINY_EXECPOOL_DISCRIMINATOR.toString()]: TINY_EXECPOOL_ACC_NAME,
15578
- [SMALL_EXECPOOL_DISCRIMINATOR.toString()]: SMALL_EXECPOOL_ACC_NAME,
15579
- [MEDIUM_EXECPOOL_DISCRIMINATOR.toString()]: MEDIUM_EXECPOOL_ACC_NAME,
15580
- [LARGE_EXECPOOL_DISCRIMINATOR.toString()]: LARGE_EXECPOOL_ACC_NAME,
15581
- };
16714
+ function discriminatorKey(discriminator) {
16715
+ return Buffer.from(discriminator).toString('hex');
16716
+ }
16717
+ // Discriminator bytes are read from the IDL at load time rather than pinned, so the
16718
+ // decoder tracks the program's account layout as the single source of truth; a
16719
+ // missing or renamed tier throws here instead of silently misrouting at runtime.
16720
+ const accountDiscriminatorCoder = new BorshCoder(convertIdlToCamelCase(ARCIUM_IDL)).accounts;
16721
+ function buildPoolAccountMap(accountNames) {
16722
+ return new Map(accountNames.map((name) => [
16723
+ discriminatorKey(accountDiscriminatorCoder.accountDiscriminator(name)),
16724
+ name,
16725
+ ]));
16726
+ }
16727
+ const MEMPOOL_ACCOUNT_BY_DISCRIMINATOR = buildPoolAccountMap(MEMPOOL_DECODER_ACCOUNT_NAMES);
16728
+ const EXECUTING_POOL_ACCOUNT_BY_DISCRIMINATOR = buildPoolAccountMap(EXECUTING_POOL_DECODER_ACCOUNT_NAMES);
16729
+ function getPoolAccountNameByDiscriminator(accountData, accountsByDiscriminator, kind) {
16730
+ if (accountData.length < DISCRIMINATOR_SIZE) {
16731
+ throw new Error(`${kind} account data is shorter than discriminator size`);
16732
+ }
16733
+ const key = discriminatorKey(accountData.subarray(0, DISCRIMINATOR_SIZE));
16734
+ const accountName = accountsByDiscriminator.get(key);
16735
+ if (accountName === undefined) {
16736
+ throw new Error(`Unknown ${kind} account discriminator: ${key}`);
16737
+ }
16738
+ return accountName;
16739
+ }
16740
+ /** @internal */
16741
+ function getMempoolAccountNameByDiscriminator(accountData) {
16742
+ return getPoolAccountNameByDiscriminator(accountData, MEMPOOL_ACCOUNT_BY_DISCRIMINATOR, 'mempool');
16743
+ }
16744
+ /** @internal */
16745
+ function getExecutingPoolAccountNameByDiscriminator(accountData) {
16746
+ return getPoolAccountNameByDiscriminator(accountData, EXECUTING_POOL_ACCOUNT_BY_DISCRIMINATOR, 'executing pool');
16747
+ }
16748
+
16749
+ const MAX_U32 = 0xffffffff;
16750
+ /**
16751
+ * Mirrors the on-chain `init_mxe_part2` recovery-peer bounds before building the instruction.
16752
+ * @internal
16753
+ */
16754
+ function assertValidRecoveryPeers(recoveryPeers) {
16755
+ if (recoveryPeers.length > MAX_RECOVERY_PEERS) {
16756
+ throw new Error(`recoveryPeers must have at most ${MAX_RECOVERY_PEERS} elements (got ${recoveryPeers.length})`);
16757
+ }
16758
+ let nonZeroPeers = 0;
16759
+ for (let index = 0; index < recoveryPeers.length; index += 1) {
16760
+ const peer = recoveryPeers[index];
16761
+ if (!Number.isInteger(peer) || peer < 0 || peer > MAX_U32) {
16762
+ throw new RangeError(`recoveryPeers[${index}] must be an integer in [0, ${MAX_U32}] (got ${peer})`);
16763
+ }
16764
+ if (peer !== 0) {
16765
+ nonZeroPeers += 1;
16766
+ }
16767
+ }
16768
+ if (nonZeroPeers > 0 && nonZeroPeers < MIN_RECOVERY_PEERS) {
16769
+ throw new Error(`recoveryPeers must have 0 or at least ${MIN_RECOVERY_PEERS} non-zero offsets (found ${nonZeroPeers})`);
16770
+ }
16771
+ }
16772
+ /** @internal */
16773
+ function normalizeRecoveryPeers(recoveryPeers) {
16774
+ assertValidRecoveryPeers(recoveryPeers);
16775
+ const paddedRecoveryPeers = [...recoveryPeers];
16776
+ while (paddedRecoveryPeers.length < MAX_RECOVERY_PEERS) {
16777
+ paddedRecoveryPeers.push(0);
16778
+ }
16779
+ return paddedRecoveryPeers;
16780
+ }
16781
+
16782
+ /** @internal */
16783
+ function getRawCircuitAccountCount(rawCircuitByteLength) {
16784
+ if (!Number.isInteger(rawCircuitByteLength) || rawCircuitByteLength < 0) {
16785
+ throw new RangeError(`rawCircuit byte length must be a non-negative integer (got ${rawCircuitByteLength})`);
16786
+ }
16787
+ const accountCount = Math.ceil(rawCircuitByteLength / MAX_RAW_CIRCUIT_BYTES_PER_ACC);
16788
+ if (accountCount > MAX_RAW_CIRCUIT_ACCOUNTS) {
16789
+ throw new RangeError(`Raw circuit is too large for on-chain upload: requires ${accountCount} raw circuit accounts, maximum is ${MAX_RAW_CIRCUIT_ACCOUNTS}`);
16790
+ }
16791
+ return accountCount;
16792
+ }
16793
+ /** @internal */
16794
+ function assertRawCircuitUploadLength(rawCircuitByteLength, declaredCircuitByteLength, circuitName) {
16795
+ if (!Number.isInteger(rawCircuitByteLength) || rawCircuitByteLength < 0) {
16796
+ throw new RangeError(`rawCircuit byte length must be a non-negative integer (got ${rawCircuitByteLength})`);
16797
+ }
16798
+ if (!Number.isInteger(declaredCircuitByteLength) || declaredCircuitByteLength <= 0) {
16799
+ throw new RangeError(`Declared circuit byte length for ${circuitName} must be a positive integer (got ${declaredCircuitByteLength})`);
16800
+ }
16801
+ if (rawCircuitByteLength !== declaredCircuitByteLength) {
16802
+ throw new RangeError(`Raw circuit byte length for ${circuitName} must match the computation definition: got ${rawCircuitByteLength}, expected ${declaredCircuitByteLength}`);
16803
+ }
16804
+ }
16805
+
16806
+ const { BN } = anchor__default;
15582
16807
  /**
15583
16808
  * Fetch and decode the mempool account info for any mempool account size.
15584
16809
  * @param provider - Anchor provider to use for fetching accounts.
@@ -15587,15 +16812,8 @@ const EXECPOOL_DISCRIMINATOR_MAP = {
15587
16812
  * @throws Error if the account cannot be fetched or the discriminator is unknown.
15588
16813
  */
15589
16814
  async function getMempoolAccInfo(provider, mempoolAccPubkey) {
15590
- const accData = await provider.connection.getAccountInfo(mempoolAccPubkey);
15591
- if (accData === null) {
15592
- throw new Error(`Failed to fetch mempool account ${mempoolAccPubkey.toBase58()}`);
15593
- }
15594
- const discriminator = Array.from(accData.data.subarray(0, DISCRIMINATOR_SIZE)).toString();
15595
- const accName = MEMPOOL_DISCRIMINATOR_MAP[discriminator];
15596
- if (accName === undefined) {
15597
- throw new Error(`Unknown mempool account discriminator: ${discriminator}`);
15598
- }
16815
+ const accData = requireAccountInfo(await provider.connection.getAccountInfo(mempoolAccPubkey), mempoolAccPubkey, 'mempool');
16816
+ const accName = getMempoolAccountNameByDiscriminator(accData.data);
15599
16817
  const program = getArciumProgram(provider);
15600
16818
  return program.coder.accounts.decode(accName, accData.data);
15601
16819
  }
@@ -15607,18 +16825,17 @@ async function getMempoolAccInfo(provider, mempoolAccPubkey) {
15607
16825
  * @throws Error if the account cannot be fetched or the discriminator is unknown.
15608
16826
  */
15609
16827
  async function getExecutingPoolAccInfo(provider, executingPoolAccPubkey) {
15610
- const accData = await provider.connection.getAccountInfo(executingPoolAccPubkey);
15611
- if (accData === null) {
15612
- throw new Error(`Failed to fetch executing pool account ${executingPoolAccPubkey.toBase58()}`);
15613
- }
15614
- const discriminator = Array.from(accData.data.subarray(0, DISCRIMINATOR_SIZE)).toString();
15615
- const accName = EXECPOOL_DISCRIMINATOR_MAP[discriminator];
15616
- if (accName === undefined) {
15617
- throw new Error(`Unknown executing pool account discriminator: ${discriminator}`);
15618
- }
16828
+ const accData = requireAccountInfo(await provider.connection.getAccountInfo(executingPoolAccPubkey), executingPoolAccPubkey, 'executing pool');
16829
+ const accName = getExecutingPoolAccountNameByDiscriminator(accData.data);
15619
16830
  const program = getArciumProgram(provider);
15620
16831
  return program.coder.accounts.decode(accName, accData.data);
15621
16832
  }
16833
+ function requireAccountInfo(accountInfo, pubkey, label) {
16834
+ if (accountInfo === null) {
16835
+ throw new Error(`Failed to fetch ${label} account ${pubkey.toBase58()}`);
16836
+ }
16837
+ return accountInfo;
16838
+ }
15622
16839
  /**
15623
16840
  * Return all computation references in the mempool for a given account.
15624
16841
  * Only non-stake computations are included.
@@ -15662,15 +16879,15 @@ async function getComputationsInMempool(arciumProgram, address) {
15662
16879
  async function getMempoolPriorityFeeStats(arciumProgram, mempoolAddress) {
15663
16880
  const refs = await getComputationsInMempool(arciumProgram, mempoolAddress);
15664
16881
  if (refs.length === 0) {
15665
- const zero = new anchor.BN(0);
16882
+ const zero = new BN(0);
15666
16883
  return { mean: zero, median: zero, min: zero, max: zero, count: 0 };
15667
16884
  }
15668
16885
  const fees = refs.map(ref => ref.priorityFee).sort((a, b) => a.cmp(b));
15669
- const sum = fees.reduce((acc, fee) => acc.add(fee), new anchor.BN(0));
15670
- const mean = sum.div(new anchor.BN(fees.length));
16886
+ const sum = fees.reduce((acc, fee) => acc.add(fee), new BN(0));
16887
+ const mean = sum.div(new BN(fees.length));
15671
16888
  const mid = Math.floor(fees.length / 2);
15672
16889
  const median = fees.length % 2 === 0
15673
- ? fees[mid - 1].add(fees[mid]).div(new anchor.BN(2))
16890
+ ? fees[mid - 1].add(fees[mid]).div(new BN(2))
15674
16891
  : fees[mid];
15675
16892
  return {
15676
16893
  mean,
@@ -15743,11 +16960,12 @@ function getCircuitState(circuitSource) {
15743
16960
  * @param mxeProgramId - Public key of the MXE program.
15744
16961
  * @param rawCircuit - Raw circuit data as a Uint8Array.
15745
16962
  * @param logging - Whether to log progress (default: true).
15746
- * @param chunkSize - Number of upload transactions to send in parallel (default: 500).
16963
+ * @param chunkSize - Number of upload transactions to send in parallel. Defaults to
16964
+ * {@link DEFAULT_UPLOAD_TX_BATCH_SIZE}.
15747
16965
  * @param confirmOptions - Transaction confirmation options.
15748
16966
  * @returns Array of transaction signatures for all upload and finalize transactions.
15749
16967
  */
15750
- async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, logging = true, chunkSize = 500, confirmOptions) {
16968
+ async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, logging = true, chunkSize = DEFAULT_UPLOAD_TX_BATCH_SIZE, confirmOptions) {
15751
16969
  const compDefAccInfo = getCompDefAccInfo(circuitName, mxeProgramId);
15752
16970
  const program = getArciumProgram(provider);
15753
16971
  const compDefAcc = await program.account.computationDefinitionAccount.fetch(compDefAccInfo.pubkey);
@@ -15757,12 +16975,12 @@ async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, lo
15757
16975
  optionalLog(logging, `Circuit ${circuitName} skipped: ${state}`);
15758
16976
  return [];
15759
16977
  }
15760
- // 9 = 8-byte discriminator + 1-byte bump for ComputationDefinitionRaw account
15761
- const numAccs = Math.ceil(rawCircuit.length / (MAX_ACCOUNT_SIZE - 9));
16978
+ assertRawCircuitUploadLength(rawCircuit.length, compDefAcc.definition.circuitLen, circuitName);
16979
+ const numAccs = getRawCircuitAccountCount(rawCircuit.length);
15762
16980
  const sigs = [];
15763
16981
  const uploadPromises = [];
15764
16982
  for (let i = 0; i < numAccs; i++) {
15765
- uploadPromises.push(uploadToCircuitAcc(provider, program, rawCircuit.subarray(i * (MAX_ACCOUNT_SIZE - 9), (i + 1) * (MAX_ACCOUNT_SIZE - 9)), i, compDefAccInfo, mxeProgramId, logging, chunkSize, confirmOptions));
16983
+ uploadPromises.push(uploadToCircuitAcc(provider, program, rawCircuit.subarray(i * MAX_RAW_CIRCUIT_BYTES_PER_ACC, (i + 1) * MAX_RAW_CIRCUIT_BYTES_PER_ACC), i, compDefAccInfo, mxeProgramId, logging, chunkSize, confirmOptions));
15766
16984
  }
15767
16985
  sigs.push(...(await Promise.all(uploadPromises)).flat());
15768
16986
  const finalizeCompDefTx = await buildFinalizeCompDefTx(provider, compDefAccInfo.offset, mxeProgramId);
@@ -15778,8 +16996,6 @@ async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, lo
15778
16996
  */
15779
16997
  async function buildFinalizeCompDefTx(provider, compDefOffset, mxeProgramId) {
15780
16998
  const program = getArciumProgram(provider);
15781
- const compDefOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15782
- compDefOffsetBuffer.writeUInt32LE(compDefOffset, 0);
15783
16999
  return program.methods
15784
17000
  .finalizeComputationDefinition(compDefOffset, mxeProgramId)
15785
17001
  .accounts({
@@ -15787,12 +17003,11 @@ async function buildFinalizeCompDefTx(provider, compDefOffset, mxeProgramId) {
15787
17003
  })
15788
17004
  .transaction();
15789
17005
  }
15790
- async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitIndex, compDefAccInfo, mxeProgramId, shouldLog = true, chunkSize = 500, confirmOptions) {
17006
+ async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitIndex, compDefAccInfo, mxeProgramId, shouldLog = true, chunkSize = DEFAULT_UPLOAD_TX_BATCH_SIZE, confirmOptions) {
15791
17007
  const rawCircuitPda = getRawCircuitAccAddress(compDefAccInfo.pubkey, rawCircuitIndex);
15792
17008
  const existingAcc = await provider.connection.getAccountInfo(rawCircuitPda);
15793
17009
  // Skip entirely if account exists with correct size (pre-seeded at genesis or already uploaded)
15794
- // Account layout: 8-byte discriminator + 1-byte bump + circuit data
15795
- const requiredAccountSize = rawCircuitPart.length + 9;
17010
+ const requiredAccountSize = rawCircuitPart.length + RAW_CIRCUIT_ACCOUNT_HEADER_SIZE;
15796
17011
  if (existingAcc !== null && existingAcc.data.length >= requiredAccountSize) {
15797
17012
  optionalLog(shouldLog, `Raw circuit acc ${rawCircuitIndex} already exists with sufficient size, skipping`);
15798
17013
  return [];
@@ -15926,18 +17141,8 @@ function getArciumProgram(provider) {
15926
17141
  */
15927
17142
  function getCompDefAccInfo(circuitName, mxeProgramId) {
15928
17143
  const offset = getCompDefAccOffset(circuitName);
15929
- const pda = getCompDefAccPDA(getArciumProgramId(), mxeProgramId, offset);
15930
- return { pubkey: pda, offset: Buffer.from(offset).readUInt32LE(0) };
15931
- }
15932
- /**
15933
- * Return the PDA for a computation definition account, given the program ID, MXE program ID, and offset.
15934
- * @param arciumProgramId - Public key of the Arcium program.
15935
- * @param mxeProgramId - Public key of the MXE program.
15936
- * @param offset - Offset as a Uint8Array.
15937
- * @returns PDA for the computation definition account.
15938
- */
15939
- function getCompDefAccPDA(arciumProgramId, mxeProgramId, offset) {
15940
- return anchor.web3.PublicKey.findProgramAddressSync([Buffer.from(COMP_DEF_ACC_SEED, 'utf-8'), mxeProgramId.toBuffer(), offset], arciumProgramId)[0];
17144
+ const offsetNumber = Buffer.from(offset).readUInt32LE(0);
17145
+ return { pubkey: getCompDefAccAddress(mxeProgramId, offsetNumber), offset: offsetNumber };
15941
17146
  }
15942
17147
  /**
15943
17148
  * Initialize an MXE (part 1). Due to Solana's 10KB per-instruction allocation limit,
@@ -15945,13 +17150,15 @@ function getCompDefAccPDA(arciumProgramId, mxeProgramId, offset) {
15945
17150
  * Call initMxePart2 afterwards to finish allocation and add keygen to mempool.
15946
17151
  * @param provider - Anchor provider to use for transactions.
15947
17152
  * @param mxeProgramId - Public key to use as the MXE program ID.
17153
+ * @param recoveryPeers - Array of 100 node offsets for recovery peers (0 for unused slots).
15948
17154
  * @param confirmOptions - Transaction confirmation options.
15949
17155
  * @returns Transaction signature.
15950
17156
  */
15951
- async function initMxePart1(provider, mxeProgramId, confirmOptions) {
17157
+ async function initMxePart1(provider, mxeProgramId, recoveryPeers, confirmOptions) {
15952
17158
  const program = getArciumProgram(provider);
17159
+ const paddedRecoveryPeers = normalizeRecoveryPeers(recoveryPeers);
15953
17160
  const tx = await program.methods
15954
- .initMxePart1()
17161
+ .initMxePart1(paddedRecoveryPeers)
15955
17162
  .accountsPartial({
15956
17163
  signer: provider.publicKey,
15957
17164
  mxeProgram: mxeProgramId,
@@ -15966,9 +17173,12 @@ async function initMxePart1(provider, mxeProgramId, confirmOptions) {
15966
17173
  * @param provider - Anchor provider to use for transactions.
15967
17174
  * @param clusterOffset - Cluster offset to associate with the MXE.
15968
17175
  * @param mxeProgramId - Public key to use as the MXE program ID.
15969
- * @param recoveryPeers - Array of 100 node offsets for recovery peers (0 for unused slots).
15970
17176
  * @param keygenOffset - Computation offset for the keygen computation.
15971
17177
  * @param keyRecoveryInitOffset - Computation offset for the key_recovery_init computation.
17178
+ * @param recoveryPeers - Recovery peer node offsets. Slots set to 0 are treated as unused.
17179
+ * The non-zero count must be either 0 (recovery disabled) or at least
17180
+ * `MIN_RECOVERY_PEERS` (4). The array is padded with zeros up to
17181
+ * `MAX_RECOVERY_PEERS` (100); passing more than that throws.
15972
17182
  * @param lutOffset - Lookup table offset for the MXE's address lookup table.
15973
17183
  * @param mxeAuthority - Optional authority for the MXE (defaults to provider.publicKey).
15974
17184
  * @param confirmOptions - Transaction confirmation options.
@@ -15976,16 +17186,8 @@ async function initMxePart1(provider, mxeProgramId, confirmOptions) {
15976
17186
  */
15977
17187
  async function initMxePart2(provider, clusterOffset, mxeProgramId, keygenOffset, keyRecoveryInitOffset, recoveryPeers, lutOffset, mxeAuthority, confirmOptions) {
15978
17188
  const program = getArciumProgram(provider);
15979
- // Ensure recoveryPeers has exactly 100 elements
15980
- const paddedRecoveryPeers = [...recoveryPeers];
15981
- while (paddedRecoveryPeers.length < 100) {
15982
- paddedRecoveryPeers.push(0);
15983
- }
15984
- if (paddedRecoveryPeers.length > 100) {
15985
- throw new Error('recoveryPeers must have at most 100 elements');
15986
- }
15987
17189
  const tx = await program.methods
15988
- .initMxePart2(clusterOffset, mxeProgramId, paddedRecoveryPeers, keygenOffset, keyRecoveryInitOffset, lutOffset)
17190
+ .initMxePart2(clusterOffset, keygenOffset, keyRecoveryInitOffset, lutOffset)
15989
17191
  .accountsPartial({
15990
17192
  signer: provider.publicKey,
15991
17193
  mxeProgram: mxeProgramId,
@@ -15996,6 +17198,14 @@ async function initMxePart2(provider, clusterOffset, mxeProgramId, keygenOffset,
15996
17198
  .transaction();
15997
17199
  return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
15998
17200
  }
17201
+ /**
17202
+ * Reclaim the rent locked in a finished computation account.
17203
+ * @param provider - Anchor provider to use for transactions.
17204
+ * @param clusterOffset - Offset of the cluster that ran the computation.
17205
+ * @param computationOffset - Offset of the computation whose rent is being claimed.
17206
+ * @param confirmOptions - Transaction confirmation options.
17207
+ * @returns Transaction signature.
17208
+ */
15999
17209
  async function claimComputationRent(provider, clusterOffset, computationOffset, confirmOptions) {
16000
17210
  const program = getArciumProgram(provider);
16001
17211
  const tx = await program.methods
@@ -16112,4 +17322,4 @@ async function awaitComputationFinalization(provider, computationOffset, mxeProg
16112
17322
  : new Error(timeoutMsg);
16113
17323
  }
16114
17324
 
16115
- export { ARCIUM_ADDR, ARCIUM_IDL, Aes128Cipher, Aes192Cipher, Aes256Cipher, ArcisModule, ArcisType, ArcisValueField, CSplRescueCipher, CURVE25519_BASE_FIELD, CURVE25519_SCALAR_FIELD, CURVE25519_SCALAR_FIELD_MODULUS, IntegerInfo, Matrix, RescueCipher, RescueDesc, RescuePrimeHash, arcisEd25519, awaitComputationFinalization, buildFinalizeCompDefTx, claimComputationRent, createPacker, deserializeLE, generateRandomFieldElem, getArciumAccountBaseSeed, getArciumEnv, getArciumProgram, getArciumProgramId, getArxNodeAccAddress, getCircuitState, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getCompDefAccOffset, getComputationAccAddress, getComputationsInMempool, getExecutingPoolAccAddress, getExecutingPoolAccInfo, getFeePoolAccAddress, getLookupTableAddress, getMXEAccAddress, getMXEArcisEd25519VerifyingKey, getMXEPublicKey, getMempoolAccAddress, getMempoolAccInfo, getMempoolPriorityFeeStats, getMxeRecoveryAccAddress, getRawCircuitAccAddress, getRecoveryClusterAccAddress, initMxePart1, initMxePart2, isNullRef, positiveModulo, randMatrix, serializeLE, sha256, toVec, uploadCircuit };
17325
+ export { ARCIUM_ADDR, ARCIUM_IDL, Aes128Cipher, Aes192Cipher, Aes256Cipher, ArcisModule, ArcisType, ArcisValueField, CSplRescueCipher, CURVE25519_BASE_FIELD, CURVE25519_SCALAR_FIELD, CURVE25519_SCALAR_FIELD_MODULUS, IntegerInfo, Matrix, RescueCipher, RescueDesc, RescuePrimeHash, arcisEd25519, awaitComputationFinalization, buildFinalizeCompDefTx, claimComputationRent, createPacker, deserializeLE, generateRandomFieldElem, getArciumAccountBaseSeed, getArciumEnv, getArciumProgram, getArciumProgramId, getArciumSignerAccAddress, getArxNodeAccAddress, getCircuitState, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getCompDefAccOffset, getComputationAccAddress, getComputationsInMempool, getExecutingPoolAccAddress, getExecutingPoolAccInfo, getFailureClaimAccAddress, getFeePoolAccAddress, getLookupTableAddress, getMXEAccAddress, getMXEArcisEd25519VerifyingKey, getMXEPublicKey, getMempoolAccAddress, getMempoolAccInfo, getMempoolPriorityFeeStats, getMxeRecoveryAccAddress, getOperatorAccAddress, getRawCircuitAccAddress, getRecoveryClusterAccAddress, getRecoveryPeerAccAddress, initMxePart1, initMxePart2, isNullRef, positiveModulo, randMatrix, serializeLE, sha256, toVec, uploadCircuit };