@monolythium/core-sdk 0.4.1 → 0.4.3
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 +139 -78
- 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 +139 -78
- package/dist/crypto/index.js.map +1 -1
- package/dist/index.cjs +849 -302
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -7
- package/dist/index.d.ts +32 -7
- package/dist/index.js +838 -303
- package/dist/index.js.map +1 -1
- package/dist/{submission-CP-5JXh5.d.cts → submission-DFg1Hujc.d.cts} +301 -46
- package/dist/{submission-CP-5JXh5.d.ts → submission-DFg1Hujc.d.ts} +301 -46
- package/package.json +1 -1
package/dist/crypto/index.js
CHANGED
|
@@ -244,7 +244,7 @@ var ML_DSA_65_SIGNING_KEY_LEN = 4032;
|
|
|
244
244
|
var ML_DSA_65_PUBLIC_KEY_LEN = 1952;
|
|
245
245
|
var ML_DSA_65_SIGNATURE_LEN = 3309;
|
|
246
246
|
var STANDARD_ALGO_NUMBER_ML_DSA_65 = 1001;
|
|
247
|
-
var ENUM_VARIANT_INDEX_ML_DSA_65 =
|
|
247
|
+
var ENUM_VARIANT_INDEX_ML_DSA_65 = 2;
|
|
248
248
|
var ADDRESS_DERIVATION_DOMAIN = "MONO_ADDRESS_BLAKE3_20_V1";
|
|
249
249
|
var ADDRESS_DERIVATION_DOMAIN_BYTES = new TextEncoder().encode(ADDRESS_DERIVATION_DOMAIN);
|
|
250
250
|
var MlDsa65Backend = class _MlDsa65Backend {
|
|
@@ -499,82 +499,6 @@ function bincodeMlDsa65OpaqueInto2(w, raw) {
|
|
|
499
499
|
w.u16(STANDARD_ALGO_NUMBER_ML_DSA_65);
|
|
500
500
|
w.bytes(raw);
|
|
501
501
|
}
|
|
502
|
-
|
|
503
|
-
// src/crypto/submission.ts
|
|
504
|
-
async function fetchEncryptionKey(client) {
|
|
505
|
-
const result = await client.call(
|
|
506
|
-
"lyth_getEncryptionKey",
|
|
507
|
-
[]
|
|
508
|
-
);
|
|
509
|
-
return {
|
|
510
|
-
algo: result.algo ?? "ml-kem-768",
|
|
511
|
-
epoch: typeof result.epoch === "string" ? BigInt(result.epoch) : BigInt(result.epoch),
|
|
512
|
-
encapsulationKey: hexToBytes(result.encapsulationKey, "encapsulationKey")
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
var ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE = "encrypted mempool submission unavailable until MB-3 threshold decryption is active";
|
|
516
|
-
async function buildEncryptedSubmission(_args) {
|
|
517
|
-
await Promise.resolve();
|
|
518
|
-
throw new Error(ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE);
|
|
519
|
-
}
|
|
520
|
-
async function submitEncryptedEnvelope(client, envelopeWireHex) {
|
|
521
|
-
return client.call("lyth_submitEncrypted", [envelopeWireHex]);
|
|
522
|
-
}
|
|
523
|
-
function buildPlaintextSubmission(args) {
|
|
524
|
-
const signed = args.backend.signEvmTx(args.tx);
|
|
525
|
-
return {
|
|
526
|
-
signedTxWireHex: `0x${signed.wireHex}`,
|
|
527
|
-
innerTxHashHex: bytesToHex(signed.txHash),
|
|
528
|
-
innerSighashHex: bytesToHex(signed.sighash),
|
|
529
|
-
innerWireBytes: signed.wireBytes.length
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
async function submitPlaintextTransaction(client, signedTxWireHex, expectedTxHashHex) {
|
|
533
|
-
const returned = await client.call("mesh_submitTx", [signedTxWireHex]);
|
|
534
|
-
const returnedBytes = hexToBytes(returned, "mesh_submitTx tx hash");
|
|
535
|
-
if (returnedBytes.length !== 32) {
|
|
536
|
-
throw new Error(
|
|
537
|
-
`mesh_submitTx tx hash must be 32 bytes, got ${returnedBytes.length}`
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
const expectedBytes = hexToBytes(expectedTxHashHex, "expected tx hash");
|
|
541
|
-
if (!bytesEqual(returnedBytes, expectedBytes)) {
|
|
542
|
-
throw new Error(
|
|
543
|
-
`mesh_submitTx returned tx hash ${bytesToHex(returnedBytes)} but the locally computed canonical hash is ${bytesToHex(expectedBytes)}`
|
|
544
|
-
);
|
|
545
|
-
}
|
|
546
|
-
return bytesToHex(returnedBytes);
|
|
547
|
-
}
|
|
548
|
-
async function submitTransactionWithPrivacy(args) {
|
|
549
|
-
if (args.private) {
|
|
550
|
-
if (args.encryptionKey === void 0) {
|
|
551
|
-
throw new Error(
|
|
552
|
-
"private submission requires an encryptionKey; fetch it via fetchEncryptionKey()"
|
|
553
|
-
);
|
|
554
|
-
}
|
|
555
|
-
const built = await buildEncryptedSubmission({
|
|
556
|
-
backend: args.backend,
|
|
557
|
-
tx: args.tx,
|
|
558
|
-
encryptionKey: args.encryptionKey,
|
|
559
|
-
class: args.class
|
|
560
|
-
});
|
|
561
|
-
await submitEncryptedEnvelope(args.client, built.envelopeWireHex);
|
|
562
|
-
return built.innerTxHashHex;
|
|
563
|
-
}
|
|
564
|
-
const plaintext = buildPlaintextSubmission({ backend: args.backend, tx: args.tx });
|
|
565
|
-
return submitPlaintextTransaction(
|
|
566
|
-
args.client,
|
|
567
|
-
plaintext.signedTxWireHex,
|
|
568
|
-
plaintext.innerTxHashHex
|
|
569
|
-
);
|
|
570
|
-
}
|
|
571
|
-
function bytesEqual(a, b) {
|
|
572
|
-
if (a.length !== b.length) return false;
|
|
573
|
-
for (let i = 0; i < a.length; i++) {
|
|
574
|
-
if (a[i] !== b[i]) return false;
|
|
575
|
-
}
|
|
576
|
-
return true;
|
|
577
|
-
}
|
|
578
502
|
var SEAL_EK_LEN = 1184;
|
|
579
503
|
var SEAL_DK_LEN = 2400;
|
|
580
504
|
var SEAL_KEM_CT_LEN = 1088;
|
|
@@ -785,6 +709,8 @@ function sealToCluster(args) {
|
|
|
785
709
|
recipients
|
|
786
710
|
};
|
|
787
711
|
}
|
|
712
|
+
|
|
713
|
+
// src/crypto/seal.ts
|
|
788
714
|
var CLUSTER_MLKEM_SHAMIR_ALGO = "cluster-mlkem768-shamir";
|
|
789
715
|
function parseClusterSealKeys(source) {
|
|
790
716
|
const n = source.roster.length;
|
|
@@ -814,7 +740,7 @@ function parseClusterSealKeys(source) {
|
|
|
814
740
|
const recomputed = sealRosterHash(keccak256, source.clusterId, source.t, n, hashInput);
|
|
815
741
|
if (source.rosterHash !== void 0) {
|
|
816
742
|
const supplied = expectBytes(hexToBytes(source.rosterHash, "rosterHash"), 32, "rosterHash");
|
|
817
|
-
if (!
|
|
743
|
+
if (!bytesEqual(supplied, recomputed)) {
|
|
818
744
|
throw new Error(
|
|
819
745
|
`cluster seal roster hash mismatch: source ${bytesToHex(supplied)} != recomputed ${bytesToHex(recomputed)} (the roster hash does not commit to this ek set)`
|
|
820
746
|
);
|
|
@@ -883,6 +809,97 @@ function toBigInt(value) {
|
|
|
883
809
|
if (typeof value === "bigint") return value;
|
|
884
810
|
return BigInt(value);
|
|
885
811
|
}
|
|
812
|
+
function bytesEqual(a, b) {
|
|
813
|
+
if (a.length !== b.length) return false;
|
|
814
|
+
for (let i = 0; i < a.length; i++) {
|
|
815
|
+
if (a[i] !== b[i]) return false;
|
|
816
|
+
}
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// src/crypto/submission.ts
|
|
821
|
+
async function fetchEncryptionKey(client) {
|
|
822
|
+
const result = await client.call(
|
|
823
|
+
"lyth_getEncryptionKey",
|
|
824
|
+
[]
|
|
825
|
+
);
|
|
826
|
+
return {
|
|
827
|
+
algo: result.algo ?? "ml-kem-768",
|
|
828
|
+
epoch: typeof result.epoch === "string" ? BigInt(result.epoch) : BigInt(result.epoch),
|
|
829
|
+
encapsulationKey: hexToBytes(result.encapsulationKey, "encapsulationKey")
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
var ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE = "private submission requires cluster seal keys; pass clusterSealKeysSource or enable lyth_getClusterSealKeys";
|
|
833
|
+
async function buildEncryptedSubmission(args) {
|
|
834
|
+
const signed = args.backend.signEvmTx(args.tx);
|
|
835
|
+
const clusterSealKeys = await resolveClusterSealKeys(args);
|
|
836
|
+
const aad = nonceAadForTx(args.tx, args.backend.addressBytes(), args.class);
|
|
837
|
+
const sealed = await sealTransaction({
|
|
838
|
+
signedTxBincode: signed.wireBytes,
|
|
839
|
+
clusterSealKeys,
|
|
840
|
+
aad,
|
|
841
|
+
senderAddress: args.backend.addressBytes(),
|
|
842
|
+
senderPubkey: args.backend.publicKey(),
|
|
843
|
+
signOuterDigest: (digest) => args.backend.signPrehash(digest)
|
|
844
|
+
});
|
|
845
|
+
return {
|
|
846
|
+
envelopeWireHex: sealed.envelopeWireHex,
|
|
847
|
+
innerSighashHex: bytesToHex(signed.sighash),
|
|
848
|
+
innerTxHashHex: bytesToHex(signed.txHash),
|
|
849
|
+
innerWireBytes: signed.wireBytes.length
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
async function submitEncryptedEnvelope(client, envelopeWireHex) {
|
|
853
|
+
return client.call("lyth_submitEncrypted", [envelopeWireHex]);
|
|
854
|
+
}
|
|
855
|
+
function buildPlaintextSubmission(args) {
|
|
856
|
+
const signed = args.backend.signEvmTx(args.tx);
|
|
857
|
+
return {
|
|
858
|
+
signedTxWireHex: `0x${signed.wireHex}`,
|
|
859
|
+
innerTxHashHex: bytesToHex(signed.txHash),
|
|
860
|
+
innerSighashHex: bytesToHex(signed.sighash),
|
|
861
|
+
innerWireBytes: signed.wireBytes.length
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
async function submitPlaintextTransaction(client, signedTxWireHex, expectedTxHashHex) {
|
|
865
|
+
const returned = await client.call("mesh_submitTx", [signedTxWireHex]);
|
|
866
|
+
const returnedBytes = hexToBytes(returned, "mesh_submitTx tx hash");
|
|
867
|
+
if (returnedBytes.length !== 32) {
|
|
868
|
+
throw new Error(
|
|
869
|
+
`mesh_submitTx tx hash must be 32 bytes, got ${returnedBytes.length}`
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
const expectedBytes = hexToBytes(expectedTxHashHex, "expected tx hash");
|
|
873
|
+
if (!bytesEqual2(returnedBytes, expectedBytes)) {
|
|
874
|
+
throw new Error(
|
|
875
|
+
`mesh_submitTx returned tx hash ${bytesToHex(returnedBytes)} but the locally computed canonical hash is ${bytesToHex(expectedBytes)}`
|
|
876
|
+
);
|
|
877
|
+
}
|
|
878
|
+
return bytesToHex(returnedBytes);
|
|
879
|
+
}
|
|
880
|
+
async function submitTransactionWithPrivacy(args) {
|
|
881
|
+
if (args.private) {
|
|
882
|
+
const built = await buildEncryptedSubmission({
|
|
883
|
+
client: args.client,
|
|
884
|
+
backend: args.backend,
|
|
885
|
+
tx: args.tx,
|
|
886
|
+
encryptionKey: args.encryptionKey,
|
|
887
|
+
clusterId: args.clusterId,
|
|
888
|
+
clusterSealKeys: args.clusterSealKeys,
|
|
889
|
+
clusterSealKeysSource: args.clusterSealKeysSource,
|
|
890
|
+
class: args.class
|
|
891
|
+
});
|
|
892
|
+
const returned = await submitEncryptedEnvelope(args.client, built.envelopeWireHex);
|
|
893
|
+
assertRpcHash(returned, "lyth_submitEncrypted tx hash");
|
|
894
|
+
return built.innerTxHashHex;
|
|
895
|
+
}
|
|
896
|
+
const plaintext = buildPlaintextSubmission({ backend: args.backend, tx: args.tx });
|
|
897
|
+
return submitPlaintextTransaction(
|
|
898
|
+
args.client,
|
|
899
|
+
plaintext.signedTxWireHex,
|
|
900
|
+
plaintext.innerTxHashHex
|
|
901
|
+
);
|
|
902
|
+
}
|
|
886
903
|
function bytesEqual2(a, b) {
|
|
887
904
|
if (a.length !== b.length) return false;
|
|
888
905
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -890,6 +907,50 @@ function bytesEqual2(a, b) {
|
|
|
890
907
|
}
|
|
891
908
|
return true;
|
|
892
909
|
}
|
|
910
|
+
async function resolveClusterSealKeys(args) {
|
|
911
|
+
if (args.clusterSealKeys !== void 0) return args.clusterSealKeys;
|
|
912
|
+
if (args.clusterSealKeysSource !== void 0) {
|
|
913
|
+
return parseClusterSealKeys(args.clusterSealKeysSource);
|
|
914
|
+
}
|
|
915
|
+
if (args.client === void 0) {
|
|
916
|
+
throw new Error(ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE);
|
|
917
|
+
}
|
|
918
|
+
const clusterId = args.clusterId ?? 0;
|
|
919
|
+
const result = await args.client.call(
|
|
920
|
+
"lyth_getClusterSealKeys",
|
|
921
|
+
[clusterId]
|
|
922
|
+
);
|
|
923
|
+
return parseClusterSealKeys({ ...result, clusterId: result.clusterId ?? clusterId });
|
|
924
|
+
}
|
|
925
|
+
function nonceAadForTx(tx, sender, mempoolClass) {
|
|
926
|
+
return {
|
|
927
|
+
sender,
|
|
928
|
+
nonce: parseBigint(tx.nonce, "nonce"),
|
|
929
|
+
chainId: parseBigint(tx.chainId, "chainId"),
|
|
930
|
+
class: mempoolClass ?? inferMempoolClass(tx),
|
|
931
|
+
maxFeePerGas: parseBigint(tx.maxFeePerGas, "maxFeePerGas"),
|
|
932
|
+
maxPriorityFeePerGas: parseBigint(tx.maxPriorityFeePerGas, "maxPriorityFeePerGas"),
|
|
933
|
+
gasLimit: parseBigint(tx.gasLimit, "gasLimit")
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
function inferMempoolClass(tx) {
|
|
937
|
+
if (tx.to === null || hasInput(tx.input)) return MempoolClass.ContractCall;
|
|
938
|
+
return MempoolClass.Transfer;
|
|
939
|
+
}
|
|
940
|
+
function hasInput(input) {
|
|
941
|
+
if (input === void 0) return false;
|
|
942
|
+
if (typeof input === "string") {
|
|
943
|
+
const stripped = input.startsWith("0x") || input.startsWith("0X") ? input.slice(2) : input;
|
|
944
|
+
return stripped.length > 0;
|
|
945
|
+
}
|
|
946
|
+
return input.length > 0;
|
|
947
|
+
}
|
|
948
|
+
function assertRpcHash(value, label) {
|
|
949
|
+
const bytes = hexToBytes(value, label);
|
|
950
|
+
if (bytes.length !== 32) {
|
|
951
|
+
throw new Error(`${label} must be 32 bytes, got ${bytes.length}`);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
893
954
|
|
|
894
955
|
export { ADDRESS_DERIVATION_DOMAIN, BincodeWriter, CLUSTER_MLKEM_SHAMIR, CLUSTER_MLKEM_SHAMIR_ALGO, DKG_AEAD_TAG_LEN, DKG_NONCE_LEN, ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE, ENUM_VARIANT_INDEX_ML_DSA_65, ML_DSA_65_PUBLIC_KEY_LEN, ML_DSA_65_SEED_LEN, ML_DSA_65_SIGNATURE_LEN, ML_DSA_65_SIGNING_KEY_LEN, ML_KEM_768_CIPHERTEXT_LEN, ML_KEM_768_ENCAPSULATION_KEY_LEN, ML_KEM_768_SHARED_SECRET_LEN, MempoolClass, MlDsa65Backend, PQM1_ALGO_TAG_FALCON512_RESERVED, PQM1_ALGO_TAG_MLDSA65, PQM1_ALGO_TAG_MLDSA87_RESERVED, PQM1_ALGO_TAG_SLHDSA128S_RESERVED, PQM1_ENTROPY_LEN, PQM1_PAYLOAD_LEN, PQM1_V1_MLDSA65_DOMAIN_TAG, PQM1_V1_MNEMONIC_WORDS, PQM1_VERSION_V1, Pqm1Error, SEAL_COMMIT_LEN, SEAL_DK_LEN, SEAL_EK_LEN, SEAL_KEM_CT_LEN, SEAL_KEM_SEED_LEN, SEAL_KEY_LEN, SEAL_NONCE_LEN, SEAL_SHARE_LEN, SEAL_TAG_LEN, STANDARD_ALGO_NUMBER_ML_DSA_65, assemblePqm1Payload, bincodeDecryptHint, bincodeEncryptedEnvelope, bincodeNonceAad, bincodeSignedTransaction, buildEncryptedEnvelope, buildEncryptedSubmission, buildPlaintextSubmission, bytesToHex, concatBytes, cryptoRandomSource, derivePqm1MlDsa65SeedFromPayload, encodeMlDsa65Opaque, encodeSealEnvelope, encodeTransactionForHash, encryptInnerTx, expectBytes, fetchEncryptionKey, generatePqm1Mnemonic, getClusterSealKeys, hexToBytes, mlDsa65AddressBytes, mlDsa65AddressFromPublicKey, outerSigDigest, parseClusterSealKeys, parsePqm1Payload, pqm1MnemonicToAddress, pqm1MnemonicToMlDsa65Backend, pqm1MnemonicToMlDsa65Seed, pqm1MnemonicToPayload, pqm1PayloadToMnemonic, sealRosterHash, sealToCluster, sealTransaction, submitEncryptedEnvelope, submitPlaintextTransaction, submitSealedTransaction, submitTransactionWithPrivacy };
|
|
895
956
|
//# sourceMappingURL=index.js.map
|