@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.cjs CHANGED
@@ -1883,7 +1883,7 @@ function createPacker(fields, typeName = 'Packer') {
1883
1883
  var address = "Arcj82pX7HxYKLR92qvgZUAd7vGS1k4hQvAFcPATFdEQ";
1884
1884
  var metadata = {
1885
1885
  name: "arcium",
1886
- version: "0.10.4",
1886
+ version: "0.11.1",
1887
1887
  spec: "0.1.0",
1888
1888
  description: "The Arcium program"
1889
1889
  };
@@ -2174,6 +2174,84 @@ var instructions = [
2174
2174
  }
2175
2175
  ]
2176
2176
  },
2177
+ {
2178
+ name: "bind_recovery_peer_migration",
2179
+ discriminator: [
2180
+ 30,
2181
+ 148,
2182
+ 4,
2183
+ 206,
2184
+ 139,
2185
+ 2,
2186
+ 55,
2187
+ 156
2188
+ ],
2189
+ accounts: [
2190
+ {
2191
+ name: "authority",
2192
+ docs: [
2193
+ "The recovery peer's `authority` — same dual role as in `MigrateArxNode`: it authorizes the",
2194
+ "bind and is the owner of `primary_stake_account`."
2195
+ ],
2196
+ signer: true
2197
+ },
2198
+ {
2199
+ name: "recovery_peer_account",
2200
+ docs: [
2201
+ "Must already be layout-migrated (`migrate_recovery_peer`) so the appended",
2202
+ "`primary_stake_account` field exists; otherwise the zero-copy load fails on the short",
2203
+ "account. Bundle `migrate_recovery_peer` ahead of this instruction in the same transaction."
2204
+ ],
2205
+ writable: true,
2206
+ pda: {
2207
+ seeds: [
2208
+ {
2209
+ kind: "const",
2210
+ value: [
2211
+ 82,
2212
+ 101,
2213
+ 99,
2214
+ 111,
2215
+ 118,
2216
+ 101,
2217
+ 114,
2218
+ 121,
2219
+ 80,
2220
+ 101,
2221
+ 101,
2222
+ 114,
2223
+ 65,
2224
+ 99,
2225
+ 99,
2226
+ 111,
2227
+ 117,
2228
+ 110,
2229
+ 116
2230
+ ]
2231
+ },
2232
+ {
2233
+ kind: "arg",
2234
+ path: "peer_offset"
2235
+ }
2236
+ ]
2237
+ }
2238
+ },
2239
+ {
2240
+ name: "primary_stake_account",
2241
+ writable: true
2242
+ },
2243
+ {
2244
+ name: "arcium_staking_program",
2245
+ address: "ArcStnN9zZZVB5WjgPhLHjYpY7Gb29mzb96ySsb1kxgq"
2246
+ }
2247
+ ],
2248
+ args: [
2249
+ {
2250
+ name: "peer_offset",
2251
+ type: "u32"
2252
+ }
2253
+ ]
2254
+ },
2177
2255
  {
2178
2256
  name: "bump_epoch_cluster",
2179
2257
  discriminator: [
@@ -2287,6 +2365,7 @@ var instructions = [
2287
2365
  },
2288
2366
  {
2289
2367
  name: "mxe",
2368
+ writable: true,
2290
2369
  pda: {
2291
2370
  seeds: [
2292
2371
  {
@@ -2824,6 +2903,7 @@ var instructions = [
2824
2903
  },
2825
2904
  {
2826
2905
  name: "mxe",
2906
+ writable: true,
2827
2907
  pda: {
2828
2908
  seeds: [
2829
2909
  {
@@ -3153,13 +3233,88 @@ var instructions = [
3153
3233
  ],
3154
3234
  accounts: [
3155
3235
  {
3156
- name: "node_authority",
3236
+ name: "staking_pool_signer",
3237
+ docs: [
3238
+ "The `arcium_staking::state::StakingPoolAccount` PDA, signing via CPI. Also the destination",
3239
+ "for the settled lamports (so the staking program immediately owns them for later",
3240
+ "proportional distribution). The `seeds`/`bump` constraint verifies it's the canonical pool",
3241
+ "PDA under `ARCIUM_STAKING_ID` (so only the staking program can call this); `Signer`",
3242
+ "enforces it actually signed."
3243
+ ],
3157
3244
  writable: true,
3158
- signer: true
3245
+ signer: true,
3246
+ pda: {
3247
+ seeds: [
3248
+ {
3249
+ kind: "const",
3250
+ value: [
3251
+ 83,
3252
+ 116,
3253
+ 97,
3254
+ 107,
3255
+ 105,
3256
+ 110,
3257
+ 103,
3258
+ 80,
3259
+ 111,
3260
+ 111,
3261
+ 108,
3262
+ 65,
3263
+ 99,
3264
+ 99,
3265
+ 111,
3266
+ 117,
3267
+ 110,
3268
+ 116
3269
+ ]
3270
+ }
3271
+ ],
3272
+ program: {
3273
+ kind: "const",
3274
+ value: [
3275
+ 146,
3276
+ 110,
3277
+ 184,
3278
+ 172,
3279
+ 179,
3280
+ 131,
3281
+ 118,
3282
+ 35,
3283
+ 207,
3284
+ 122,
3285
+ 30,
3286
+ 190,
3287
+ 228,
3288
+ 134,
3289
+ 232,
3290
+ 140,
3291
+ 222,
3292
+ 89,
3293
+ 53,
3294
+ 150,
3295
+ 174,
3296
+ 187,
3297
+ 151,
3298
+ 58,
3299
+ 208,
3300
+ 108,
3301
+ 237,
3302
+ 119,
3303
+ 97,
3304
+ 204,
3305
+ 184,
3306
+ 186
3307
+ ]
3308
+ }
3309
+ }
3159
3310
  },
3160
3311
  {
3161
- name: "recipient",
3162
- writable: true
3312
+ name: "primary_stake_account",
3313
+ docs: [
3314
+ "The `PrimaryStakingAccount` bound to this node. Passed so the handler can verify",
3315
+ "`node.primary_staking_account == primary_stake_account.key()` — i.e. the staking account",
3316
+ "that's about to claim the fees is the one this node was initialized with."
3317
+ ]
3163
3318
  },
3164
3319
  {
3165
3320
  name: "cluster",
@@ -3238,7 +3393,197 @@ var instructions = [
3238
3393
  name: "node_offset",
3239
3394
  type: "u32"
3240
3395
  }
3241
- ]
3396
+ ],
3397
+ returns: "u64"
3398
+ },
3399
+ {
3400
+ name: "claim_recovery_peer_fees",
3401
+ discriminator: [
3402
+ 132,
3403
+ 120,
3404
+ 187,
3405
+ 164,
3406
+ 106,
3407
+ 57,
3408
+ 202,
3409
+ 8
3410
+ ],
3411
+ accounts: [
3412
+ {
3413
+ name: "staking_pool_signer",
3414
+ docs: [
3415
+ "`arcium_staking::StakingPoolAccount` PDA, signing via CPI and receiving the drained",
3416
+ "lamports. The `seeds`/`bump` constraint verifies it's the canonical pool PDA under",
3417
+ "`ARCIUM_STAKING_ID`; `Signer` enforces `is_signer`."
3418
+ ],
3419
+ writable: true,
3420
+ signer: true,
3421
+ pda: {
3422
+ seeds: [
3423
+ {
3424
+ kind: "const",
3425
+ value: [
3426
+ 83,
3427
+ 116,
3428
+ 97,
3429
+ 107,
3430
+ 105,
3431
+ 110,
3432
+ 103,
3433
+ 80,
3434
+ 111,
3435
+ 111,
3436
+ 108,
3437
+ 65,
3438
+ 99,
3439
+ 99,
3440
+ 111,
3441
+ 117,
3442
+ 110,
3443
+ 116
3444
+ ]
3445
+ }
3446
+ ],
3447
+ program: {
3448
+ kind: "const",
3449
+ value: [
3450
+ 146,
3451
+ 110,
3452
+ 184,
3453
+ 172,
3454
+ 179,
3455
+ 131,
3456
+ 118,
3457
+ 35,
3458
+ 207,
3459
+ 122,
3460
+ 30,
3461
+ 190,
3462
+ 228,
3463
+ 134,
3464
+ 232,
3465
+ 140,
3466
+ 222,
3467
+ 89,
3468
+ 53,
3469
+ 150,
3470
+ 174,
3471
+ 187,
3472
+ 151,
3473
+ 58,
3474
+ 208,
3475
+ 108,
3476
+ 237,
3477
+ 119,
3478
+ 97,
3479
+ 204,
3480
+ 184,
3481
+ 186
3482
+ ]
3483
+ }
3484
+ }
3485
+ },
3486
+ {
3487
+ name: "primary_stake_account",
3488
+ docs: [
3489
+ "`PrimaryStakingAccount` the claiming peer is bound to. Only the key is compared",
3490
+ "against `recovery_peer.primary_stake_account`; the staking program owns the struct."
3491
+ ]
3492
+ },
3493
+ {
3494
+ name: "recovery_peer",
3495
+ pda: {
3496
+ seeds: [
3497
+ {
3498
+ kind: "const",
3499
+ value: [
3500
+ 82,
3501
+ 101,
3502
+ 99,
3503
+ 111,
3504
+ 118,
3505
+ 101,
3506
+ 114,
3507
+ 121,
3508
+ 80,
3509
+ 101,
3510
+ 101,
3511
+ 114,
3512
+ 65,
3513
+ 99,
3514
+ 99,
3515
+ 111,
3516
+ 117,
3517
+ 110,
3518
+ 116
3519
+ ]
3520
+ },
3521
+ {
3522
+ kind: "arg",
3523
+ path: "peer_offset"
3524
+ }
3525
+ ]
3526
+ }
3527
+ },
3528
+ {
3529
+ name: "mxe",
3530
+ writable: true,
3531
+ pda: {
3532
+ seeds: [
3533
+ {
3534
+ kind: "const",
3535
+ value: [
3536
+ 77,
3537
+ 88,
3538
+ 69,
3539
+ 65,
3540
+ 99,
3541
+ 99,
3542
+ 111,
3543
+ 117,
3544
+ 110,
3545
+ 116
3546
+ ]
3547
+ },
3548
+ {
3549
+ kind: "arg",
3550
+ path: "mxe_program"
3551
+ }
3552
+ ]
3553
+ }
3554
+ },
3555
+ {
3556
+ name: "pool",
3557
+ writable: true,
3558
+ pda: {
3559
+ seeds: [
3560
+ {
3561
+ kind: "const",
3562
+ value: [
3563
+ 70,
3564
+ 101,
3565
+ 101,
3566
+ 80,
3567
+ 111,
3568
+ 111,
3569
+ 108
3570
+ ]
3571
+ }
3572
+ ]
3573
+ }
3574
+ }
3575
+ ],
3576
+ args: [
3577
+ {
3578
+ name: "mxe_program",
3579
+ type: "pubkey"
3580
+ },
3581
+ {
3582
+ name: "peer_offset",
3583
+ type: "u32"
3584
+ }
3585
+ ],
3586
+ returns: "u64"
3242
3587
  },
3243
3588
  {
3244
3589
  name: "close_computation_definition",
@@ -4545,6 +4890,14 @@ var instructions = [
4545
4890
  }
4546
4891
  ],
4547
4892
  args: [
4893
+ {
4894
+ name: "_selector",
4895
+ type: {
4896
+ defined: {
4897
+ name: "LeaderSelector"
4898
+ }
4899
+ }
4900
+ }
4548
4901
  ]
4549
4902
  },
4550
4903
  {
@@ -6156,6 +6509,31 @@ var instructions = [
6156
6509
  ]
6157
6510
  }
6158
6511
  },
6512
+ {
6513
+ name: "primary_stake_account",
6514
+ docs: [
6515
+ "The `PrimaryStakingAccount` (owned by the `arcium_staking` program) that this node will be",
6516
+ "bound to for the rest of its life. Reward settlement requires this linkage: fees accrued",
6517
+ "under this node can only be drained via a CPI signed by the staking program's pool PDA",
6518
+ "after matching on this key.",
6519
+ "the staking program's responsibility — if the staker binds garbage they lock themselves",
6520
+ "out of rewards, which is their own problem."
6521
+ ],
6522
+ writable: true
6523
+ },
6524
+ {
6525
+ name: "staker",
6526
+ docs: [
6527
+ "Authority of `primary_stake_account`. Required as a second signer so we can CPI into",
6528
+ "`arcium_staking::bind_primary_stake` and commit the stake to this node. The staking",
6529
+ "program re-derives the stake PDA from this key and rejects the call if it mismatches."
6530
+ ],
6531
+ signer: true
6532
+ },
6533
+ {
6534
+ name: "arcium_staking_program",
6535
+ address: "ArcStnN9zZZVB5WjgPhLHjYpY7Gb29mzb96ySsb1kxgq"
6536
+ },
6159
6537
  {
6160
6538
  name: "system_program",
6161
6539
  address: "11111111111111111111111111111111"
@@ -7023,6 +7401,15 @@ var instructions = [
7023
7401
  }
7024
7402
  ],
7025
7403
  args: [
7404
+ {
7405
+ name: "recovery_peers",
7406
+ type: {
7407
+ array: [
7408
+ "u32",
7409
+ 100
7410
+ ]
7411
+ }
7412
+ }
7026
7413
  ]
7027
7414
  },
7028
7415
  {
@@ -7137,8 +7524,8 @@ var instructions = [
7137
7524
  ]
7138
7525
  },
7139
7526
  {
7140
- kind: "arg",
7141
- path: "_mxe_program"
7527
+ kind: "account",
7528
+ path: "mxe_program"
7142
7529
  }
7143
7530
  ]
7144
7531
  }
@@ -7438,6 +7825,17 @@ var instructions = [
7438
7825
  ]
7439
7826
  }
7440
7827
  },
7828
+ {
7829
+ name: "instructions_sysvar",
7830
+ docs: [
7831
+ "Instructions sysvar — used in the handler to verify the **next** instruction in this",
7832
+ "transaction is `arcium_staking::init_mxe_recovery_stake_state` with the same",
7833
+ "`mxe_program`. This mirrors the reverse check on the staking side and is what",
7834
+ "guarantees that every MXE is created alongside its recovery stake state (replacement",
7835
+ "for the CPI we couldn't do because of the 4KB stack limit on `try_accounts`)."
7836
+ ],
7837
+ address: "Sysvar1nstructions1111111111111111111111111"
7838
+ },
7441
7839
  {
7442
7840
  name: "system_program",
7443
7841
  address: "11111111111111111111111111111111"
@@ -7448,19 +7846,6 @@ var instructions = [
7448
7846
  name: "cluster_offset",
7449
7847
  type: "u32"
7450
7848
  },
7451
- {
7452
- name: "mxe_program",
7453
- type: "pubkey"
7454
- },
7455
- {
7456
- name: "recovery_peers",
7457
- type: {
7458
- array: [
7459
- "u32",
7460
- 100
7461
- ]
7462
- }
7463
- },
7464
7849
  {
7465
7850
  name: "keygen_offset",
7466
7851
  type: "u64"
@@ -7918,6 +8303,31 @@ var instructions = [
7918
8303
  ]
7919
8304
  }
7920
8305
  },
8306
+ {
8307
+ name: "primary_stake_account",
8308
+ docs: [
8309
+ "The `PrimaryStakingAccount` (owned by `arcium_staking`) that the recovery peer is",
8310
+ "binding itself to. Mirrors the stake-first requirement on `InitArxNode`: every",
8311
+ "recovery peer has to point at a real staking account so we have someone to slash",
8312
+ "(or dock rewards from) if the peer misbehaves. Full account-structure validation",
8313
+ "is the staking program's job — here we just make sure the account is owned by it.",
8314
+ "point at any primary stake account they have authority over."
8315
+ ],
8316
+ writable: true
8317
+ },
8318
+ {
8319
+ name: "staker",
8320
+ docs: [
8321
+ "Authority of `primary_stake_account`. Required as a second signer so we can CPI into",
8322
+ "`arcium_staking::bind_primary_stake` and commit the stake to this recovery peer. The",
8323
+ "staking program re-derives the stake PDA from this key and rejects on mismatch."
8324
+ ],
8325
+ signer: true
8326
+ },
8327
+ {
8328
+ name: "arcium_staking_program",
8329
+ address: "ArcStnN9zZZVB5WjgPhLHjYpY7Gb29mzb96ySsb1kxgq"
8330
+ },
7921
8331
  {
7922
8332
  name: "system_program",
7923
8333
  address: "11111111111111111111111111111111"
@@ -8054,6 +8464,171 @@ var instructions = [
8054
8464
  }
8055
8465
  ]
8056
8466
  },
8467
+ {
8468
+ name: "migrate_arx_node",
8469
+ discriminator: [
8470
+ 26,
8471
+ 223,
8472
+ 103,
8473
+ 52,
8474
+ 241,
8475
+ 117,
8476
+ 229,
8477
+ 143
8478
+ ],
8479
+ accounts: [
8480
+ {
8481
+ name: "authority",
8482
+ docs: [
8483
+ "The node's `config.authority`, which both *authorizes* the bind (only the node's own admin",
8484
+ "may link a stake account to it — otherwise anyone could divert a node's rewards to their",
8485
+ "own stake) and doubles as the `staker` (owner of `primary_stake_account`) for the CPI."
8486
+ ],
8487
+ signer: true
8488
+ },
8489
+ {
8490
+ name: "arx_node_acc",
8491
+ writable: true,
8492
+ pda: {
8493
+ seeds: [
8494
+ {
8495
+ kind: "const",
8496
+ value: [
8497
+ 65,
8498
+ 114,
8499
+ 120,
8500
+ 78,
8501
+ 111,
8502
+ 100,
8503
+ 101
8504
+ ]
8505
+ },
8506
+ {
8507
+ kind: "arg",
8508
+ path: "node_offset"
8509
+ }
8510
+ ]
8511
+ }
8512
+ },
8513
+ {
8514
+ name: "primary_stake_account",
8515
+ docs: [
8516
+ "The `PrimaryStakingAccount` (created beforehand via",
8517
+ "`arcium_staking::add_primary_stake_to_legacy_acc`) to bind. Owner-checked here; the staking",
8518
+ "program re-derives `[SEED, authority]` and rejects a mismatch during the bind CPI."
8519
+ ],
8520
+ writable: true
8521
+ },
8522
+ {
8523
+ name: "arcium_staking_program",
8524
+ address: "ArcStnN9zZZVB5WjgPhLHjYpY7Gb29mzb96ySsb1kxgq"
8525
+ }
8526
+ ],
8527
+ args: [
8528
+ {
8529
+ name: "node_offset",
8530
+ type: "u32"
8531
+ }
8532
+ ]
8533
+ },
8534
+ {
8535
+ name: "migrate_cluster",
8536
+ docs: [
8537
+ "One-shot layout migrations for the staking upgrade. Each grows one already-deployed",
8538
+ "account to the current (append-only) layout; idempotent and permissionless. See",
8539
+ "`instructions::migration`."
8540
+ ],
8541
+ discriminator: [
8542
+ 158,
8543
+ 61,
8544
+ 104,
8545
+ 161,
8546
+ 253,
8547
+ 138,
8548
+ 0,
8549
+ 17
8550
+ ],
8551
+ accounts: [
8552
+ {
8553
+ name: "payer",
8554
+ writable: true,
8555
+ signer: true
8556
+ },
8557
+ {
8558
+ name: "cluster",
8559
+ docs: [
8560
+ "because the new program cannot deserialize the old (short) layout via `Account<Cluster>`."
8561
+ ],
8562
+ writable: true
8563
+ },
8564
+ {
8565
+ name: "system_program",
8566
+ address: "11111111111111111111111111111111"
8567
+ }
8568
+ ],
8569
+ args: [
8570
+ ]
8571
+ },
8572
+ {
8573
+ name: "migrate_mxe_account",
8574
+ discriminator: [
8575
+ 96,
8576
+ 162,
8577
+ 117,
8578
+ 100,
8579
+ 242,
8580
+ 143,
8581
+ 16,
8582
+ 80
8583
+ ],
8584
+ accounts: [
8585
+ {
8586
+ name: "payer",
8587
+ writable: true,
8588
+ signer: true
8589
+ },
8590
+ {
8591
+ name: "mxe",
8592
+ writable: true
8593
+ },
8594
+ {
8595
+ name: "system_program",
8596
+ address: "11111111111111111111111111111111"
8597
+ }
8598
+ ],
8599
+ args: [
8600
+ ]
8601
+ },
8602
+ {
8603
+ name: "migrate_recovery_peer",
8604
+ discriminator: [
8605
+ 58,
8606
+ 226,
8607
+ 37,
8608
+ 60,
8609
+ 200,
8610
+ 31,
8611
+ 251,
8612
+ 245
8613
+ ],
8614
+ accounts: [
8615
+ {
8616
+ name: "payer",
8617
+ writable: true,
8618
+ signer: true
8619
+ },
8620
+ {
8621
+ name: "recovery_peer",
8622
+ writable: true
8623
+ },
8624
+ {
8625
+ name: "system_program",
8626
+ address: "11111111111111111111111111111111"
8627
+ }
8628
+ ],
8629
+ args: [
8630
+ ]
8631
+ },
8057
8632
  {
8058
8633
  name: "propose_fee",
8059
8634
  discriminator: [
@@ -8226,6 +8801,42 @@ var instructions = [
8226
8801
  ]
8227
8802
  }
8228
8803
  },
8804
+ {
8805
+ name: "mempool",
8806
+ docs: [
8807
+ "The cluster's mempool account, used only to read its size (from the discriminator) so we",
8808
+ "know the minimum primary stake the invited node must hold.",
8809
+ "`mempool_size_of`."
8810
+ ],
8811
+ pda: {
8812
+ seeds: [
8813
+ {
8814
+ kind: "const",
8815
+ value: [
8816
+ 77,
8817
+ 101,
8818
+ 109,
8819
+ 112,
8820
+ 111,
8821
+ 111,
8822
+ 108
8823
+ ]
8824
+ },
8825
+ {
8826
+ kind: "arg",
8827
+ path: "cluster_offset"
8828
+ }
8829
+ ]
8830
+ }
8831
+ },
8832
+ {
8833
+ name: "primary_stake_account",
8834
+ docs: [
8835
+ "The `PrimaryStakingAccount` (owned by `arcium_staking`) bound to the invited node. We read",
8836
+ "its `primary_stake` (first field) to enforce the per-mempool-size minimum. Verified to be",
8837
+ "owned by the staking program and to match the node's recorded `primary_staking_account`."
8838
+ ]
8839
+ },
8229
8840
  {
8230
8841
  name: "clock",
8231
8842
  writable: true,
@@ -8272,7 +8883,12 @@ var instructions = [
8272
8883
  docs: [
8273
8884
  "Queues a computation.",
8274
8885
  "cu_price_micro: The priority price of a CU, in micro-lamports. Used",
8275
- "to calculate the priority fee and rounded down."
8886
+ "to calculate the priority fee and rounded down.",
8887
+ "callback_cu_limit: The compute unit limit to request for the callback transaction(s)",
8888
+ "via set_compute_unit_limit. 0 means unset (the node uses the default compute budget).",
8889
+ "A non-zero value incurs an additional priority fee of callback_cu_limit * cu_price_micro.",
8890
+ "callback_cu_limit + padding together occupy the 8 bytes that previously held the",
8891
+ "(always-zero) output_delivery_fee: u64, so the instruction layout is unchanged."
8276
8892
  ],
8277
8893
  discriminator: [
8278
8894
  1,
@@ -8605,8 +9221,12 @@ var instructions = [
8605
9221
  type: "u8"
8606
9222
  },
8607
9223
  {
8608
- name: "output_delivery_fee",
8609
- type: "u64"
9224
+ name: "callback_cu_limit",
9225
+ type: "u32"
9226
+ },
9227
+ {
9228
+ name: "padding",
9229
+ type: "u32"
8610
9230
  },
8611
9231
  {
8612
9232
  name: "cu_price_micro",
@@ -9883,7 +10503,63 @@ var instructions = [
9883
10503
  ],
9884
10504
  accounts: [
9885
10505
  {
9886
- name: "current_authority",
10506
+ name: "current_authority",
10507
+ writable: true,
10508
+ signer: true
10509
+ },
10510
+ {
10511
+ name: "cluster_acc",
10512
+ writable: true,
10513
+ pda: {
10514
+ seeds: [
10515
+ {
10516
+ kind: "const",
10517
+ value: [
10518
+ 67,
10519
+ 108,
10520
+ 117,
10521
+ 115,
10522
+ 116,
10523
+ 101,
10524
+ 114
10525
+ ]
10526
+ },
10527
+ {
10528
+ kind: "arg",
10529
+ path: "_id"
10530
+ }
10531
+ ]
10532
+ }
10533
+ }
10534
+ ],
10535
+ args: [
10536
+ {
10537
+ name: "cluster_id",
10538
+ type: "u32"
10539
+ },
10540
+ {
10541
+ name: "new_authority",
10542
+ type: {
10543
+ option: "pubkey"
10544
+ }
10545
+ }
10546
+ ]
10547
+ },
10548
+ {
10549
+ name: "set_cluster_td_info",
10550
+ discriminator: [
10551
+ 182,
10552
+ 126,
10553
+ 92,
10554
+ 101,
10555
+ 25,
10556
+ 252,
10557
+ 84,
10558
+ 180
10559
+ ],
10560
+ accounts: [
10561
+ {
10562
+ name: "authority",
9887
10563
  writable: true,
9888
10564
  signer: true
9889
10565
  },
@@ -9918,28 +10594,32 @@ var instructions = [
9918
10594
  type: "u32"
9919
10595
  },
9920
10596
  {
9921
- name: "new_authority",
10597
+ name: "td_info",
9922
10598
  type: {
9923
- option: "pubkey"
10599
+ option: {
10600
+ defined: {
10601
+ name: "NodeMetadata"
10602
+ }
10603
+ }
9924
10604
  }
9925
10605
  }
9926
10606
  ]
9927
10607
  },
9928
10608
  {
9929
- name: "set_cluster_td_info",
10609
+ name: "set_leader_choice",
9930
10610
  discriminator: [
9931
- 182,
9932
- 126,
9933
- 92,
9934
- 101,
9935
- 25,
9936
- 252,
9937
- 84,
9938
- 180
10611
+ 42,
10612
+ 7,
10613
+ 112,
10614
+ 255,
10615
+ 254,
10616
+ 186,
10617
+ 135,
10618
+ 133
9939
10619
  ],
9940
10620
  accounts: [
9941
10621
  {
9942
- name: "authority",
10622
+ name: "node_authority",
9943
10623
  writable: true,
9944
10624
  signer: true
9945
10625
  },
@@ -9962,7 +10642,53 @@ var instructions = [
9962
10642
  },
9963
10643
  {
9964
10644
  kind: "arg",
9965
- path: "_id"
10645
+ path: "cluster_offset"
10646
+ }
10647
+ ]
10648
+ }
10649
+ },
10650
+ {
10651
+ name: "arx_node_acc",
10652
+ pda: {
10653
+ seeds: [
10654
+ {
10655
+ kind: "const",
10656
+ value: [
10657
+ 65,
10658
+ 114,
10659
+ 120,
10660
+ 78,
10661
+ 111,
10662
+ 100,
10663
+ 101
10664
+ ]
10665
+ },
10666
+ {
10667
+ kind: "arg",
10668
+ path: "node_offset"
10669
+ }
10670
+ ]
10671
+ }
10672
+ },
10673
+ {
10674
+ name: "mempool",
10675
+ pda: {
10676
+ seeds: [
10677
+ {
10678
+ kind: "const",
10679
+ value: [
10680
+ 77,
10681
+ 101,
10682
+ 109,
10683
+ 112,
10684
+ 111,
10685
+ 111,
10686
+ 108
10687
+ ]
10688
+ },
10689
+ {
10690
+ kind: "arg",
10691
+ path: "cluster_offset"
9966
10692
  }
9967
10693
  ]
9968
10694
  }
@@ -9970,16 +10696,18 @@ var instructions = [
9970
10696
  ],
9971
10697
  args: [
9972
10698
  {
9973
- name: "cluster_id",
10699
+ name: "cluster_offset",
9974
10700
  type: "u32"
9975
10701
  },
9976
10702
  {
9977
- name: "td_info",
10703
+ name: "node_offset",
10704
+ type: "u32"
10705
+ },
10706
+ {
10707
+ name: "choice",
9978
10708
  type: {
9979
- option: {
9980
- defined: {
9981
- name: "NodeMetadata"
9982
- }
10709
+ defined: {
10710
+ name: "LeaderChoice"
9983
10711
  }
9984
10712
  }
9985
10713
  }
@@ -10311,6 +11039,156 @@ var instructions = [
10311
11039
  }
10312
11040
  ]
10313
11041
  },
11042
+ {
11043
+ name: "set_node_staking",
11044
+ discriminator: [
11045
+ 158,
11046
+ 40,
11047
+ 109,
11048
+ 244,
11049
+ 217,
11050
+ 195,
11051
+ 35,
11052
+ 140
11053
+ ],
11054
+ accounts: [
11055
+ {
11056
+ name: "staking_pool_signer",
11057
+ docs: [
11058
+ "The `arcium_staking::state::StakingPoolAccount` PDA, signing via CPI. The `seeds`/`bump`",
11059
+ "constraint verifies it's the canonical pool PDA under `ARCIUM_STAKING_ID` (so only the",
11060
+ "staking program can call this)"
11061
+ ],
11062
+ signer: true,
11063
+ pda: {
11064
+ seeds: [
11065
+ {
11066
+ kind: "const",
11067
+ value: [
11068
+ 83,
11069
+ 116,
11070
+ 97,
11071
+ 107,
11072
+ 105,
11073
+ 110,
11074
+ 103,
11075
+ 80,
11076
+ 111,
11077
+ 111,
11078
+ 108,
11079
+ 65,
11080
+ 99,
11081
+ 99,
11082
+ 111,
11083
+ 117,
11084
+ 110,
11085
+ 116
11086
+ ]
11087
+ }
11088
+ ],
11089
+ program: {
11090
+ kind: "const",
11091
+ value: [
11092
+ 146,
11093
+ 110,
11094
+ 184,
11095
+ 172,
11096
+ 179,
11097
+ 131,
11098
+ 118,
11099
+ 35,
11100
+ 207,
11101
+ 122,
11102
+ 30,
11103
+ 190,
11104
+ 228,
11105
+ 134,
11106
+ 232,
11107
+ 140,
11108
+ 222,
11109
+ 89,
11110
+ 53,
11111
+ 150,
11112
+ 174,
11113
+ 187,
11114
+ 151,
11115
+ 58,
11116
+ 208,
11117
+ 108,
11118
+ 237,
11119
+ 119,
11120
+ 97,
11121
+ 204,
11122
+ 184,
11123
+ 186
11124
+ ]
11125
+ }
11126
+ }
11127
+ },
11128
+ {
11129
+ name: "cluster",
11130
+ writable: true,
11131
+ pda: {
11132
+ seeds: [
11133
+ {
11134
+ kind: "const",
11135
+ value: [
11136
+ 67,
11137
+ 108,
11138
+ 117,
11139
+ 115,
11140
+ 116,
11141
+ 101,
11142
+ 114
11143
+ ]
11144
+ },
11145
+ {
11146
+ kind: "arg",
11147
+ path: "cluster_offset"
11148
+ }
11149
+ ]
11150
+ }
11151
+ },
11152
+ {
11153
+ name: "clock",
11154
+ pda: {
11155
+ seeds: [
11156
+ {
11157
+ kind: "const",
11158
+ value: [
11159
+ 67,
11160
+ 108,
11161
+ 111,
11162
+ 99,
11163
+ 107,
11164
+ 65,
11165
+ 99,
11166
+ 99,
11167
+ 111,
11168
+ 117,
11169
+ 110,
11170
+ 116
11171
+ ]
11172
+ }
11173
+ ]
11174
+ }
11175
+ }
11176
+ ],
11177
+ args: [
11178
+ {
11179
+ name: "cluster_offset",
11180
+ type: "u32"
11181
+ },
11182
+ {
11183
+ name: "node_offset",
11184
+ type: "u32"
11185
+ },
11186
+ {
11187
+ name: "stake",
11188
+ type: "u64"
11189
+ }
11190
+ ]
11191
+ },
10314
11192
  {
10315
11193
  name: "submit_aggregated_bls_pubkey",
10316
11194
  discriminator: [
@@ -11640,6 +12518,11 @@ var errors = [
11640
12518
  name: "MaxParallelismReached",
11641
12519
  msg: "Max parallelism reached"
11642
12520
  },
12521
+ {
12522
+ code: 6104,
12523
+ name: "MempoolAlreadyFullSize",
12524
+ msg: "Mempool is already at its full allocated size"
12525
+ },
11643
12526
  {
11644
12527
  code: 6200,
11645
12528
  name: "InvalidComputationOffset",
@@ -11815,6 +12698,16 @@ var errors = [
11815
12698
  name: "InvalidNodeOffset",
11816
12699
  msg: "Node offset is invalid"
11817
12700
  },
12701
+ {
12702
+ code: 6411,
12703
+ name: "InvalidStakingPoolSigner",
12704
+ msg: "The provided staking pool signer is not the staking program's StakingPoolAccount PDA"
12705
+ },
12706
+ {
12707
+ code: 6412,
12708
+ name: "InvalidStakingAccount",
12709
+ msg: "The provided primary stake account is not owned by the staking program or does not match the node's bound staking account"
12710
+ },
11818
12711
  {
11819
12712
  code: 6500,
11820
12713
  name: "ClusterFull",
@@ -11873,7 +12766,7 @@ var errors = [
11873
12766
  {
11874
12767
  code: 6602,
11875
12768
  name: "HeapFull",
11876
- msg: "Heap is full"
12769
+ msg: "Mempool capacity for the current slot reached - retry next slot or reduce queue rate"
11877
12770
  },
11878
12771
  {
11879
12772
  code: 6603,
@@ -11990,6 +12883,11 @@ var errors = [
11990
12883
  name: "RecoveryInitAlreadyInitialized",
11991
12884
  msg: "Recovery already initialized"
11992
12885
  },
12886
+ {
12887
+ code: 6626,
12888
+ name: "InvalidSubsequentIx",
12889
+ msg: "Subsequent instruction in this transaction is not the expected one"
12890
+ },
11993
12891
  {
11994
12892
  code: 6700,
11995
12893
  name: "MxeNotInMigrationState",
@@ -12114,6 +13012,16 @@ var errors = [
12114
13012
  code: 6725,
12115
13013
  name: "CannotCloseMxeDuringMigration",
12116
13014
  msg: "MXE is in migration state, cannot close MXE"
13015
+ },
13016
+ {
13017
+ code: 6726,
13018
+ name: "InvalidMigrationAccount",
13019
+ msg: "Account is not a valid target for this migration (wrong owner or discriminator)"
13020
+ },
13021
+ {
13022
+ code: 6727,
13023
+ name: "InsufficientPrimaryStake",
13024
+ msg: "Node's primary stake is below the minimum for this cluster's mempool size"
12117
13025
  }
12118
13026
  ];
12119
13027
  var types = [
@@ -12914,30 +13822,71 @@ var types = [
12914
13822
  }
12915
13823
  },
12916
13824
  {
12917
- name: "bls_public_key",
13825
+ name: "bls_public_key",
13826
+ docs: [
13827
+ "BLS public key for the cluster (64 bytes compressed G2 point for alt-bn128)",
13828
+ "Set only when all nodes have submitted and agreed on the aggregated pubkey"
13829
+ ],
13830
+ type: {
13831
+ defined: {
13832
+ name: "SetUnset",
13833
+ generics: [
13834
+ {
13835
+ kind: "type",
13836
+ type: {
13837
+ defined: {
13838
+ name: "BN254G2BLSPublicKey"
13839
+ }
13840
+ }
13841
+ }
13842
+ ]
13843
+ }
13844
+ }
13845
+ },
13846
+ {
13847
+ name: "bump",
13848
+ docs: [
13849
+ "PDA bump. Declared by hand rather than via the `#[bump]` macro (which appends the bump",
13850
+ "as the *final* struct field) so it keeps its original offset right after",
13851
+ "`bls_public_key`. Everything below is appended *after* the bump, which means the byte",
13852
+ "layout of every field up to and including `bump` is identical to the pre-staking",
13853
+ "`Cluster` — old deserializers (including external user programs that read this account)",
13854
+ "decode the original prefix and harmlessly ignore the trailing staking fields."
13855
+ ],
13856
+ type: "u8"
13857
+ },
13858
+ {
13859
+ name: "current_epoch_total_rewards",
13860
+ docs: [
13861
+ "Running total of computation rewards accrued during `rewards_epoch`. Drained to zero",
13862
+ "by `claim_node_fees` when nodes settle via `finalize_epoch_rewards`."
13863
+ ],
13864
+ type: "u64"
13865
+ },
13866
+ {
13867
+ name: "rewards_epoch",
13868
+ docs: [
13869
+ "The epoch that `current_epoch_total_rewards` belongs to. If the clock has advanced",
13870
+ "past this epoch and `current_epoch_total_rewards > 0`, the rewards are stale",
13871
+ "(nodes didn't settle in time) — new accruals are silently skipped until nodes",
13872
+ "finalize, which punishes lazy operators."
13873
+ ],
13874
+ type: {
13875
+ defined: {
13876
+ name: "Epoch"
13877
+ }
13878
+ }
13879
+ },
13880
+ {
13881
+ name: "leader_selector",
12918
13882
  docs: [
12919
- "BLS public key for the cluster (64 bytes compressed G2 point for alt-bn128)",
12920
- "Set only when all nodes have submitted and agreed on the aggregated pubkey"
13883
+ "The selector for leader."
12921
13884
  ],
12922
13885
  type: {
12923
13886
  defined: {
12924
- name: "SetUnset",
12925
- generics: [
12926
- {
12927
- kind: "type",
12928
- type: {
12929
- defined: {
12930
- name: "BN254G2BLSPublicKey"
12931
- }
12932
- }
12933
- }
12934
- ]
13887
+ name: "LeaderSelector"
12935
13888
  }
12936
13889
  }
12937
- },
12938
- {
12939
- name: "bump",
12940
- type: "u8"
12941
13890
  }
12942
13891
  ]
12943
13892
  }
@@ -13471,16 +14420,28 @@ var types = [
13471
14420
  {
13472
14421
  name: "priority_fee",
13473
14422
  docs: [
13474
- "The additional fee to enforce priortized execution in the mempool."
14423
+ "The additional fee to enforce prioritized execution in the mempool."
13475
14424
  ],
13476
14425
  type: "u64"
13477
14426
  },
13478
14427
  {
13479
- name: "output_delivery_fee",
14428
+ name: "callback_cu_limit",
13480
14429
  docs: [
13481
- "A fee for output delivery fees (i.e. tx fees)."
14430
+ "The compute unit limit to request for the callback transaction(s), i.e. how many CUs the",
14431
+ "node should request via set_compute_unit_limit. 0 means unset, in which case the node uses",
14432
+ "the default compute budget.",
14433
+ "",
14434
+ "This reuses the low 4 bytes of what was previously `output_delivery_fee: u64` (which was",
14435
+ "always 0), so the serialized layout of ExecutionFee is unchanged."
13482
14436
  ],
13483
- type: "u64"
14437
+ type: "u32"
14438
+ },
14439
+ {
14440
+ name: "padding",
14441
+ docs: [
14442
+ "Padding preserving the original 8-byte (u64) layout of the former `output_delivery_fee`."
14443
+ ],
14444
+ type: "u32"
13484
14445
  }
13485
14446
  ]
13486
14447
  }
@@ -13846,6 +14807,113 @@ var types = [
13846
14807
  ]
13847
14808
  }
13848
14809
  },
14810
+ {
14811
+ name: "LeaderChoice",
14812
+ docs: [
14813
+ "The computation chosen by a node to be executed when the node is leader."
14814
+ ],
14815
+ type: {
14816
+ kind: "struct",
14817
+ fields: [
14818
+ {
14819
+ name: "offset",
14820
+ docs: [
14821
+ "Computation_offset of the chosen computation."
14822
+ ],
14823
+ type: "u64"
14824
+ },
14825
+ {
14826
+ name: "slot_idx",
14827
+ docs: [
14828
+ "The index of the max_heap the computation is in inside the MemPool's Circular Buffer.",
14829
+ "This is the physical index, not the logical one."
14830
+ ],
14831
+ type: "u16"
14832
+ }
14833
+ ]
14834
+ }
14835
+ },
14836
+ {
14837
+ name: "LeaderInfo",
14838
+ docs: [
14839
+ "The information about a node."
14840
+ ],
14841
+ type: {
14842
+ kind: "struct",
14843
+ fields: [
14844
+ {
14845
+ name: "stake",
14846
+ docs: [
14847
+ "The node's stake."
14848
+ ],
14849
+ type: "u64"
14850
+ },
14851
+ {
14852
+ name: "count",
14853
+ docs: [
14854
+ "The number + 1 of times the node has been chosen as leader in this cycle.",
14855
+ "0 if the stake is unset.",
14856
+ "This way works well for performance."
14857
+ ],
14858
+ type: "u64"
14859
+ },
14860
+ {
14861
+ name: "last_counter_plus_one",
14862
+ docs: [
14863
+ "The last time the node has been chosen as leader."
14864
+ ],
14865
+ type: "u64"
14866
+ },
14867
+ {
14868
+ name: "choice",
14869
+ docs: [
14870
+ "The choice of that node."
14871
+ ],
14872
+ type: {
14873
+ defined: {
14874
+ name: "LeaderChoice"
14875
+ }
14876
+ }
14877
+ }
14878
+ ]
14879
+ }
14880
+ },
14881
+ {
14882
+ name: "LeaderSelector",
14883
+ docs: [
14884
+ "To select a Leader.",
14885
+ "Uses the greatest divisors method: https://en.wikipedia.org/wiki/D%27Hondt_method"
14886
+ ],
14887
+ type: {
14888
+ kind: "struct",
14889
+ fields: [
14890
+ {
14891
+ name: "staking_epoch",
14892
+ docs: [
14893
+ "The last epoch the staking was set."
14894
+ ],
14895
+ type: {
14896
+ defined: {
14897
+ name: "Epoch"
14898
+ }
14899
+ }
14900
+ },
14901
+ {
14902
+ name: "info",
14903
+ docs: [
14904
+ "The information about each node."
14905
+ ],
14906
+ type: {
14907
+ vec: {
14908
+ defined: {
14909
+ name: "LeaderInfo"
14910
+ }
14911
+ }
14912
+ }
14913
+ }
14914
+ ]
14915
+ }
14916
+ },
13849
14917
  {
13850
14918
  name: "LocalCircuitSource",
13851
14919
  type: {
@@ -13970,7 +15038,40 @@ var types = [
13970
15038
  },
13971
15039
  {
13972
15040
  name: "bump",
15041
+ docs: [
15042
+ "PDA bump. Declared by hand rather than via the `#[bump]` macro (which appends the bump",
15043
+ "as the *final* struct field) so it keeps its original offset right after `status`.",
15044
+ "The recovery-reward fields below are appended *after* the bump, leaving the byte layout",
15045
+ "of every field up to and including `bump` identical to the pre-staking `MXEAccount` —",
15046
+ "old deserializers (including external user programs) decode the original prefix and",
15047
+ "harmlessly ignore the trailing fields."
15048
+ ],
13973
15049
  type: "u8"
15050
+ },
15051
+ {
15052
+ name: "current_epoch_recovery_rewards",
15053
+ docs: [
15054
+ "Running total of recovery-peer rewards accrued during `recovery_rewards_epoch`.",
15055
+ "Fed by the 20% slice of every computation/failure fee processed on this MXE;",
15056
+ "drained to zero by `claim_recovery_peer_fees` when recovery peers settle via",
15057
+ "`arcium_staking::finalize_recovery_epoch_rewards`. Same stale-epoch guard as",
15058
+ "`Cluster::current_epoch_total_rewards` — if peers don't settle before the epoch",
15059
+ "rolls over, new accruals are silently skipped until the pot is drained."
15060
+ ],
15061
+ type: "u64"
15062
+ },
15063
+ {
15064
+ name: "recovery_rewards_epoch",
15065
+ docs: [
15066
+ "Epoch that `current_epoch_recovery_rewards` is attributed to. Compared against the",
15067
+ "executing cluster's `last_updated_epoch` (the same proxy used by cluster rewards) to",
15068
+ "decide whether a new accrual is for the current round or a stale one."
15069
+ ],
15070
+ type: {
15071
+ defined: {
15072
+ name: "Epoch"
15073
+ }
15074
+ }
13974
15075
  }
13975
15076
  ]
13976
15077
  }
@@ -14305,9 +15406,7 @@ var types = [
14305
15406
  name: "NodeRef",
14306
15407
  docs: [
14307
15408
  "A reference to a node in the cluster.",
14308
- "The offset is to derive the Node Account.",
14309
- "The current_total_rewards is the total rewards the node has received so far in the current",
14310
- "epoch."
15409
+ "The offset is to derive the Node Account."
14311
15410
  ],
14312
15411
  type: {
14313
15412
  kind: "struct",
@@ -14317,11 +15416,22 @@ var types = [
14317
15416
  type: "u32"
14318
15417
  },
14319
15418
  {
14320
- name: "current_total_rewards",
15419
+ name: "_padding",
14321
15420
  docs: [
14322
- "Current total rewards the node has received in the current epoch in lamports."
15421
+ "Reserved padding occupying the 8 bytes that previously held `current_total_rewards: u64`",
15422
+ "(per-node reward tracking, now superseded by the cluster-level",
15423
+ "`current_epoch_total_rewards`). We keep these bytes rather than shrinking `NodeRef`",
15424
+ "because `nodes: Vec<NodeRef>` sits in the *middle* of the `Cluster` struct: removing the",
15425
+ "field would change the encoded element size and desync the borsh decode of every field",
15426
+ "after `nodes` for already-deployed accounts and external deserializers. Do not repurpose",
15427
+ "without a full account migration."
14323
15428
  ],
14324
- type: "u64"
15429
+ type: {
15430
+ array: [
15431
+ "u8",
15432
+ 8
15433
+ ]
15434
+ }
14325
15435
  },
14326
15436
  {
14327
15437
  name: "vote",
@@ -14759,7 +15869,27 @@ var types = [
14759
15869
  },
14760
15870
  {
14761
15871
  name: "bump",
15872
+ docs: [
15873
+ "PDA bump. Declared by hand rather than via the `#[bump]` macro (which appends the bump",
15874
+ "as the *final* struct field) so it keeps its original offset (76) right after",
15875
+ "`peer_offset`. `primary_stake_account` is appended *after* the bump, leaving the byte",
15876
+ "layout of every field up to and including `bump` identical to the pre-staking",
15877
+ "`RecoveryPeerAccount` — old deserializers decode the original prefix and harmlessly",
15878
+ "ignore the trailing field."
15879
+ ],
14762
15880
  type: "u8"
15881
+ },
15882
+ {
15883
+ name: "primary_stake_account",
15884
+ docs: [
15885
+ "The `PrimaryStakingAccount` (owned by `arcium_staking`) this recovery peer is bound",
15886
+ "to. Enforced at init time via an owner check so every recovery peer has skin in the",
15887
+ "game — the same stake-first model we already apply to `ArxNode`. Stored here so",
15888
+ "downstream instructions (and off-chain consumers) can look up the backing stake",
15889
+ "without re-validating the chain of accounts. Appended after `bump` to preserve the",
15890
+ "legacy on-chain layout (see the `bump` field comment)."
15891
+ ],
15892
+ type: "pubkey"
14763
15893
  }
14764
15894
  ]
14765
15895
  }
@@ -15308,6 +16438,26 @@ const MXE_RECOVERY_ACC_SEED = 'MxeRecoveryAccount';
15308
16438
  * @constant {string}
15309
16439
  */
15310
16440
  const RAW_CIRCUIT_ACC_SEED = 'ComputationDefinitionRaw';
16441
+ /**
16442
+ * Seed for RecoveryPeerAccount PDA.
16443
+ * @constant {string}
16444
+ */
16445
+ const RECOVERY_PEER_ACC_SEED = 'RecoveryPeerAccount';
16446
+ /**
16447
+ * Seed for Operator PDA.
16448
+ * @constant {string}
16449
+ */
16450
+ const OPERATOR_ACC_SEED = 'Operator';
16451
+ /**
16452
+ * Seed for FailureClaimAccountHeader PDA.
16453
+ * @constant {string}
16454
+ */
16455
+ const FAILURE_CLAIM_ACC_SEED = 'FailureClaimAccountHeader';
16456
+ /**
16457
+ * Seed for ArciumSignerAccount PDA.
16458
+ * @constant {string}
16459
+ */
16460
+ const ARCIUM_SIGNER_ACC_SEED = 'ArciumSignerAccount';
15311
16461
  /**
15312
16462
  * Maximum number of bytes that can be reallocated per instruction.
15313
16463
  * @constant {number}
@@ -15328,11 +16478,36 @@ const MAX_ACCOUNT_SIZE = 10485760;
15328
16478
  * @constant {number}
15329
16479
  */
15330
16480
  const MAX_EMBIGGEN_IX_PER_TX = 18;
16481
+ /**
16482
+ * Default number of upload transactions sent in parallel.
16483
+ * @constant {number}
16484
+ */
16485
+ const DEFAULT_UPLOAD_TX_BATCH_SIZE = 500;
15331
16486
  /**
15332
16487
  * Size of account discriminator in bytes.
15333
16488
  * @constant {number}
15334
16489
  */
15335
16490
  const DISCRIMINATOR_SIZE = 8;
16491
+ /**
16492
+ * Size of the bump field in a ComputationDefinitionRaw account.
16493
+ * @constant {number}
16494
+ */
16495
+ const RAW_CIRCUIT_ACCOUNT_BUMP_SIZE = 1;
16496
+ /**
16497
+ * Size of ComputationDefinitionRaw account metadata before circuit bytes.
16498
+ * @constant {number}
16499
+ */
16500
+ const RAW_CIRCUIT_ACCOUNT_HEADER_SIZE = DISCRIMINATOR_SIZE + RAW_CIRCUIT_ACCOUNT_BUMP_SIZE;
16501
+ /**
16502
+ * Maximum circuit bytes that fit in one ComputationDefinitionRaw account.
16503
+ * @constant {number}
16504
+ */
16505
+ const MAX_RAW_CIRCUIT_BYTES_PER_ACC = MAX_ACCOUNT_SIZE - RAW_CIRCUIT_ACCOUNT_HEADER_SIZE;
16506
+ /**
16507
+ * Maximum number of raw circuit accounts addressable by the u8 raw circuit index.
16508
+ * @constant {number}
16509
+ */
16510
+ const MAX_RAW_CIRCUIT_ACCOUNTS = 256;
15336
16511
  /**
15337
16512
  * Size of offset buffer in bytes (u32).
15338
16513
  * @constant {number}
@@ -15343,7 +16518,20 @@ const OFFSET_BUFFER_SIZE = 4;
15343
16518
  * @constant {number}
15344
16519
  */
15345
16520
  const COMP_DEF_OFFSET_SIZE = 4;
16521
+ /**
16522
+ * Maximum recovery peer slots supported by key recovery accounts.
16523
+ * @constant {number}
16524
+ */
16525
+ const MAX_RECOVERY_PEERS = 100;
16526
+ /**
16527
+ * Minimum recovery peers required for key recovery.
16528
+ * @constant {number}
16529
+ */
16530
+ const MIN_RECOVERY_PEERS = 4;
15346
16531
 
16532
+ const U64_SEED_SIZE = 8;
16533
+ const MAX_U8 = 0xff;
16534
+ const MAX_U32$1 = 0xffffffff;
15347
16535
  /**
15348
16536
  * Return the public key of the deployed Arcium program on Solana.
15349
16537
  * @returns Arcium program's public key.
@@ -15358,10 +16546,7 @@ function getArciumProgramId() {
15358
16546
  * @returns Derived computation account public key.
15359
16547
  */
15360
16548
  function getComputationAccAddress(clusterOffset, computationOffset) {
15361
- const clOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15362
- clOffsetBuffer.writeUInt32LE(clusterOffset, 0);
15363
- const seeds = [Buffer.from(COMPUTATION_ACC_SEED), clOffsetBuffer, computationOffset.toArrayLike(Buffer, 'le', 8)];
15364
- return generateArciumPDAFrom(seeds)[0];
16549
+ return findArciumPda([stringSeed(COMPUTATION_ACC_SEED), u32Seed(clusterOffset), u64Seed(computationOffset)]);
15365
16550
  }
15366
16551
  /**
15367
16552
  * Derive the mempool account address for a given cluster.
@@ -15369,10 +16554,7 @@ function getComputationAccAddress(clusterOffset, computationOffset) {
15369
16554
  * @returns Derived mempool account public key.
15370
16555
  */
15371
16556
  function getMempoolAccAddress(clusterOffset) {
15372
- const clOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15373
- clOffsetBuffer.writeUInt32LE(clusterOffset, 0);
15374
- const seeds = [Buffer.from(MEMPOOL_ACC_SEED), clOffsetBuffer];
15375
- return generateArciumPDAFrom(seeds)[0];
16557
+ return findArciumPda([stringSeed(MEMPOOL_ACC_SEED), u32Seed(clusterOffset)]);
15376
16558
  }
15377
16559
  /**
15378
16560
  * Derive the executing pool account address for a given cluster.
@@ -15380,26 +16562,21 @@ function getMempoolAccAddress(clusterOffset) {
15380
16562
  * @returns Derived executing pool account public key.
15381
16563
  */
15382
16564
  function getExecutingPoolAccAddress(clusterOffset) {
15383
- const clOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15384
- clOffsetBuffer.writeUInt32LE(clusterOffset, 0);
15385
- const seeds = [Buffer.from(EXEC_POOL_ACC_SEED), clOffsetBuffer];
15386
- return generateArciumPDAFrom(seeds)[0];
16565
+ return findArciumPda([stringSeed(EXEC_POOL_ACC_SEED), u32Seed(clusterOffset)]);
15387
16566
  }
15388
16567
  /**
15389
16568
  * Derive the fee pool account address.
15390
16569
  * @returns Derived fee pool account public key.
15391
16570
  */
15392
16571
  function getFeePoolAccAddress() {
15393
- const seeds = [Buffer.from(POOL_ACC_SEED)];
15394
- return generateArciumPDAFrom(seeds)[0];
16572
+ return findArciumPda([stringSeed(POOL_ACC_SEED)]);
15395
16573
  }
15396
16574
  /**
15397
16575
  * Derive the clock account address.
15398
16576
  * @returns Derived clock account public key.
15399
16577
  */
15400
16578
  function getClockAccAddress() {
15401
- const seeds = [Buffer.from(CLOCK_ACC_SEED)];
15402
- return generateArciumPDAFrom(seeds)[0];
16579
+ return findArciumPda([stringSeed(CLOCK_ACC_SEED)]);
15403
16580
  }
15404
16581
  /**
15405
16582
  * Derive the cluster account address for a given offset.
@@ -15407,10 +16584,7 @@ function getClockAccAddress() {
15407
16584
  * @returns Derived cluster account public key.
15408
16585
  */
15409
16586
  function getClusterAccAddress(clusterOffset) {
15410
- const offsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15411
- offsetBuffer.writeUInt32LE(clusterOffset, 0);
15412
- const seeds = [Buffer.from(CLUSTER_ACC_SEED), offsetBuffer];
15413
- return generateArciumPDAFrom(seeds)[0];
16587
+ return findArciumPda([stringSeed(CLUSTER_ACC_SEED), u32Seed(clusterOffset)]);
15414
16588
  }
15415
16589
  /**
15416
16590
  * Derive the ArxNode account address for a given offset.
@@ -15418,10 +16592,7 @@ function getClusterAccAddress(clusterOffset) {
15418
16592
  * @returns Derived ArxNode account public key.
15419
16593
  */
15420
16594
  function getArxNodeAccAddress(nodeOffset) {
15421
- const offsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15422
- offsetBuffer.writeUInt32LE(nodeOffset, 0);
15423
- const seeds = [Buffer.from(ARX_NODE_ACC_SEED), offsetBuffer];
15424
- return generateArciumPDAFrom(seeds)[0];
16595
+ return findArciumPda([stringSeed(ARX_NODE_ACC_SEED), u32Seed(nodeOffset)]);
15425
16596
  }
15426
16597
  /**
15427
16598
  * Derive the MXE account address for a given MXE program ID.
@@ -15429,8 +16600,7 @@ function getArxNodeAccAddress(nodeOffset) {
15429
16600
  * @returns Derived MXE account public key.
15430
16601
  */
15431
16602
  function getMXEAccAddress(mxeProgramId) {
15432
- const seeds = [Buffer.from(MXE_ACCOUNT_SEED), mxeProgramId.toBuffer()];
15433
- return generateArciumPDAFrom(seeds)[0];
16603
+ return findArciumPda([stringSeed(MXE_ACCOUNT_SEED), pubkeySeed(mxeProgramId)]);
15434
16604
  }
15435
16605
  /**
15436
16606
  * Derive the computation definition account address for a given MXE program ID and offset.
@@ -15439,10 +16609,7 @@ function getMXEAccAddress(mxeProgramId) {
15439
16609
  * @returns Derived computation definition account public key.
15440
16610
  */
15441
16611
  function getCompDefAccAddress(mxeProgramId, compDefOffset) {
15442
- const offsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15443
- offsetBuffer.writeUInt32LE(compDefOffset, 0);
15444
- const seeds = [Buffer.from(COMP_DEF_ACC_SEED), mxeProgramId.toBuffer(), offsetBuffer];
15445
- return generateArciumPDAFrom(seeds)[0];
16612
+ return findArciumPda([stringSeed(COMP_DEF_ACC_SEED), pubkeySeed(mxeProgramId), u32Seed(compDefOffset)]);
15446
16613
  }
15447
16614
  /**
15448
16615
  * Derive the recovery cluster account address for a given MXE program ID.
@@ -15450,8 +16617,7 @@ function getCompDefAccAddress(mxeProgramId, compDefOffset) {
15450
16617
  * @returns Derived recovery cluster account public key.
15451
16618
  */
15452
16619
  function getRecoveryClusterAccAddress(mxeProgramId) {
15453
- const seeds = [Buffer.from(RECOVERY_CLUSTER_ACC_SEED), mxeProgramId.toBuffer()];
15454
- return generateArciumPDAFrom(seeds)[0];
16620
+ return findArciumPda([stringSeed(RECOVERY_CLUSTER_ACC_SEED), pubkeySeed(mxeProgramId)]);
15455
16621
  }
15456
16622
  /**
15457
16623
  * Derive the MXE recovery account address for a key recovery session.
@@ -15459,22 +16625,52 @@ function getRecoveryClusterAccAddress(mxeProgramId) {
15459
16625
  * @returns Derived MXE recovery account public key.
15460
16626
  */
15461
16627
  function getMxeRecoveryAccAddress(originalMxeProgramId) {
15462
- const seeds = [Buffer.from(MXE_RECOVERY_ACC_SEED), originalMxeProgramId.toBuffer()];
15463
- return generateArciumPDAFrom(seeds)[0];
16628
+ return findArciumPda([stringSeed(MXE_RECOVERY_ACC_SEED), pubkeySeed(originalMxeProgramId)]);
16629
+ }
16630
+ /**
16631
+ * Derive the recovery peer account address for a given recovery peer offset.
16632
+ * @param peerOffset - Recovery peer offset as a u32 in `[0, 2^32 - 1]`.
16633
+ * @returns Derived recovery peer account public key.
16634
+ */
16635
+ function getRecoveryPeerAccAddress(peerOffset) {
16636
+ return findArciumPda([stringSeed(RECOVERY_PEER_ACC_SEED), u32Seed(peerOffset)]);
16637
+ }
16638
+ /**
16639
+ * Derive the operator account address for a given operator signer.
16640
+ * @param operatorSigner - Public key of the operator signer.
16641
+ * @returns Derived operator account public key.
16642
+ */
16643
+ function getOperatorAccAddress(operatorSigner) {
16644
+ return findArciumPda([stringSeed(OPERATOR_ACC_SEED), pubkeySeed(operatorSigner)]);
16645
+ }
16646
+ /**
16647
+ * Derive the failure claim account address for a given MXE program and computation offset.
16648
+ * @param mxeProgramId - Public key of the MXE program.
16649
+ * @param computationOffset - Computation offset as an anchor.BN in `[0, 2^64 - 1]`.
16650
+ * @returns Derived failure claim account public key.
16651
+ */
16652
+ function getFailureClaimAccAddress(mxeProgramId, computationOffset) {
16653
+ return findArciumPda([stringSeed(FAILURE_CLAIM_ACC_SEED), pubkeySeed(mxeProgramId), u64Seed(computationOffset)]);
16654
+ }
16655
+ /**
16656
+ * Derive the Arcium signer account address used by an MXE program when invoking the Arcium
16657
+ * program. Unlike most other helpers in this module, this PDA is derived under the MXE
16658
+ * program ID (the caller), not the Arcium program ID - Arcium verifies the seed via
16659
+ * `seeds::program = _mxe_program`.
16660
+ * @param mxeProgramId - Public key of the MXE program that owns the signer PDA.
16661
+ * @returns Derived Arcium signer account public key.
16662
+ */
16663
+ function getArciumSignerAccAddress(mxeProgramId) {
16664
+ return findPda(mxeProgramId, [stringSeed(ARCIUM_SIGNER_ACC_SEED)]);
15464
16665
  }
15465
16666
  /**
15466
16667
  * Derive the raw circuit account address for a given computation definition and index.
15467
16668
  * @param compDefPubkey - Public key of the computation definition account.
15468
- * @param rawCircuitIndex - Index of the raw circuit account (0-based).
16669
+ * @param rawCircuitIndex - Index of the raw circuit account as a u8 in `[0, 255]`.
15469
16670
  * @returns Derived raw circuit account public key.
15470
16671
  */
15471
16672
  function getRawCircuitAccAddress(compDefPubkey, rawCircuitIndex) {
15472
- const seeds = [
15473
- Buffer.from(RAW_CIRCUIT_ACC_SEED),
15474
- compDefPubkey.toBuffer(),
15475
- Buffer.from([rawCircuitIndex]),
15476
- ];
15477
- return generateArciumPDAFrom(seeds)[0];
16673
+ return findArciumPda([stringSeed(RAW_CIRCUIT_ACC_SEED), pubkeySeed(compDefPubkey), u8Seed(rawCircuitIndex)]);
15478
16674
  }
15479
16675
  /**
15480
16676
  * Derive the address lookup table address for an MXE program.
@@ -15484,120 +16680,149 @@ function getRawCircuitAccAddress(compDefPubkey, rawCircuitIndex) {
15484
16680
  */
15485
16681
  function getLookupTableAddress(mxeProgramId, lutOffset) {
15486
16682
  const mxeAccount = getMXEAccAddress(mxeProgramId);
15487
- const lutIndexBuffer = lutOffset.toArrayLike(Buffer, 'le', 8);
15488
- const seeds = [mxeAccount.toBuffer(), lutIndexBuffer];
15489
- return web3_js.PublicKey.findProgramAddressSync(seeds, web3_js.AddressLookupTableProgram.programId)[0];
16683
+ return findPda(web3_js.AddressLookupTableProgram.programId, [pubkeySeed(mxeAccount), u64Seed(lutOffset)]);
15490
16684
  }
15491
- /**
15492
- * Generate a program-derived address (PDA) from the provided seeds and the Arcium program ID.
15493
- * @param seeds - Array of Buffer seeds used for PDA derivation.
15494
- * @returns Tuple containing the derived public key and the bump seed.
15495
- */
15496
- function generateArciumPDAFrom(seeds) {
15497
- const programId = getArciumProgramId();
15498
- return web3_js.PublicKey.findProgramAddressSync(seeds, programId);
16685
+ function stringSeed(value) {
16686
+ return Buffer.from(value);
16687
+ }
16688
+ function u8Seed(value) {
16689
+ assertIntegerInRange(value, 0, MAX_U8, 'u8 seed');
16690
+ return Buffer.from([value]);
16691
+ }
16692
+ function u32Seed(value) {
16693
+ assertIntegerInRange(value, 0, MAX_U32$1, 'u32 seed');
16694
+ const buffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
16695
+ buffer.writeUInt32LE(value, 0);
16696
+ return buffer;
16697
+ }
16698
+ function u64Seed(value) {
16699
+ if (value.isNeg() || value.byteLength() > U64_SEED_SIZE) {
16700
+ throw new RangeError(`u64 seed must be between 0 and 18446744073709551615 (got ${value.toString()})`);
16701
+ }
16702
+ return value.toArrayLike(Buffer, 'le', U64_SEED_SIZE);
16703
+ }
16704
+ function pubkeySeed(value) {
16705
+ return value.toBuffer();
16706
+ }
16707
+ function findArciumPda(seeds) {
16708
+ return findPda(getArciumProgramId(), seeds);
16709
+ }
16710
+ function findPda(programId, seeds) {
16711
+ return web3_js.PublicKey.findProgramAddressSync(seeds, programId)[0];
16712
+ }
16713
+ function assertIntegerInRange(value, min, max, label) {
16714
+ if (!Number.isInteger(value) || value < min || value > max) {
16715
+ throw new RangeError(`${label} must be an integer between ${min} and ${max} (got ${value})`);
16716
+ }
15499
16717
  }
15500
16718
 
15501
- const TINY_MEMPOOL_ACC_NAME = 'tinyMempool';
15502
- const TINY_MEMPOOL_DISCRIMINATOR = [
15503
- 176,
15504
- 33,
15505
- 67,
15506
- 108,
15507
- 73,
15508
- 135,
15509
- 110,
15510
- 166,
15511
- ];
15512
- const TINY_EXECPOOL_ACC_NAME = 'tinyExecPool';
15513
- const TINY_EXECPOOL_DISCRIMINATOR = [
15514
- 80,
15515
- 245,
15516
- 5,
15517
- 90,
15518
- 154,
15519
- 189,
15520
- 190,
15521
- 172,
15522
- ];
15523
- const SMALL_MEMPOOL_ACC_NAME = 'smallMempool';
15524
- const SMALL_MEMPOOL_DISCRIMINATOR = [
15525
- 123,
15526
- 153,
15527
- 151,
15528
- 118,
15529
- 126,
15530
- 71,
15531
- 73,
15532
- 92,
15533
- ];
15534
- const SMALL_EXECPOOL_ACC_NAME = 'smallExecPool';
15535
- const SMALL_EXECPOOL_DISCRIMINATOR = [
15536
- 37,
15537
- 147,
15538
- 249,
15539
- 253,
15540
- 217,
15541
- 136,
15542
- 3,
15543
- 87,
16719
+ // Names are validated against the IDL account-name union at compile time, so a
16720
+ // typo or stale tier fails `tsc` rather than only throwing at load.
16721
+ const MEMPOOL_DECODER_ACCOUNT_NAMES = [
16722
+ 'tinyMempool',
16723
+ 'smallMempool',
16724
+ 'mediumMempool',
16725
+ 'largeMempool',
15544
16726
  ];
15545
- const MEDIUM_MEMPOOL_ACC_NAME = 'mediumMempool';
15546
- const MEDIUM_MEMPOOL_DISCRIMINATOR = [
15547
- 10,
15548
- 249,
15549
- 58,
15550
- 39,
15551
- 255,
15552
- 231,
15553
- 199,
15554
- 168,
16727
+ const EXECUTING_POOL_DECODER_ACCOUNT_NAMES = [
16728
+ 'tinyExecPool',
16729
+ 'smallExecPool',
16730
+ 'mediumExecPool',
16731
+ 'largeExecPool',
15555
16732
  ];
15556
- const MEDIUM_EXECPOOL_ACC_NAME = 'mediumExecPool';
15557
- const MEDIUM_EXECPOOL_DISCRIMINATOR = [
15558
- 97,
15559
- 117,
15560
- 128,
15561
- 202,
15562
- 213,
15563
- 76,
15564
- 5,
15565
- 163,
15566
- ];
15567
- const LARGE_MEMPOOL_ACC_NAME = 'largeMempool';
15568
- const LARGE_MEMPOOL_DISCRIMINATOR = [
15569
- 16,
15570
- 168,
15571
- 90,
15572
- 235,
15573
- 249,
15574
- 207,
15575
- 73,
15576
- 223,
15577
- ];
15578
- const LARGE_EXECPOOL_ACC_NAME = 'largeExecPool';
15579
- const LARGE_EXECPOOL_DISCRIMINATOR = [
15580
- 147,
15581
- 145,
15582
- 148,
15583
- 170,
15584
- 30,
15585
- 13,
15586
- 43,
15587
- 216,
15588
- ];
15589
- const MEMPOOL_DISCRIMINATOR_MAP = {
15590
- [TINY_MEMPOOL_DISCRIMINATOR.toString()]: TINY_MEMPOOL_ACC_NAME,
15591
- [SMALL_MEMPOOL_DISCRIMINATOR.toString()]: SMALL_MEMPOOL_ACC_NAME,
15592
- [MEDIUM_MEMPOOL_DISCRIMINATOR.toString()]: MEDIUM_MEMPOOL_ACC_NAME,
15593
- [LARGE_MEMPOOL_DISCRIMINATOR.toString()]: LARGE_MEMPOOL_ACC_NAME,
15594
- };
15595
- const EXECPOOL_DISCRIMINATOR_MAP = {
15596
- [TINY_EXECPOOL_DISCRIMINATOR.toString()]: TINY_EXECPOOL_ACC_NAME,
15597
- [SMALL_EXECPOOL_DISCRIMINATOR.toString()]: SMALL_EXECPOOL_ACC_NAME,
15598
- [MEDIUM_EXECPOOL_DISCRIMINATOR.toString()]: MEDIUM_EXECPOOL_ACC_NAME,
15599
- [LARGE_EXECPOOL_DISCRIMINATOR.toString()]: LARGE_EXECPOOL_ACC_NAME,
15600
- };
16733
+ function discriminatorKey(discriminator) {
16734
+ return Buffer.from(discriminator).toString('hex');
16735
+ }
16736
+ // Discriminator bytes are read from the IDL at load time rather than pinned, so the
16737
+ // decoder tracks the program's account layout as the single source of truth; a
16738
+ // missing or renamed tier throws here instead of silently misrouting at runtime.
16739
+ const accountDiscriminatorCoder = new anchor.BorshCoder(anchor.convertIdlToCamelCase(ARCIUM_IDL)).accounts;
16740
+ function buildPoolAccountMap(accountNames) {
16741
+ return new Map(accountNames.map((name) => [
16742
+ discriminatorKey(accountDiscriminatorCoder.accountDiscriminator(name)),
16743
+ name,
16744
+ ]));
16745
+ }
16746
+ const MEMPOOL_ACCOUNT_BY_DISCRIMINATOR = buildPoolAccountMap(MEMPOOL_DECODER_ACCOUNT_NAMES);
16747
+ const EXECUTING_POOL_ACCOUNT_BY_DISCRIMINATOR = buildPoolAccountMap(EXECUTING_POOL_DECODER_ACCOUNT_NAMES);
16748
+ function getPoolAccountNameByDiscriminator(accountData, accountsByDiscriminator, kind) {
16749
+ if (accountData.length < DISCRIMINATOR_SIZE) {
16750
+ throw new Error(`${kind} account data is shorter than discriminator size`);
16751
+ }
16752
+ const key = discriminatorKey(accountData.subarray(0, DISCRIMINATOR_SIZE));
16753
+ const accountName = accountsByDiscriminator.get(key);
16754
+ if (accountName === undefined) {
16755
+ throw new Error(`Unknown ${kind} account discriminator: ${key}`);
16756
+ }
16757
+ return accountName;
16758
+ }
16759
+ /** @internal */
16760
+ function getMempoolAccountNameByDiscriminator(accountData) {
16761
+ return getPoolAccountNameByDiscriminator(accountData, MEMPOOL_ACCOUNT_BY_DISCRIMINATOR, 'mempool');
16762
+ }
16763
+ /** @internal */
16764
+ function getExecutingPoolAccountNameByDiscriminator(accountData) {
16765
+ return getPoolAccountNameByDiscriminator(accountData, EXECUTING_POOL_ACCOUNT_BY_DISCRIMINATOR, 'executing pool');
16766
+ }
16767
+
16768
+ const MAX_U32 = 0xffffffff;
16769
+ /**
16770
+ * Mirrors the on-chain `init_mxe_part2` recovery-peer bounds before building the instruction.
16771
+ * @internal
16772
+ */
16773
+ function assertValidRecoveryPeers(recoveryPeers) {
16774
+ if (recoveryPeers.length > MAX_RECOVERY_PEERS) {
16775
+ throw new Error(`recoveryPeers must have at most ${MAX_RECOVERY_PEERS} elements (got ${recoveryPeers.length})`);
16776
+ }
16777
+ let nonZeroPeers = 0;
16778
+ for (let index = 0; index < recoveryPeers.length; index += 1) {
16779
+ const peer = recoveryPeers[index];
16780
+ if (!Number.isInteger(peer) || peer < 0 || peer > MAX_U32) {
16781
+ throw new RangeError(`recoveryPeers[${index}] must be an integer in [0, ${MAX_U32}] (got ${peer})`);
16782
+ }
16783
+ if (peer !== 0) {
16784
+ nonZeroPeers += 1;
16785
+ }
16786
+ }
16787
+ if (nonZeroPeers > 0 && nonZeroPeers < MIN_RECOVERY_PEERS) {
16788
+ throw new Error(`recoveryPeers must have 0 or at least ${MIN_RECOVERY_PEERS} non-zero offsets (found ${nonZeroPeers})`);
16789
+ }
16790
+ }
16791
+ /** @internal */
16792
+ function normalizeRecoveryPeers(recoveryPeers) {
16793
+ assertValidRecoveryPeers(recoveryPeers);
16794
+ const paddedRecoveryPeers = [...recoveryPeers];
16795
+ while (paddedRecoveryPeers.length < MAX_RECOVERY_PEERS) {
16796
+ paddedRecoveryPeers.push(0);
16797
+ }
16798
+ return paddedRecoveryPeers;
16799
+ }
16800
+
16801
+ /** @internal */
16802
+ function getRawCircuitAccountCount(rawCircuitByteLength) {
16803
+ if (!Number.isInteger(rawCircuitByteLength) || rawCircuitByteLength < 0) {
16804
+ throw new RangeError(`rawCircuit byte length must be a non-negative integer (got ${rawCircuitByteLength})`);
16805
+ }
16806
+ const accountCount = Math.ceil(rawCircuitByteLength / MAX_RAW_CIRCUIT_BYTES_PER_ACC);
16807
+ if (accountCount > MAX_RAW_CIRCUIT_ACCOUNTS) {
16808
+ throw new RangeError(`Raw circuit is too large for on-chain upload: requires ${accountCount} raw circuit accounts, maximum is ${MAX_RAW_CIRCUIT_ACCOUNTS}`);
16809
+ }
16810
+ return accountCount;
16811
+ }
16812
+ /** @internal */
16813
+ function assertRawCircuitUploadLength(rawCircuitByteLength, declaredCircuitByteLength, circuitName) {
16814
+ if (!Number.isInteger(rawCircuitByteLength) || rawCircuitByteLength < 0) {
16815
+ throw new RangeError(`rawCircuit byte length must be a non-negative integer (got ${rawCircuitByteLength})`);
16816
+ }
16817
+ if (!Number.isInteger(declaredCircuitByteLength) || declaredCircuitByteLength <= 0) {
16818
+ throw new RangeError(`Declared circuit byte length for ${circuitName} must be a positive integer (got ${declaredCircuitByteLength})`);
16819
+ }
16820
+ if (rawCircuitByteLength !== declaredCircuitByteLength) {
16821
+ throw new RangeError(`Raw circuit byte length for ${circuitName} must match the computation definition: got ${rawCircuitByteLength}, expected ${declaredCircuitByteLength}`);
16822
+ }
16823
+ }
16824
+
16825
+ const { BN } = anchor;
15601
16826
  /**
15602
16827
  * Fetch and decode the mempool account info for any mempool account size.
15603
16828
  * @param provider - Anchor provider to use for fetching accounts.
@@ -15606,15 +16831,8 @@ const EXECPOOL_DISCRIMINATOR_MAP = {
15606
16831
  * @throws Error if the account cannot be fetched or the discriminator is unknown.
15607
16832
  */
15608
16833
  async function getMempoolAccInfo(provider, mempoolAccPubkey) {
15609
- const accData = await provider.connection.getAccountInfo(mempoolAccPubkey);
15610
- if (accData === null) {
15611
- throw new Error(`Failed to fetch mempool account ${mempoolAccPubkey.toBase58()}`);
15612
- }
15613
- const discriminator = Array.from(accData.data.subarray(0, DISCRIMINATOR_SIZE)).toString();
15614
- const accName = MEMPOOL_DISCRIMINATOR_MAP[discriminator];
15615
- if (accName === undefined) {
15616
- throw new Error(`Unknown mempool account discriminator: ${discriminator}`);
15617
- }
16834
+ const accData = requireAccountInfo(await provider.connection.getAccountInfo(mempoolAccPubkey), mempoolAccPubkey, 'mempool');
16835
+ const accName = getMempoolAccountNameByDiscriminator(accData.data);
15618
16836
  const program = getArciumProgram(provider);
15619
16837
  return program.coder.accounts.decode(accName, accData.data);
15620
16838
  }
@@ -15626,18 +16844,17 @@ async function getMempoolAccInfo(provider, mempoolAccPubkey) {
15626
16844
  * @throws Error if the account cannot be fetched or the discriminator is unknown.
15627
16845
  */
15628
16846
  async function getExecutingPoolAccInfo(provider, executingPoolAccPubkey) {
15629
- const accData = await provider.connection.getAccountInfo(executingPoolAccPubkey);
15630
- if (accData === null) {
15631
- throw new Error(`Failed to fetch executing pool account ${executingPoolAccPubkey.toBase58()}`);
15632
- }
15633
- const discriminator = Array.from(accData.data.subarray(0, DISCRIMINATOR_SIZE)).toString();
15634
- const accName = EXECPOOL_DISCRIMINATOR_MAP[discriminator];
15635
- if (accName === undefined) {
15636
- throw new Error(`Unknown executing pool account discriminator: ${discriminator}`);
15637
- }
16847
+ const accData = requireAccountInfo(await provider.connection.getAccountInfo(executingPoolAccPubkey), executingPoolAccPubkey, 'executing pool');
16848
+ const accName = getExecutingPoolAccountNameByDiscriminator(accData.data);
15638
16849
  const program = getArciumProgram(provider);
15639
16850
  return program.coder.accounts.decode(accName, accData.data);
15640
16851
  }
16852
+ function requireAccountInfo(accountInfo, pubkey, label) {
16853
+ if (accountInfo === null) {
16854
+ throw new Error(`Failed to fetch ${label} account ${pubkey.toBase58()}`);
16855
+ }
16856
+ return accountInfo;
16857
+ }
15641
16858
  /**
15642
16859
  * Return all computation references in the mempool for a given account.
15643
16860
  * Only non-stake computations are included.
@@ -15681,15 +16898,15 @@ async function getComputationsInMempool(arciumProgram, address) {
15681
16898
  async function getMempoolPriorityFeeStats(arciumProgram, mempoolAddress) {
15682
16899
  const refs = await getComputationsInMempool(arciumProgram, mempoolAddress);
15683
16900
  if (refs.length === 0) {
15684
- const zero = new anchor__namespace.BN(0);
16901
+ const zero = new BN(0);
15685
16902
  return { mean: zero, median: zero, min: zero, max: zero, count: 0 };
15686
16903
  }
15687
16904
  const fees = refs.map(ref => ref.priorityFee).sort((a, b) => a.cmp(b));
15688
- const sum = fees.reduce((acc, fee) => acc.add(fee), new anchor__namespace.BN(0));
15689
- const mean = sum.div(new anchor__namespace.BN(fees.length));
16905
+ const sum = fees.reduce((acc, fee) => acc.add(fee), new BN(0));
16906
+ const mean = sum.div(new BN(fees.length));
15690
16907
  const mid = Math.floor(fees.length / 2);
15691
16908
  const median = fees.length % 2 === 0
15692
- ? fees[mid - 1].add(fees[mid]).div(new anchor__namespace.BN(2))
16909
+ ? fees[mid - 1].add(fees[mid]).div(new BN(2))
15693
16910
  : fees[mid];
15694
16911
  return {
15695
16912
  mean,
@@ -15762,11 +16979,12 @@ function getCircuitState(circuitSource) {
15762
16979
  * @param mxeProgramId - Public key of the MXE program.
15763
16980
  * @param rawCircuit - Raw circuit data as a Uint8Array.
15764
16981
  * @param logging - Whether to log progress (default: true).
15765
- * @param chunkSize - Number of upload transactions to send in parallel (default: 500).
16982
+ * @param chunkSize - Number of upload transactions to send in parallel. Defaults to
16983
+ * {@link DEFAULT_UPLOAD_TX_BATCH_SIZE}.
15766
16984
  * @param confirmOptions - Transaction confirmation options.
15767
16985
  * @returns Array of transaction signatures for all upload and finalize transactions.
15768
16986
  */
15769
- async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, logging = true, chunkSize = 500, confirmOptions) {
16987
+ async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, logging = true, chunkSize = DEFAULT_UPLOAD_TX_BATCH_SIZE, confirmOptions) {
15770
16988
  const compDefAccInfo = getCompDefAccInfo(circuitName, mxeProgramId);
15771
16989
  const program = getArciumProgram(provider);
15772
16990
  const compDefAcc = await program.account.computationDefinitionAccount.fetch(compDefAccInfo.pubkey);
@@ -15776,12 +16994,12 @@ async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, lo
15776
16994
  optionalLog(logging, `Circuit ${circuitName} skipped: ${state}`);
15777
16995
  return [];
15778
16996
  }
15779
- // 9 = 8-byte discriminator + 1-byte bump for ComputationDefinitionRaw account
15780
- const numAccs = Math.ceil(rawCircuit.length / (MAX_ACCOUNT_SIZE - 9));
16997
+ assertRawCircuitUploadLength(rawCircuit.length, compDefAcc.definition.circuitLen, circuitName);
16998
+ const numAccs = getRawCircuitAccountCount(rawCircuit.length);
15781
16999
  const sigs = [];
15782
17000
  const uploadPromises = [];
15783
17001
  for (let i = 0; i < numAccs; i++) {
15784
- uploadPromises.push(uploadToCircuitAcc(provider, program, rawCircuit.subarray(i * (MAX_ACCOUNT_SIZE - 9), (i + 1) * (MAX_ACCOUNT_SIZE - 9)), i, compDefAccInfo, mxeProgramId, logging, chunkSize, confirmOptions));
17002
+ 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));
15785
17003
  }
15786
17004
  sigs.push(...(await Promise.all(uploadPromises)).flat());
15787
17005
  const finalizeCompDefTx = await buildFinalizeCompDefTx(provider, compDefAccInfo.offset, mxeProgramId);
@@ -15797,8 +17015,6 @@ async function uploadCircuit(provider, circuitName, mxeProgramId, rawCircuit, lo
15797
17015
  */
15798
17016
  async function buildFinalizeCompDefTx(provider, compDefOffset, mxeProgramId) {
15799
17017
  const program = getArciumProgram(provider);
15800
- const compDefOffsetBuffer = Buffer.alloc(OFFSET_BUFFER_SIZE);
15801
- compDefOffsetBuffer.writeUInt32LE(compDefOffset, 0);
15802
17018
  return program.methods
15803
17019
  .finalizeComputationDefinition(compDefOffset, mxeProgramId)
15804
17020
  .accounts({
@@ -15806,12 +17022,11 @@ async function buildFinalizeCompDefTx(provider, compDefOffset, mxeProgramId) {
15806
17022
  })
15807
17023
  .transaction();
15808
17024
  }
15809
- async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitIndex, compDefAccInfo, mxeProgramId, shouldLog = true, chunkSize = 500, confirmOptions) {
17025
+ async function uploadToCircuitAcc(provider, program, rawCircuitPart, rawCircuitIndex, compDefAccInfo, mxeProgramId, shouldLog = true, chunkSize = DEFAULT_UPLOAD_TX_BATCH_SIZE, confirmOptions) {
15810
17026
  const rawCircuitPda = getRawCircuitAccAddress(compDefAccInfo.pubkey, rawCircuitIndex);
15811
17027
  const existingAcc = await provider.connection.getAccountInfo(rawCircuitPda);
15812
17028
  // Skip entirely if account exists with correct size (pre-seeded at genesis or already uploaded)
15813
- // Account layout: 8-byte discriminator + 1-byte bump + circuit data
15814
- const requiredAccountSize = rawCircuitPart.length + 9;
17029
+ const requiredAccountSize = rawCircuitPart.length + RAW_CIRCUIT_ACCOUNT_HEADER_SIZE;
15815
17030
  if (existingAcc !== null && existingAcc.data.length >= requiredAccountSize) {
15816
17031
  optionalLog(shouldLog, `Raw circuit acc ${rawCircuitIndex} already exists with sufficient size, skipping`);
15817
17032
  return [];
@@ -15945,18 +17160,8 @@ function getArciumProgram(provider) {
15945
17160
  */
15946
17161
  function getCompDefAccInfo(circuitName, mxeProgramId) {
15947
17162
  const offset = getCompDefAccOffset(circuitName);
15948
- const pda = getCompDefAccPDA(getArciumProgramId(), mxeProgramId, offset);
15949
- return { pubkey: pda, offset: Buffer.from(offset).readUInt32LE(0) };
15950
- }
15951
- /**
15952
- * Return the PDA for a computation definition account, given the program ID, MXE program ID, and offset.
15953
- * @param arciumProgramId - Public key of the Arcium program.
15954
- * @param mxeProgramId - Public key of the MXE program.
15955
- * @param offset - Offset as a Uint8Array.
15956
- * @returns PDA for the computation definition account.
15957
- */
15958
- function getCompDefAccPDA(arciumProgramId, mxeProgramId, offset) {
15959
- return anchor__namespace.web3.PublicKey.findProgramAddressSync([Buffer.from(COMP_DEF_ACC_SEED, 'utf-8'), mxeProgramId.toBuffer(), offset], arciumProgramId)[0];
17163
+ const offsetNumber = Buffer.from(offset).readUInt32LE(0);
17164
+ return { pubkey: getCompDefAccAddress(mxeProgramId, offsetNumber), offset: offsetNumber };
15960
17165
  }
15961
17166
  /**
15962
17167
  * Initialize an MXE (part 1). Due to Solana's 10KB per-instruction allocation limit,
@@ -15964,13 +17169,15 @@ function getCompDefAccPDA(arciumProgramId, mxeProgramId, offset) {
15964
17169
  * Call initMxePart2 afterwards to finish allocation and add keygen to mempool.
15965
17170
  * @param provider - Anchor provider to use for transactions.
15966
17171
  * @param mxeProgramId - Public key to use as the MXE program ID.
17172
+ * @param recoveryPeers - Array of 100 node offsets for recovery peers (0 for unused slots).
15967
17173
  * @param confirmOptions - Transaction confirmation options.
15968
17174
  * @returns Transaction signature.
15969
17175
  */
15970
- async function initMxePart1(provider, mxeProgramId, confirmOptions) {
17176
+ async function initMxePart1(provider, mxeProgramId, recoveryPeers, confirmOptions) {
15971
17177
  const program = getArciumProgram(provider);
17178
+ const paddedRecoveryPeers = normalizeRecoveryPeers(recoveryPeers);
15972
17179
  const tx = await program.methods
15973
- .initMxePart1()
17180
+ .initMxePart1(paddedRecoveryPeers)
15974
17181
  .accountsPartial({
15975
17182
  signer: provider.publicKey,
15976
17183
  mxeProgram: mxeProgramId,
@@ -15985,9 +17192,12 @@ async function initMxePart1(provider, mxeProgramId, confirmOptions) {
15985
17192
  * @param provider - Anchor provider to use for transactions.
15986
17193
  * @param clusterOffset - Cluster offset to associate with the MXE.
15987
17194
  * @param mxeProgramId - Public key to use as the MXE program ID.
15988
- * @param recoveryPeers - Array of 100 node offsets for recovery peers (0 for unused slots).
15989
17195
  * @param keygenOffset - Computation offset for the keygen computation.
15990
17196
  * @param keyRecoveryInitOffset - Computation offset for the key_recovery_init computation.
17197
+ * @param recoveryPeers - Recovery peer node offsets. Slots set to 0 are treated as unused.
17198
+ * The non-zero count must be either 0 (recovery disabled) or at least
17199
+ * `MIN_RECOVERY_PEERS` (4). The array is padded with zeros up to
17200
+ * `MAX_RECOVERY_PEERS` (100); passing more than that throws.
15991
17201
  * @param lutOffset - Lookup table offset for the MXE's address lookup table.
15992
17202
  * @param mxeAuthority - Optional authority for the MXE (defaults to provider.publicKey).
15993
17203
  * @param confirmOptions - Transaction confirmation options.
@@ -15995,16 +17205,8 @@ async function initMxePart1(provider, mxeProgramId, confirmOptions) {
15995
17205
  */
15996
17206
  async function initMxePart2(provider, clusterOffset, mxeProgramId, keygenOffset, keyRecoveryInitOffset, recoveryPeers, lutOffset, mxeAuthority, confirmOptions) {
15997
17207
  const program = getArciumProgram(provider);
15998
- // Ensure recoveryPeers has exactly 100 elements
15999
- const paddedRecoveryPeers = [...recoveryPeers];
16000
- while (paddedRecoveryPeers.length < 100) {
16001
- paddedRecoveryPeers.push(0);
16002
- }
16003
- if (paddedRecoveryPeers.length > 100) {
16004
- throw new Error('recoveryPeers must have at most 100 elements');
16005
- }
16006
17208
  const tx = await program.methods
16007
- .initMxePart2(clusterOffset, mxeProgramId, paddedRecoveryPeers, keygenOffset, keyRecoveryInitOffset, lutOffset)
17209
+ .initMxePart2(clusterOffset, keygenOffset, keyRecoveryInitOffset, lutOffset)
16008
17210
  .accountsPartial({
16009
17211
  signer: provider.publicKey,
16010
17212
  mxeProgram: mxeProgramId,
@@ -16015,6 +17217,14 @@ async function initMxePart2(provider, clusterOffset, mxeProgramId, keygenOffset,
16015
17217
  .transaction();
16016
17218
  return signAndSendWithBlockhash(provider, tx, await provider.connection.getLatestBlockhash({ commitment: confirmOptions?.commitment || 'confirmed' }), confirmOptions);
16017
17219
  }
17220
+ /**
17221
+ * Reclaim the rent locked in a finished computation account.
17222
+ * @param provider - Anchor provider to use for transactions.
17223
+ * @param clusterOffset - Offset of the cluster that ran the computation.
17224
+ * @param computationOffset - Offset of the computation whose rent is being claimed.
17225
+ * @param confirmOptions - Transaction confirmation options.
17226
+ * @returns Transaction signature.
17227
+ */
16018
17228
  async function claimComputationRent(provider, clusterOffset, computationOffset, confirmOptions) {
16019
17229
  const program = getArciumProgram(provider);
16020
17230
  const tx = await program.methods
@@ -16163,6 +17373,7 @@ exports.getArciumAccountBaseSeed = getArciumAccountBaseSeed;
16163
17373
  exports.getArciumEnv = getArciumEnv;
16164
17374
  exports.getArciumProgram = getArciumProgram;
16165
17375
  exports.getArciumProgramId = getArciumProgramId;
17376
+ exports.getArciumSignerAccAddress = getArciumSignerAccAddress;
16166
17377
  exports.getArxNodeAccAddress = getArxNodeAccAddress;
16167
17378
  exports.getCircuitState = getCircuitState;
16168
17379
  exports.getClockAccAddress = getClockAccAddress;
@@ -16173,6 +17384,7 @@ exports.getComputationAccAddress = getComputationAccAddress;
16173
17384
  exports.getComputationsInMempool = getComputationsInMempool;
16174
17385
  exports.getExecutingPoolAccAddress = getExecutingPoolAccAddress;
16175
17386
  exports.getExecutingPoolAccInfo = getExecutingPoolAccInfo;
17387
+ exports.getFailureClaimAccAddress = getFailureClaimAccAddress;
16176
17388
  exports.getFeePoolAccAddress = getFeePoolAccAddress;
16177
17389
  exports.getLookupTableAddress = getLookupTableAddress;
16178
17390
  exports.getMXEAccAddress = getMXEAccAddress;
@@ -16182,8 +17394,10 @@ exports.getMempoolAccAddress = getMempoolAccAddress;
16182
17394
  exports.getMempoolAccInfo = getMempoolAccInfo;
16183
17395
  exports.getMempoolPriorityFeeStats = getMempoolPriorityFeeStats;
16184
17396
  exports.getMxeRecoveryAccAddress = getMxeRecoveryAccAddress;
17397
+ exports.getOperatorAccAddress = getOperatorAccAddress;
16185
17398
  exports.getRawCircuitAccAddress = getRawCircuitAccAddress;
16186
17399
  exports.getRecoveryClusterAccAddress = getRecoveryClusterAccAddress;
17400
+ exports.getRecoveryPeerAccAddress = getRecoveryPeerAccAddress;
16187
17401
  exports.initMxePart1 = initMxePart1;
16188
17402
  exports.initMxePart2 = initMxePart2;
16189
17403
  exports.isNullRef = isNullRef;