@monolythium/core-sdk 0.4.0 → 0.4.2
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/crypto/index.cjs +138 -77
- package/dist/crypto/index.cjs.map +1 -1
- package/dist/crypto/index.d.cts +3 -252
- package/dist/crypto/index.d.ts +3 -252
- package/dist/crypto/index.js +138 -77
- package/dist/crypto/index.js.map +1 -1
- package/dist/index.cjs +1273 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -6
- package/dist/index.d.ts +113 -6
- package/dist/index.js +1243 -94
- package/dist/index.js.map +1 -1
- package/dist/{submission-CKXlYstD.d.cts → submission-Cc9r1eqX.d.cts} +395 -63
- package/dist/{submission-CKXlYstD.d.ts → submission-Cc9r1eqX.d.ts} +395 -63
- package/package.json +1 -1
package/dist/crypto/index.cjs
CHANGED
|
@@ -501,82 +501,6 @@ function bincodeMlDsa65OpaqueInto2(w, raw) {
|
|
|
501
501
|
w.u16(STANDARD_ALGO_NUMBER_ML_DSA_65);
|
|
502
502
|
w.bytes(raw);
|
|
503
503
|
}
|
|
504
|
-
|
|
505
|
-
// src/crypto/submission.ts
|
|
506
|
-
async function fetchEncryptionKey(client) {
|
|
507
|
-
const result = await client.call(
|
|
508
|
-
"lyth_getEncryptionKey",
|
|
509
|
-
[]
|
|
510
|
-
);
|
|
511
|
-
return {
|
|
512
|
-
algo: result.algo ?? "ml-kem-768",
|
|
513
|
-
epoch: typeof result.epoch === "string" ? BigInt(result.epoch) : BigInt(result.epoch),
|
|
514
|
-
encapsulationKey: hexToBytes(result.encapsulationKey, "encapsulationKey")
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
var ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE = "encrypted mempool submission unavailable until MB-3 threshold decryption is active";
|
|
518
|
-
async function buildEncryptedSubmission(_args) {
|
|
519
|
-
await Promise.resolve();
|
|
520
|
-
throw new Error(ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE);
|
|
521
|
-
}
|
|
522
|
-
async function submitEncryptedEnvelope(client, envelopeWireHex) {
|
|
523
|
-
return client.call("lyth_submitEncrypted", [envelopeWireHex]);
|
|
524
|
-
}
|
|
525
|
-
function buildPlaintextSubmission(args) {
|
|
526
|
-
const signed = args.backend.signEvmTx(args.tx);
|
|
527
|
-
return {
|
|
528
|
-
signedTxWireHex: `0x${signed.wireHex}`,
|
|
529
|
-
innerTxHashHex: bytesToHex(signed.txHash),
|
|
530
|
-
innerSighashHex: bytesToHex(signed.sighash),
|
|
531
|
-
innerWireBytes: signed.wireBytes.length
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
async function submitPlaintextTransaction(client, signedTxWireHex, expectedTxHashHex) {
|
|
535
|
-
const returned = await client.call("mesh_submitTx", [signedTxWireHex]);
|
|
536
|
-
const returnedBytes = hexToBytes(returned, "mesh_submitTx tx hash");
|
|
537
|
-
if (returnedBytes.length !== 32) {
|
|
538
|
-
throw new Error(
|
|
539
|
-
`mesh_submitTx tx hash must be 32 bytes, got ${returnedBytes.length}`
|
|
540
|
-
);
|
|
541
|
-
}
|
|
542
|
-
const expectedBytes = hexToBytes(expectedTxHashHex, "expected tx hash");
|
|
543
|
-
if (!bytesEqual(returnedBytes, expectedBytes)) {
|
|
544
|
-
throw new Error(
|
|
545
|
-
`mesh_submitTx returned tx hash ${bytesToHex(returnedBytes)} but the locally computed canonical hash is ${bytesToHex(expectedBytes)}`
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
return bytesToHex(returnedBytes);
|
|
549
|
-
}
|
|
550
|
-
async function submitTransactionWithPrivacy(args) {
|
|
551
|
-
if (args.private) {
|
|
552
|
-
if (args.encryptionKey === void 0) {
|
|
553
|
-
throw new Error(
|
|
554
|
-
"private submission requires an encryptionKey; fetch it via fetchEncryptionKey()"
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
|
-
const built = await buildEncryptedSubmission({
|
|
558
|
-
backend: args.backend,
|
|
559
|
-
tx: args.tx,
|
|
560
|
-
encryptionKey: args.encryptionKey,
|
|
561
|
-
class: args.class
|
|
562
|
-
});
|
|
563
|
-
await submitEncryptedEnvelope(args.client, built.envelopeWireHex);
|
|
564
|
-
return built.innerTxHashHex;
|
|
565
|
-
}
|
|
566
|
-
const plaintext = buildPlaintextSubmission({ backend: args.backend, tx: args.tx });
|
|
567
|
-
return submitPlaintextTransaction(
|
|
568
|
-
args.client,
|
|
569
|
-
plaintext.signedTxWireHex,
|
|
570
|
-
plaintext.innerTxHashHex
|
|
571
|
-
);
|
|
572
|
-
}
|
|
573
|
-
function bytesEqual(a, b) {
|
|
574
|
-
if (a.length !== b.length) return false;
|
|
575
|
-
for (let i = 0; i < a.length; i++) {
|
|
576
|
-
if (a[i] !== b[i]) return false;
|
|
577
|
-
}
|
|
578
|
-
return true;
|
|
579
|
-
}
|
|
580
504
|
var SEAL_EK_LEN = 1184;
|
|
581
505
|
var SEAL_DK_LEN = 2400;
|
|
582
506
|
var SEAL_KEM_CT_LEN = 1088;
|
|
@@ -787,6 +711,8 @@ function sealToCluster(args) {
|
|
|
787
711
|
recipients
|
|
788
712
|
};
|
|
789
713
|
}
|
|
714
|
+
|
|
715
|
+
// src/crypto/seal.ts
|
|
790
716
|
var CLUSTER_MLKEM_SHAMIR_ALGO = "cluster-mlkem768-shamir";
|
|
791
717
|
function parseClusterSealKeys(source) {
|
|
792
718
|
const n = source.roster.length;
|
|
@@ -816,7 +742,7 @@ function parseClusterSealKeys(source) {
|
|
|
816
742
|
const recomputed = sealRosterHash(keccak256, source.clusterId, source.t, n, hashInput);
|
|
817
743
|
if (source.rosterHash !== void 0) {
|
|
818
744
|
const supplied = expectBytes(hexToBytes(source.rosterHash, "rosterHash"), 32, "rosterHash");
|
|
819
|
-
if (!
|
|
745
|
+
if (!bytesEqual(supplied, recomputed)) {
|
|
820
746
|
throw new Error(
|
|
821
747
|
`cluster seal roster hash mismatch: source ${bytesToHex(supplied)} != recomputed ${bytesToHex(recomputed)} (the roster hash does not commit to this ek set)`
|
|
822
748
|
);
|
|
@@ -885,6 +811,97 @@ function toBigInt(value) {
|
|
|
885
811
|
if (typeof value === "bigint") return value;
|
|
886
812
|
return BigInt(value);
|
|
887
813
|
}
|
|
814
|
+
function bytesEqual(a, b) {
|
|
815
|
+
if (a.length !== b.length) return false;
|
|
816
|
+
for (let i = 0; i < a.length; i++) {
|
|
817
|
+
if (a[i] !== b[i]) return false;
|
|
818
|
+
}
|
|
819
|
+
return true;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// src/crypto/submission.ts
|
|
823
|
+
async function fetchEncryptionKey(client) {
|
|
824
|
+
const result = await client.call(
|
|
825
|
+
"lyth_getEncryptionKey",
|
|
826
|
+
[]
|
|
827
|
+
);
|
|
828
|
+
return {
|
|
829
|
+
algo: result.algo ?? "ml-kem-768",
|
|
830
|
+
epoch: typeof result.epoch === "string" ? BigInt(result.epoch) : BigInt(result.epoch),
|
|
831
|
+
encapsulationKey: hexToBytes(result.encapsulationKey, "encapsulationKey")
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
var ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE = "private submission requires cluster seal keys; pass clusterSealKeysSource or enable lyth_getClusterSealKeys";
|
|
835
|
+
async function buildEncryptedSubmission(args) {
|
|
836
|
+
const signed = args.backend.signEvmTx(args.tx);
|
|
837
|
+
const clusterSealKeys = await resolveClusterSealKeys(args);
|
|
838
|
+
const aad = nonceAadForTx(args.tx, args.backend.addressBytes(), args.class);
|
|
839
|
+
const sealed = await sealTransaction({
|
|
840
|
+
signedTxBincode: signed.wireBytes,
|
|
841
|
+
clusterSealKeys,
|
|
842
|
+
aad,
|
|
843
|
+
senderAddress: args.backend.addressBytes(),
|
|
844
|
+
senderPubkey: args.backend.publicKey(),
|
|
845
|
+
signOuterDigest: (digest) => args.backend.signPrehash(digest)
|
|
846
|
+
});
|
|
847
|
+
return {
|
|
848
|
+
envelopeWireHex: sealed.envelopeWireHex,
|
|
849
|
+
innerSighashHex: bytesToHex(signed.sighash),
|
|
850
|
+
innerTxHashHex: bytesToHex(signed.txHash),
|
|
851
|
+
innerWireBytes: signed.wireBytes.length
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
async function submitEncryptedEnvelope(client, envelopeWireHex) {
|
|
855
|
+
return client.call("lyth_submitEncrypted", [envelopeWireHex]);
|
|
856
|
+
}
|
|
857
|
+
function buildPlaintextSubmission(args) {
|
|
858
|
+
const signed = args.backend.signEvmTx(args.tx);
|
|
859
|
+
return {
|
|
860
|
+
signedTxWireHex: `0x${signed.wireHex}`,
|
|
861
|
+
innerTxHashHex: bytesToHex(signed.txHash),
|
|
862
|
+
innerSighashHex: bytesToHex(signed.sighash),
|
|
863
|
+
innerWireBytes: signed.wireBytes.length
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
async function submitPlaintextTransaction(client, signedTxWireHex, expectedTxHashHex) {
|
|
867
|
+
const returned = await client.call("mesh_submitTx", [signedTxWireHex]);
|
|
868
|
+
const returnedBytes = hexToBytes(returned, "mesh_submitTx tx hash");
|
|
869
|
+
if (returnedBytes.length !== 32) {
|
|
870
|
+
throw new Error(
|
|
871
|
+
`mesh_submitTx tx hash must be 32 bytes, got ${returnedBytes.length}`
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
const expectedBytes = hexToBytes(expectedTxHashHex, "expected tx hash");
|
|
875
|
+
if (!bytesEqual2(returnedBytes, expectedBytes)) {
|
|
876
|
+
throw new Error(
|
|
877
|
+
`mesh_submitTx returned tx hash ${bytesToHex(returnedBytes)} but the locally computed canonical hash is ${bytesToHex(expectedBytes)}`
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
return bytesToHex(returnedBytes);
|
|
881
|
+
}
|
|
882
|
+
async function submitTransactionWithPrivacy(args) {
|
|
883
|
+
if (args.private) {
|
|
884
|
+
const built = await buildEncryptedSubmission({
|
|
885
|
+
client: args.client,
|
|
886
|
+
backend: args.backend,
|
|
887
|
+
tx: args.tx,
|
|
888
|
+
encryptionKey: args.encryptionKey,
|
|
889
|
+
clusterId: args.clusterId,
|
|
890
|
+
clusterSealKeys: args.clusterSealKeys,
|
|
891
|
+
clusterSealKeysSource: args.clusterSealKeysSource,
|
|
892
|
+
class: args.class
|
|
893
|
+
});
|
|
894
|
+
const returned = await submitEncryptedEnvelope(args.client, built.envelopeWireHex);
|
|
895
|
+
assertRpcHash(returned, "lyth_submitEncrypted tx hash");
|
|
896
|
+
return built.innerTxHashHex;
|
|
897
|
+
}
|
|
898
|
+
const plaintext = buildPlaintextSubmission({ backend: args.backend, tx: args.tx });
|
|
899
|
+
return submitPlaintextTransaction(
|
|
900
|
+
args.client,
|
|
901
|
+
plaintext.signedTxWireHex,
|
|
902
|
+
plaintext.innerTxHashHex
|
|
903
|
+
);
|
|
904
|
+
}
|
|
888
905
|
function bytesEqual2(a, b) {
|
|
889
906
|
if (a.length !== b.length) return false;
|
|
890
907
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -892,6 +909,50 @@ function bytesEqual2(a, b) {
|
|
|
892
909
|
}
|
|
893
910
|
return true;
|
|
894
911
|
}
|
|
912
|
+
async function resolveClusterSealKeys(args) {
|
|
913
|
+
if (args.clusterSealKeys !== void 0) return args.clusterSealKeys;
|
|
914
|
+
if (args.clusterSealKeysSource !== void 0) {
|
|
915
|
+
return parseClusterSealKeys(args.clusterSealKeysSource);
|
|
916
|
+
}
|
|
917
|
+
if (args.client === void 0) {
|
|
918
|
+
throw new Error(ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE);
|
|
919
|
+
}
|
|
920
|
+
const clusterId = args.clusterId ?? 0;
|
|
921
|
+
const result = await args.client.call(
|
|
922
|
+
"lyth_getClusterSealKeys",
|
|
923
|
+
[clusterId]
|
|
924
|
+
);
|
|
925
|
+
return parseClusterSealKeys({ ...result, clusterId: result.clusterId ?? clusterId });
|
|
926
|
+
}
|
|
927
|
+
function nonceAadForTx(tx, sender, mempoolClass) {
|
|
928
|
+
return {
|
|
929
|
+
sender,
|
|
930
|
+
nonce: parseBigint(tx.nonce, "nonce"),
|
|
931
|
+
chainId: parseBigint(tx.chainId, "chainId"),
|
|
932
|
+
class: mempoolClass ?? inferMempoolClass(tx),
|
|
933
|
+
maxFeePerGas: parseBigint(tx.maxFeePerGas, "maxFeePerGas"),
|
|
934
|
+
maxPriorityFeePerGas: parseBigint(tx.maxPriorityFeePerGas, "maxPriorityFeePerGas"),
|
|
935
|
+
gasLimit: parseBigint(tx.gasLimit, "gasLimit")
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
function inferMempoolClass(tx) {
|
|
939
|
+
if (tx.to === null || hasInput(tx.input)) return MempoolClass.ContractCall;
|
|
940
|
+
return MempoolClass.Transfer;
|
|
941
|
+
}
|
|
942
|
+
function hasInput(input) {
|
|
943
|
+
if (input === void 0) return false;
|
|
944
|
+
if (typeof input === "string") {
|
|
945
|
+
const stripped = input.startsWith("0x") || input.startsWith("0X") ? input.slice(2) : input;
|
|
946
|
+
return stripped.length > 0;
|
|
947
|
+
}
|
|
948
|
+
return input.length > 0;
|
|
949
|
+
}
|
|
950
|
+
function assertRpcHash(value, label) {
|
|
951
|
+
const bytes = hexToBytes(value, label);
|
|
952
|
+
if (bytes.length !== 32) {
|
|
953
|
+
throw new Error(`${label} must be 32 bytes, got ${bytes.length}`);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
895
956
|
|
|
896
957
|
exports.ADDRESS_DERIVATION_DOMAIN = ADDRESS_DERIVATION_DOMAIN;
|
|
897
958
|
exports.BincodeWriter = BincodeWriter;
|