@zhoujun_aptos/octopus-ts-sdk-min 0.22.5 → 0.22.7
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/dist/common/index.d.ts +39 -4
- package/dist/common/index.js +328 -204
- package/dist/common/index.js.map +1 -1
- package/dist/esm/index.d.mts +39 -4
- package/dist/esm/index.mjs +329 -205
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/common/index.js
CHANGED
|
@@ -2412,11 +2412,82 @@ var worker_config_exports = {};
|
|
|
2412
2412
|
__export(worker_config_exports, {
|
|
2413
2413
|
WorkerConfig: () => WorkerConfig,
|
|
2414
2414
|
get: () => get,
|
|
2415
|
+
getAsync: () => getAsync,
|
|
2415
2416
|
randWorker: () => randWorker,
|
|
2416
2417
|
view: () => view
|
|
2417
2418
|
});
|
|
2418
2419
|
var import_ts_sdk11 = require("@aptos-labs/ts-sdk");
|
|
2419
2420
|
var import_utils16 = require("@noble/curves/utils");
|
|
2421
|
+
|
|
2422
|
+
// src/result.ts
|
|
2423
|
+
var Result = class _Result {
|
|
2424
|
+
isOk;
|
|
2425
|
+
okValue;
|
|
2426
|
+
errValue;
|
|
2427
|
+
extra;
|
|
2428
|
+
constructor({ isOk, okValue, errValue, extra }) {
|
|
2429
|
+
this.isOk = isOk;
|
|
2430
|
+
this.okValue = okValue;
|
|
2431
|
+
this.errValue = errValue;
|
|
2432
|
+
this.extra = extra;
|
|
2433
|
+
}
|
|
2434
|
+
static Ok(args) {
|
|
2435
|
+
return new _Result({ isOk: true, okValue: args.value, extra: args.extra });
|
|
2436
|
+
}
|
|
2437
|
+
static Err(args) {
|
|
2438
|
+
return new _Result({ isOk: false, errValue: args.error, extra: args.extra });
|
|
2439
|
+
}
|
|
2440
|
+
/**
|
|
2441
|
+
* You write a closure that either returns a T or throws, and we wrap it to return a Result<T>.
|
|
2442
|
+
* Your closure is also given an `extra` dictionary to record additional context.
|
|
2443
|
+
*/
|
|
2444
|
+
static capture({ task, recordsExecutionTimeMs = false }) {
|
|
2445
|
+
const start = performance.now();
|
|
2446
|
+
var extra = {};
|
|
2447
|
+
var error;
|
|
2448
|
+
var okValue;
|
|
2449
|
+
try {
|
|
2450
|
+
okValue = task(extra);
|
|
2451
|
+
} catch (caught) {
|
|
2452
|
+
error = caught;
|
|
2453
|
+
} finally {
|
|
2454
|
+
if (recordsExecutionTimeMs) {
|
|
2455
|
+
extra["_sdk_execution_time_ms"] = performance.now() - start;
|
|
2456
|
+
}
|
|
2457
|
+
if (error !== void 0) {
|
|
2458
|
+
return _Result.Err({ error, extra });
|
|
2459
|
+
} else {
|
|
2460
|
+
return _Result.Ok({ value: okValue, extra });
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
/**
|
|
2465
|
+
* You write an async closure that either returns a T or throws, and we wrap it to return a Result<T>.
|
|
2466
|
+
* Your closure is also given an `extra` dictionary to record additional context.
|
|
2467
|
+
*/
|
|
2468
|
+
static async captureAsync({ task, recordsExecutionTimeMs = false }) {
|
|
2469
|
+
var extra = {};
|
|
2470
|
+
const start = performance.now();
|
|
2471
|
+
var error;
|
|
2472
|
+
var okValue;
|
|
2473
|
+
try {
|
|
2474
|
+
okValue = await task(extra);
|
|
2475
|
+
} catch (caught) {
|
|
2476
|
+
error = caught;
|
|
2477
|
+
} finally {
|
|
2478
|
+
if (recordsExecutionTimeMs) {
|
|
2479
|
+
extra["_sdk_execution_time_ms"] = performance.now() - start;
|
|
2480
|
+
}
|
|
2481
|
+
if (error !== void 0) {
|
|
2482
|
+
return _Result.Err({ error, extra });
|
|
2483
|
+
} else {
|
|
2484
|
+
return _Result.Ok({ value: okValue, extra });
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
};
|
|
2489
|
+
|
|
2490
|
+
// src/worker_config.ts
|
|
2420
2491
|
var WorkerConfig = class _WorkerConfig {
|
|
2421
2492
|
expiryTimeMicrosecs;
|
|
2422
2493
|
endpoint;
|
|
@@ -2501,6 +2572,23 @@ async function get(workerEndpoint) {
|
|
|
2501
2572
|
const hex = await response.text();
|
|
2502
2573
|
return WorkerConfig.fromHex(hex);
|
|
2503
2574
|
}
|
|
2575
|
+
async function getAsync(workerEndpoint) {
|
|
2576
|
+
const task = async (extra) => {
|
|
2577
|
+
const url = `${workerEndpoint}/config_bcs`;
|
|
2578
|
+
extra["url"] = url;
|
|
2579
|
+
const response = await fetch(url, {
|
|
2580
|
+
method: "GET"
|
|
2581
|
+
});
|
|
2582
|
+
extra["responseStatus"] = response.status;
|
|
2583
|
+
extra["responseStatusText"] = response.statusText;
|
|
2584
|
+
if (!response.ok) {
|
|
2585
|
+
throw `Failed to fetch worker config: ${response.status} ${response.statusText}`;
|
|
2586
|
+
}
|
|
2587
|
+
const hex = await response.text();
|
|
2588
|
+
return WorkerConfig.fromHex(hex);
|
|
2589
|
+
};
|
|
2590
|
+
return await Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
2591
|
+
}
|
|
2504
2592
|
function randWorker() {
|
|
2505
2593
|
const addr = new import_ts_sdk11.AccountAddress(utils_exports.randBytes(32));
|
|
2506
2594
|
const encDk = keygen2();
|
|
@@ -2717,64 +2805,76 @@ var ProofOfPermission = class _ProofOfPermission {
|
|
|
2717
2805
|
}
|
|
2718
2806
|
};
|
|
2719
2807
|
async function verifyPermission({ fullDecryptionDomain, proof }) {
|
|
2720
|
-
const
|
|
2721
|
-
|
|
2808
|
+
const task = async (extra) => {
|
|
2809
|
+
const aptos = createAptos(getChainNameFromChainId(fullDecryptionDomain.getAptosContractID().chainId));
|
|
2810
|
+
const [verifySigResult, checkAuthKeyResult, checkPermissionResult] = await Promise.all([
|
|
2811
|
+
verifySig({ aptos, fullDecryptionDomain, proof }),
|
|
2812
|
+
checkAuthKey({ aptos, userAddr: proof.userAddr, publicKey: proof.publicKey }),
|
|
2813
|
+
checkPermission({ aptos, fullDecryptionDomain, proof })
|
|
2814
|
+
]);
|
|
2815
|
+
extra["verifySigResult"] = verifySigResult;
|
|
2816
|
+
extra["checkAuthKeyResult"] = checkAuthKeyResult;
|
|
2817
|
+
extra["checkPermissionResult"] = checkPermissionResult;
|
|
2818
|
+
if (!verifySigResult.isOk || !checkAuthKeyResult.isOk || !checkPermissionResult.isOk) {
|
|
2819
|
+
throw "one or more sub-checks failed";
|
|
2820
|
+
}
|
|
2821
|
+
};
|
|
2822
|
+
return await Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
2823
|
+
}
|
|
2824
|
+
async function verifySig({ aptos, fullDecryptionDomain, proof }) {
|
|
2825
|
+
const task = async (extra) => {
|
|
2722
2826
|
const msgToSign = fullDecryptionDomain.toPrettyMessage();
|
|
2723
2827
|
const msgToSignHex = (0, import_utils17.bytesToHex)(new TextEncoder().encode(msgToSign));
|
|
2724
|
-
const
|
|
2725
|
-
const
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
}
|
|
2828
|
+
const fullMessageSeemsFromPetra = proof.fullMessage.includes(msgToSign);
|
|
2829
|
+
const fullMessageSeemsFromAptosConnect = proof.fullMessage.includes(msgToSignHex);
|
|
2830
|
+
extra["msgToSign"] = msgToSign;
|
|
2831
|
+
extra["msgToSignHex"] = msgToSignHex;
|
|
2832
|
+
extra["fullMessageSeemsFromPetra"] = fullMessageSeemsFromPetra;
|
|
2833
|
+
extra["fullMessageSeemsFromAptosConnect"] = fullMessageSeemsFromAptosConnect;
|
|
2834
|
+
if (!fullMessageSeemsFromPetra && !fullMessageSeemsFromAptosConnect) throw "fullMessage does not contain fullDecryptionDomain or its hex";
|
|
2835
|
+
const sigValid = await proof.publicKey.verifySignatureAsync({
|
|
2836
|
+
aptosConfig: aptos.config,
|
|
2837
|
+
message: proof.fullMessage,
|
|
2838
|
+
signature: proof.signature
|
|
2839
|
+
});
|
|
2840
|
+
if (!sigValid) throw "verifySignatureAsync failed";
|
|
2736
2841
|
};
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
console.log(`onChainHex: ${onChainHex}`);
|
|
2744
|
-
console.log(`userHex : ${userHex}`);
|
|
2745
|
-
return onChainHex === userHex;
|
|
2746
|
-
} catch (error) {
|
|
2747
|
-
return false;
|
|
2842
|
+
return await Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
2843
|
+
}
|
|
2844
|
+
async function checkAuthKey({ aptos, userAddr, publicKey }) {
|
|
2845
|
+
const task = async (extra) => {
|
|
2846
|
+
if (!(publicKey instanceof import_ts_sdk12.AccountPublicKey)) {
|
|
2847
|
+
throw "publicKey is not an AccountPublicKey";
|
|
2748
2848
|
}
|
|
2849
|
+
const onChainAuthKeyBytes = await getAccountAuthKeyBytes(aptos, userAddr);
|
|
2850
|
+
const userAuthKeyBytes = publicKey.authKey().bcsToBytes();
|
|
2851
|
+
const onChainHex = (0, import_utils17.bytesToHex)(onChainAuthKeyBytes);
|
|
2852
|
+
const userHex = (0, import_utils17.bytesToHex)(userAuthKeyBytes);
|
|
2853
|
+
extra["onChainHex"] = onChainHex;
|
|
2854
|
+
extra["userHex"] = userHex;
|
|
2855
|
+
if (onChainHex !== userHex) throw "on-chain auth key does not match user auth key";
|
|
2749
2856
|
};
|
|
2750
|
-
|
|
2857
|
+
return await Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
2858
|
+
}
|
|
2859
|
+
async function checkPermission({ aptos, fullDecryptionDomain, proof }) {
|
|
2860
|
+
const task = async (extra) => {
|
|
2751
2861
|
const contractId = fullDecryptionDomain.getAptosContractID();
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2862
|
+
const viewFunctionInvocationResult = await view2({
|
|
2863
|
+
aptos,
|
|
2864
|
+
func: `${contractId.moduleAddr.toStringLong()}::${contractId.moduleName}::${contractId.functionName}`,
|
|
2865
|
+
typeArguments: [],
|
|
2866
|
+
functionArguments: [proof.userAddr, fullDecryptionDomain.domain]
|
|
2867
|
+
});
|
|
2868
|
+
extra["viewFunctionInvocationResult"] = viewFunctionInvocationResult;
|
|
2869
|
+
if (!viewFunctionInvocationResult.isOk) {
|
|
2870
|
+
throw "view function invocation failed";
|
|
2871
|
+
}
|
|
2872
|
+
const returnedMoveValue = viewFunctionInvocationResult.okValue;
|
|
2873
|
+
if (returnedMoveValue?.toString() !== "true") {
|
|
2874
|
+
throw "access control contract return value is not true";
|
|
2762
2875
|
}
|
|
2763
2876
|
};
|
|
2764
|
-
|
|
2765
|
-
taskVerifySig(),
|
|
2766
|
-
taskCheckAuthKey(),
|
|
2767
|
-
taskCheckPermission()
|
|
2768
|
-
]);
|
|
2769
|
-
if (!sigIsValid) {
|
|
2770
|
-
throw new Error("Signature invalid.");
|
|
2771
|
-
}
|
|
2772
|
-
if (!authKeyMatches) {
|
|
2773
|
-
throw new Error("Authentication key mismatch: on-chain key does not match provided public key.");
|
|
2774
|
-
}
|
|
2775
|
-
if (!userIsPermitted) {
|
|
2776
|
-
throw new Error("Permission denied.");
|
|
2777
|
-
}
|
|
2877
|
+
return await Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
2778
2878
|
}
|
|
2779
2879
|
function getChainNameFromChainId(chainId) {
|
|
2780
2880
|
if (chainId === 1) {
|
|
@@ -2811,18 +2911,22 @@ async function getAccountAuthKeyBytes(aptos, address) {
|
|
|
2811
2911
|
const accountInfo = await aptos.getAccountInfo({ accountAddress: address });
|
|
2812
2912
|
return (0, import_utils17.hexToBytes)(accountInfo.authentication_key.replace("0x", ""));
|
|
2813
2913
|
}
|
|
2814
|
-
async function view2(aptos, func, typeArguments, functionArguments) {
|
|
2815
|
-
const
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2914
|
+
async function view2({ aptos, func, typeArguments, functionArguments }) {
|
|
2915
|
+
const task = async (extra) => {
|
|
2916
|
+
const returnedMoveValues = await aptos.view({
|
|
2917
|
+
payload: {
|
|
2918
|
+
function: func,
|
|
2919
|
+
typeArguments,
|
|
2920
|
+
functionArguments
|
|
2921
|
+
}
|
|
2922
|
+
});
|
|
2923
|
+
extra["returnedMoveValues"] = returnedMoveValues;
|
|
2924
|
+
if (returnedMoveValues.length === 0) {
|
|
2925
|
+
throw `aptos.view returned an empty list`;
|
|
2820
2926
|
}
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
}
|
|
2825
|
-
return result[0];
|
|
2927
|
+
return returnedMoveValues[0];
|
|
2928
|
+
};
|
|
2929
|
+
return await Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
2826
2930
|
}
|
|
2827
2931
|
|
|
2828
2932
|
// src/threshold-ibe/solana.ts
|
|
@@ -2923,76 +3027,107 @@ var ProofOfPermission2 = class _ProofOfPermission {
|
|
|
2923
3027
|
}
|
|
2924
3028
|
};
|
|
2925
3029
|
async function verifyPermission2({ fullDecryptionDomain, proof }) {
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
}
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
instructions = txn.instructions.map((ix) => ({
|
|
2943
|
-
programId: ix.programId,
|
|
2944
|
-
data: Buffer.from(ix.data)
|
|
2945
|
-
}));
|
|
2946
|
-
}
|
|
2947
|
-
if (instructions.length !== 1) {
|
|
2948
|
-
throw new Error(`transaction must contain exactly 1 instruction, found ${instructions.length}`);
|
|
2949
|
-
}
|
|
2950
|
-
const instruction = instructions[0];
|
|
2951
|
-
if (!instruction.programId.equals(fullDecryptionDomain.getSolanaContractID().programId)) {
|
|
2952
|
-
throw new Error(`transaction instruction program ID (${instruction.programId.toString()}) does not match contract program ID`);
|
|
2953
|
-
}
|
|
2954
|
-
const instructionData = instruction.data;
|
|
2955
|
-
if (instructionData.length < 12) {
|
|
2956
|
-
throw new Error("instruction data too short (must be at least 12 bytes: 8-byte discriminator + 4-byte Vec length)");
|
|
2957
|
-
}
|
|
2958
|
-
const paramData = instructionData.slice(8);
|
|
2959
|
-
const vecLength = paramData.readUInt32LE(0);
|
|
2960
|
-
if (paramData.length < 4 + vecLength) {
|
|
2961
|
-
throw new Error(`instruction data incomplete: expected ${4 + vecLength} bytes after discriminator, found ${paramData.length}`);
|
|
2962
|
-
}
|
|
2963
|
-
const fullBlobNameBytes = paramData.slice(4, 4 + vecLength);
|
|
2964
|
-
const expectedParamDataLength = 4 + vecLength;
|
|
2965
|
-
if (paramData.length > expectedParamDataLength) {
|
|
2966
|
-
throw new Error(`instruction data has extra bytes: expected exactly ${expectedParamDataLength} bytes after discriminator, found ${paramData.length}`);
|
|
3030
|
+
var extra = {};
|
|
3031
|
+
try {
|
|
3032
|
+
const txn = proof.inner;
|
|
3033
|
+
const validateTxnResult = validateTxn({ txn, fullDecryptionDomain });
|
|
3034
|
+
if (!validateTxnResult.isOk) {
|
|
3035
|
+
extra["causedBy"] = validateTxnResult.extra;
|
|
3036
|
+
throw "transaction is invalid";
|
|
3037
|
+
}
|
|
3038
|
+
const simulationResult = await assertTransactionSimulationPasses(txn, fullDecryptionDomain.getSolanaContractID().knownChainName);
|
|
3039
|
+
if (!simulationResult.isOk) {
|
|
3040
|
+
extra["causedBy"] = simulationResult.extra;
|
|
3041
|
+
throw "transaction simulation failed";
|
|
3042
|
+
}
|
|
3043
|
+
return Result.Ok({ value: void 0, extra });
|
|
3044
|
+
} catch (error) {
|
|
3045
|
+
return Result.Err({ error, extra });
|
|
2967
3046
|
}
|
|
2968
|
-
|
|
2969
|
-
|
|
3047
|
+
}
|
|
3048
|
+
function validateTxn({ txn, fullDecryptionDomain }) {
|
|
3049
|
+
try {
|
|
3050
|
+
let instructions;
|
|
3051
|
+
if (txn instanceof import_web3.VersionedTransaction) {
|
|
3052
|
+
const message = txn.message;
|
|
3053
|
+
instructions = message.compiledInstructions.map((ix) => {
|
|
3054
|
+
if (ix.programIdIndex >= message.staticAccountKeys.length) {
|
|
3055
|
+
throw `some program ID index is out of bounds for static account keys (are you using address table lookups? threshold-ibe does not support it yet)`;
|
|
3056
|
+
}
|
|
3057
|
+
const programId = message.staticAccountKeys[ix.programIdIndex];
|
|
3058
|
+
return { programId, data: Buffer.from(ix.data) };
|
|
3059
|
+
});
|
|
3060
|
+
} else {
|
|
3061
|
+
instructions = txn.instructions.map((ix) => ({
|
|
3062
|
+
programId: ix.programId,
|
|
3063
|
+
data: Buffer.from(ix.data)
|
|
3064
|
+
}));
|
|
3065
|
+
}
|
|
3066
|
+
if (instructions.length !== 1) throw `transaction must contain exactly 1 instruction`;
|
|
3067
|
+
const instruction = instructions[0];
|
|
3068
|
+
if (!instruction.programId.equals(fullDecryptionDomain.getSolanaContractID().programId)) {
|
|
3069
|
+
throw `transaction instruction program ID does not match contract program ID`;
|
|
3070
|
+
}
|
|
3071
|
+
const instructionData = instruction.data;
|
|
3072
|
+
if (instructionData.length < 12) {
|
|
3073
|
+
throw "instruction data too short";
|
|
3074
|
+
}
|
|
3075
|
+
const paramData = instructionData.slice(8);
|
|
3076
|
+
const vecLength = paramData.readUInt32LE(0);
|
|
3077
|
+
if (paramData.length < 4 + vecLength) throw `instruction data incomplete`;
|
|
3078
|
+
const domainAsTxnParam = paramData.slice(4, 4 + vecLength);
|
|
3079
|
+
const expectedParamDataLength = 4 + vecLength;
|
|
3080
|
+
if (paramData.length > expectedParamDataLength) {
|
|
3081
|
+
throw `instruction data has extra bytes`;
|
|
3082
|
+
}
|
|
3083
|
+
if ((0, import_utils18.bytesToHex)(domainAsTxnParam) !== (0, import_utils18.bytesToHex)(fullDecryptionDomain.domain)) {
|
|
3084
|
+
throw `instruction parameter does not match decryptionContext.domain`;
|
|
3085
|
+
}
|
|
3086
|
+
return Result.Ok({ value: void 0 });
|
|
3087
|
+
} catch (error) {
|
|
3088
|
+
return Result.Err({ error });
|
|
2970
3089
|
}
|
|
2971
3090
|
}
|
|
2972
3091
|
async function assertTransactionSimulationPasses(txn, chainName) {
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
rpcUrl
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
3092
|
+
var extra = {};
|
|
3093
|
+
var error;
|
|
3094
|
+
const start = performance.now();
|
|
3095
|
+
try {
|
|
3096
|
+
let rpcUrl;
|
|
3097
|
+
if (chainName === "localnet" || chainName === "localhost") {
|
|
3098
|
+
rpcUrl = "http://127.0.0.1:8899";
|
|
3099
|
+
} else if (chainName === "devnet") {
|
|
3100
|
+
rpcUrl = "https://api.devnet.solana.com";
|
|
3101
|
+
} else if (chainName === "testnet") {
|
|
3102
|
+
rpcUrl = "https://api.testnet.solana.com";
|
|
3103
|
+
} else if (chainName === "mainnet-beta") {
|
|
3104
|
+
rpcUrl = "https://api.mainnet-beta.solana.com";
|
|
3105
|
+
} else {
|
|
3106
|
+
extra["chainName"] = chainName;
|
|
3107
|
+
throw `unsupported chain name`;
|
|
3108
|
+
}
|
|
3109
|
+
const connection = new import_web3.Connection(rpcUrl, "confirmed");
|
|
3110
|
+
let simulation;
|
|
3111
|
+
if (txn instanceof import_web3.VersionedTransaction) {
|
|
3112
|
+
simulation = await connection.simulateTransaction(txn, {
|
|
3113
|
+
sigVerify: true
|
|
3114
|
+
});
|
|
3115
|
+
} else {
|
|
3116
|
+
simulation = await connection.simulateTransaction(txn);
|
|
3117
|
+
}
|
|
3118
|
+
if (simulation.value.err) {
|
|
3119
|
+
extra["simulationError"] = simulation.value.err;
|
|
3120
|
+
throw `transaction simulation failed`;
|
|
3121
|
+
}
|
|
3122
|
+
} catch (caught) {
|
|
3123
|
+
error = caught;
|
|
3124
|
+
} finally {
|
|
3125
|
+
extra["executionTimeMs"] = performance.now() - start;
|
|
3126
|
+
if (error !== void 0) {
|
|
3127
|
+
return Result.Err({ error, extra });
|
|
3128
|
+
} else {
|
|
3129
|
+
return Result.Ok({ value: void 0, extra });
|
|
3130
|
+
}
|
|
2996
3131
|
}
|
|
2997
3132
|
}
|
|
2998
3133
|
|
|
@@ -3098,11 +3233,16 @@ var EncryptionKey2 = class _EncryptionKey {
|
|
|
3098
3233
|
this.ibeMpks = ibeMpks;
|
|
3099
3234
|
}
|
|
3100
3235
|
static async fetch({ committee }) {
|
|
3101
|
-
const
|
|
3102
|
-
const
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3236
|
+
const task = async (extra) => {
|
|
3237
|
+
const workerConfigGetResults = await Promise.all(committee.workerEndpoints.map(async (endpoint) => {
|
|
3238
|
+
return worker_config_exports.getAsync(endpoint);
|
|
3239
|
+
}));
|
|
3240
|
+
extra["workerConfigGetResults"] = workerConfigGetResults;
|
|
3241
|
+
if (workerConfigGetResults.some((result) => !result.isOk)) throw "failed to get all worker configs";
|
|
3242
|
+
const ibeMpks = workerConfigGetResults.map((result) => result.okValue.ibeMpk);
|
|
3243
|
+
return new _EncryptionKey({ ibeMpks });
|
|
3244
|
+
};
|
|
3245
|
+
return await Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
3106
3246
|
}
|
|
3107
3247
|
};
|
|
3108
3248
|
var DecryptionKey2 = class _DecryptionKey {
|
|
@@ -3111,43 +3251,43 @@ var DecryptionKey2 = class _DecryptionKey {
|
|
|
3111
3251
|
this.ibeDecryptionKeys = ibeDecryptionKeys;
|
|
3112
3252
|
}
|
|
3113
3253
|
static async fetch({ committee, contractId, domain, proof }) {
|
|
3114
|
-
const
|
|
3115
|
-
|
|
3254
|
+
const task = async (extra) => {
|
|
3255
|
+
extra["committee"] = committee;
|
|
3256
|
+
const decKeyLoadResults = await Promise.all(committee.workerEndpoints.map(async (_workerEndpoint, index) => {
|
|
3257
|
+
return _DecryptionKey.fetchDecKeyShare({ committee, contractId, domain, proof, index });
|
|
3258
|
+
}));
|
|
3259
|
+
extra["decKeyLoadResults"] = decKeyLoadResults;
|
|
3260
|
+
const numSharesCollected = decKeyLoadResults.filter((loadResult) => loadResult.isOk).length;
|
|
3261
|
+
if (numSharesCollected < committee.threshold) throw `failed to collect enough shares`;
|
|
3262
|
+
const decKeyShares = decKeyLoadResults.map((loadResult) => loadResult.okValue ?? null);
|
|
3263
|
+
return new _DecryptionKey(decKeyShares);
|
|
3264
|
+
};
|
|
3265
|
+
return Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
3266
|
+
}
|
|
3267
|
+
static async fetchDecKeyShare({ committee, contractId, domain, proof, index }) {
|
|
3268
|
+
const task = async (extra) => {
|
|
3269
|
+
const targetWorkerEndpoint = committee.workerEndpoints[index];
|
|
3270
|
+
const task2 = WorkerTask.newThresholdIbeDecryptionKey({ committee, contractId, domain, proof });
|
|
3116
3271
|
const controller = new AbortController();
|
|
3117
3272
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
3118
3273
|
var response = null;
|
|
3119
3274
|
try {
|
|
3120
|
-
response = await fetch(
|
|
3275
|
+
response = await fetch(targetWorkerEndpoint, {
|
|
3121
3276
|
method: "POST",
|
|
3122
|
-
body:
|
|
3277
|
+
body: task2.toHex(),
|
|
3123
3278
|
signal: controller.signal
|
|
3124
3279
|
});
|
|
3125
3280
|
} catch (error) {
|
|
3126
3281
|
clearTimeout(timeoutId);
|
|
3127
3282
|
}
|
|
3128
|
-
if (response == null)
|
|
3129
|
-
return new WorkerTimedOut();
|
|
3130
|
-
}
|
|
3283
|
+
if (response == null) throw "worker is not responding";
|
|
3131
3284
|
const responseBody = await response.text();
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
}
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
return new CouldNotParseDecryptionKey(responseBody);
|
|
3139
|
-
}
|
|
3140
|
-
}));
|
|
3141
|
-
const numSharesCollected = decKeyLoadResults.filter((loadResult) => loadResult instanceof IdentityPrivateKey2).length;
|
|
3142
|
-
if (numSharesCollected < committee.threshold) {
|
|
3143
|
-
const workerResults = committee.workerEndpoints.map((workerEndpoint, i) => {
|
|
3144
|
-
const result = decKeyLoadResults[i];
|
|
3145
|
-
return `${workerEndpoint}: ${result instanceof IdentityPrivateKey2 ? "Success" : result.toDisplayString()}`;
|
|
3146
|
-
}).join(", ");
|
|
3147
|
-
throw new Error(`Failed to collect enough shares to decrypt. Collected ${numSharesCollected} shares, but needed ${committee.threshold} shares. Worker results: ${workerResults}`);
|
|
3148
|
-
}
|
|
3149
|
-
const decKeys = decKeyLoadResults.map((loadResult) => loadResult instanceof IdentityPrivateKey2 ? loadResult : null);
|
|
3150
|
-
return new _DecryptionKey(decKeys);
|
|
3285
|
+
extra["workerResponseStatus"] = response.status;
|
|
3286
|
+
extra["workerResponseBody"] = responseBody;
|
|
3287
|
+
if (response.status !== 200) throw `worker rejected: ${response.status}`;
|
|
3288
|
+
return IdentityPrivateKey2.fromHex(responseBody);
|
|
3289
|
+
};
|
|
3290
|
+
return Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
3151
3291
|
}
|
|
3152
3292
|
};
|
|
3153
3293
|
var Ciphertext7 = class _Ciphertext {
|
|
@@ -3343,41 +3483,25 @@ function decrypt7({ decryptionKey, ciphertext }) {
|
|
|
3343
3483
|
return decrypt6(symmKey, ciphertext.aesCiph);
|
|
3344
3484
|
}
|
|
3345
3485
|
async function verifyAndExtract({ ibeMsk, committee, contractId, domain, proof }) {
|
|
3346
|
-
const
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3486
|
+
const task = async (extra) => {
|
|
3487
|
+
extra["contractIdScheme"] = contractId.scheme;
|
|
3488
|
+
extra["proofScheme"] = proof.scheme;
|
|
3489
|
+
const decryptionContext = new FullDecryptionDomain({ committee, contractId, domain });
|
|
3490
|
+
if (contractId.scheme == ContractID3.SCHEME_APTOS && proof.scheme == ProofOfPermission3.SCHEME_APTOS) {
|
|
3491
|
+
const aptosResult = await verifyPermission({ fullDecryptionDomain: decryptionContext, proof: proof.inner });
|
|
3492
|
+
extra["verifyAptosResult"] = aptosResult;
|
|
3493
|
+
if (!aptosResult.isOk) throw "aptos verification failed";
|
|
3494
|
+
} else if (contractId.scheme == ContractID3.SCHEME_SOLANA && proof.scheme == ProofOfPermission3.SCHEME_SOLANA) {
|
|
3495
|
+
const solanaResult = await verifyPermission2({ fullDecryptionDomain: decryptionContext, proof: proof.inner });
|
|
3496
|
+
extra["verifySolanaResult"] = solanaResult;
|
|
3497
|
+
if (!solanaResult.isOk) throw "solana verification failed";
|
|
3498
|
+
} else {
|
|
3499
|
+
throw "unsupported scheme combination";
|
|
3500
|
+
}
|
|
3501
|
+
return extract2(ibeMsk, decryptionContext.toBytes());
|
|
3502
|
+
};
|
|
3503
|
+
return Result.captureAsync({ task, recordsExecutionTimeMs: true });
|
|
3355
3504
|
}
|
|
3356
|
-
var WorkerTimedOut = class {
|
|
3357
|
-
toDisplayString() {
|
|
3358
|
-
return "Timed out";
|
|
3359
|
-
}
|
|
3360
|
-
};
|
|
3361
|
-
var WorkerRejected = class {
|
|
3362
|
-
statusCode;
|
|
3363
|
-
responseBody;
|
|
3364
|
-
constructor(statusCode, responseBody) {
|
|
3365
|
-
this.statusCode = statusCode;
|
|
3366
|
-
this.responseBody = responseBody;
|
|
3367
|
-
}
|
|
3368
|
-
toDisplayString() {
|
|
3369
|
-
return `Rejected: ${this.statusCode} ${this.responseBody}`;
|
|
3370
|
-
}
|
|
3371
|
-
};
|
|
3372
|
-
var CouldNotParseDecryptionKey = class {
|
|
3373
|
-
originalHex;
|
|
3374
|
-
constructor(originalHex) {
|
|
3375
|
-
this.originalHex = originalHex;
|
|
3376
|
-
}
|
|
3377
|
-
toDisplayString() {
|
|
3378
|
-
return `Could not parse decryption key: ${this.originalHex}`;
|
|
3379
|
-
}
|
|
3380
|
-
};
|
|
3381
3505
|
|
|
3382
3506
|
// src/worker_task.ts
|
|
3383
3507
|
var TYPE_SILENT_SETUP_DECRYPTION_KEY = 5;
|
|
@@ -3607,16 +3731,16 @@ var DecryptionContext = class _DecryptionContext {
|
|
|
3607
3731
|
clearTimeout(timeoutId);
|
|
3608
3732
|
}
|
|
3609
3733
|
if (response == null) {
|
|
3610
|
-
return new
|
|
3734
|
+
return new WorkerTimedOut();
|
|
3611
3735
|
}
|
|
3612
3736
|
const responseBody = await response.text();
|
|
3613
3737
|
if (response.status !== 200) {
|
|
3614
|
-
return new
|
|
3738
|
+
return new WorkerRejected(response.status, responseBody);
|
|
3615
3739
|
}
|
|
3616
3740
|
try {
|
|
3617
3741
|
return IdentityPrivateKey2.fromHex(responseBody);
|
|
3618
3742
|
} catch (error) {
|
|
3619
|
-
return new
|
|
3743
|
+
return new CouldNotParseDecryptionKey(responseBody);
|
|
3620
3744
|
}
|
|
3621
3745
|
}));
|
|
3622
3746
|
const numSharesCollected = decKeyLoadResults.filter((loadResult) => loadResult instanceof IdentityPrivateKey2).length;
|
|
@@ -3722,12 +3846,12 @@ var Decryptor = class {
|
|
|
3722
3846
|
return decrypt6(symmKey, ciphertext.aesCiph);
|
|
3723
3847
|
}
|
|
3724
3848
|
};
|
|
3725
|
-
var
|
|
3849
|
+
var WorkerTimedOut = class {
|
|
3726
3850
|
toDisplayString() {
|
|
3727
3851
|
return "Timed out";
|
|
3728
3852
|
}
|
|
3729
3853
|
};
|
|
3730
|
-
var
|
|
3854
|
+
var WorkerRejected = class {
|
|
3731
3855
|
statusCode;
|
|
3732
3856
|
responseBody;
|
|
3733
3857
|
constructor(statusCode, responseBody) {
|
|
@@ -3738,7 +3862,7 @@ var WorkerRejected2 = class {
|
|
|
3738
3862
|
return `Rejected: ${this.statusCode} ${this.responseBody}`;
|
|
3739
3863
|
}
|
|
3740
3864
|
};
|
|
3741
|
-
var
|
|
3865
|
+
var CouldNotParseDecryptionKey = class {
|
|
3742
3866
|
originalHex;
|
|
3743
3867
|
constructor(originalHex) {
|
|
3744
3868
|
this.originalHex = originalHex;
|
|
@@ -4302,16 +4426,16 @@ var DecryptionContext2 = class _DecryptionContext {
|
|
|
4302
4426
|
clearTimeout(timeoutId);
|
|
4303
4427
|
}
|
|
4304
4428
|
if (response == null) {
|
|
4305
|
-
return new
|
|
4429
|
+
return new WorkerTimedOut2();
|
|
4306
4430
|
}
|
|
4307
4431
|
const responseBody = await response.text();
|
|
4308
4432
|
if (response.status !== 200) {
|
|
4309
|
-
return new
|
|
4433
|
+
return new WorkerRejected2(response.status, responseBody);
|
|
4310
4434
|
}
|
|
4311
4435
|
try {
|
|
4312
4436
|
return IdentityPrivateKey2.fromHex(responseBody);
|
|
4313
4437
|
} catch (error) {
|
|
4314
|
-
return new
|
|
4438
|
+
return new CouldNotParseDecryptionKey2(responseBody);
|
|
4315
4439
|
}
|
|
4316
4440
|
}));
|
|
4317
4441
|
const numSharesCollected = decKeyLoadResults.filter((loadResult) => loadResult instanceof IdentityPrivateKey2).length;
|
|
@@ -4416,12 +4540,12 @@ var Decryptor2 = class {
|
|
|
4416
4540
|
return decrypt6(symmKey, ciphertext.aesCiph);
|
|
4417
4541
|
}
|
|
4418
4542
|
};
|
|
4419
|
-
var
|
|
4543
|
+
var WorkerTimedOut2 = class {
|
|
4420
4544
|
toDisplayString() {
|
|
4421
4545
|
return "Timed out";
|
|
4422
4546
|
}
|
|
4423
4547
|
};
|
|
4424
|
-
var
|
|
4548
|
+
var WorkerRejected2 = class {
|
|
4425
4549
|
statusCode;
|
|
4426
4550
|
responseBody;
|
|
4427
4551
|
constructor(statusCode, responseBody) {
|
|
@@ -4432,7 +4556,7 @@ var WorkerRejected3 = class {
|
|
|
4432
4556
|
return `Rejected: ${this.statusCode} ${this.responseBody}`;
|
|
4433
4557
|
}
|
|
4434
4558
|
};
|
|
4435
|
-
var
|
|
4559
|
+
var CouldNotParseDecryptionKey2 = class {
|
|
4436
4560
|
originalHex;
|
|
4437
4561
|
constructor(originalHex) {
|
|
4438
4562
|
this.originalHex = originalHex;
|