@monolythium/core-sdk 0.4.22 → 0.4.24
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 +6 -529
- package/dist/crypto/index.cjs.map +1 -1
- package/dist/crypto/index.d.cts +75 -3
- package/dist/crypto/index.d.ts +75 -3
- package/dist/crypto/index.js +6 -494
- package/dist/crypto/index.js.map +1 -1
- package/dist/index.cjs +638 -1031
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7014 -392
- package/dist/index.d.ts +7014 -392
- package/dist/index.js +633 -1025
- package/dist/index.js.map +1 -1
- package/dist/ml-dsa-Drcmrw5h.d.cts +90 -0
- package/dist/ml-dsa-Drcmrw5h.d.ts +90 -0
- package/package.json +1 -1
- package/dist/submission-B4FmDnm_.d.cts +0 -7079
- package/dist/submission-B4FmDnm_.d.ts +0 -7079
package/dist/index.cjs
CHANGED
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
var blake3_js = require('@noble/hashes/blake3.js');
|
|
4
4
|
var sha3_js = require('@noble/hashes/sha3.js');
|
|
5
|
-
var mlKem_js = require('@noble/post-quantum/ml-kem.js');
|
|
6
|
-
var chacha_js = require('@noble/ciphers/chacha.js');
|
|
7
|
-
require('@noble/hashes/utils.js');
|
|
8
5
|
var mlDsa_js = require('@noble/post-quantum/ml-dsa.js');
|
|
9
6
|
var bls12381_js = require('@noble/curves/bls12-381.js');
|
|
10
7
|
var bip39 = require('@scure/bip39');
|
|
@@ -382,10 +379,6 @@ var NODE_REGISTRY_SELECTORS = {
|
|
|
382
379
|
formClusterV2: "0x" + selectorHex("formCluster(bytes,bytes,bytes,bytes)"),
|
|
383
380
|
/** `setOperatorDisplay(bytes32,string,string)` — owner-callable public display metadata. */
|
|
384
381
|
setOperatorDisplay: "0x" + selectorHex("setOperatorDisplay(bytes32,string,string)"),
|
|
385
|
-
/** `publishOperatorSealKey(bytes32,bytes)` — owner-callable LythiumSeal EK publication. */
|
|
386
|
-
publishOperatorSealKey: "0x" + selectorHex("publishOperatorSealKey(bytes32,bytes)"),
|
|
387
|
-
/** `getOperatorSealKey(bytes32)` view — returns the operator's published LythiumSeal EK. */
|
|
388
|
-
getOperatorSealKey: "0x" + selectorHex("getOperatorSealKey(bytes32)"),
|
|
389
382
|
/**
|
|
390
383
|
* `updateCharter(uint32,bytes,bytes,bytes)` — Component H live charter
|
|
391
384
|
* amendment (Law §6.8); re-signs a new 30-byte charter for a LIVE cluster
|
|
@@ -419,7 +412,6 @@ var NODE_REGISTRY_BLS_PUBKEY_BYTES = NODE_REGISTRY_CLUSTER_MEMBER_REF_BYTES;
|
|
|
419
412
|
var NODE_REGISTRY_CONSENSUS_PUBKEY_BYTES = 1952;
|
|
420
413
|
var NODE_REGISTRY_CONSENSUS_SIGNATURE_BYTES = 3309;
|
|
421
414
|
var NODE_REGISTRY_CONSENSUS_POP_BYTES = 3309;
|
|
422
|
-
var NODE_REGISTRY_OPERATOR_SEAL_EK_BYTES = 1184;
|
|
423
415
|
var NODE_REGISTRY_DKG_ATTESTATION_SIG_BYTES = 96;
|
|
424
416
|
var NODE_REGISTRY_DKG_THRESHOLD_SIG_BYTES = NODE_REGISTRY_DKG_ATTESTATION_SIG_BYTES;
|
|
425
417
|
var NODE_REGISTRY_DKG_RESHARE_MIN_SIGNERS = 5;
|
|
@@ -686,43 +678,6 @@ function encodeSetOperatorDisplayCalldata(args) {
|
|
|
686
678
|
)
|
|
687
679
|
);
|
|
688
680
|
}
|
|
689
|
-
function encodePublishOperatorSealKeyCalldata(args) {
|
|
690
|
-
const peerId = expectLength2(toBytes(args.peerId), 32, "peerId");
|
|
691
|
-
const sealEk = expectNonZeroBytes(
|
|
692
|
-
expectLength2(toBytes(args.sealEk), NODE_REGISTRY_OPERATOR_SEAL_EK_BYTES, "sealEk"),
|
|
693
|
-
"sealEk"
|
|
694
|
-
);
|
|
695
|
-
const sealEkPadded = padToWord(sealEk);
|
|
696
|
-
return bytesToHex(
|
|
697
|
-
concatBytes(
|
|
698
|
-
hexToBytes(NODE_REGISTRY_SELECTORS.publishOperatorSealKey),
|
|
699
|
-
peerId,
|
|
700
|
-
uint64Word(2n * 32n, "sealEkOffset"),
|
|
701
|
-
uint64Word(BigInt(sealEk.length), "sealEkLength"),
|
|
702
|
-
sealEkPadded
|
|
703
|
-
)
|
|
704
|
-
);
|
|
705
|
-
}
|
|
706
|
-
function encodeGetOperatorSealKeyCalldata(args) {
|
|
707
|
-
return bytesToHex(
|
|
708
|
-
concatBytes(
|
|
709
|
-
hexToBytes(NODE_REGISTRY_SELECTORS.getOperatorSealKey),
|
|
710
|
-
expectLength2(toBytes(args.operatorId), 32, "operatorId")
|
|
711
|
-
)
|
|
712
|
-
);
|
|
713
|
-
}
|
|
714
|
-
function decodeOperatorSealKey(returnData) {
|
|
715
|
-
const bytes = toBytes(returnData);
|
|
716
|
-
if (bytes.length === NODE_REGISTRY_OPERATOR_SEAL_EK_BYTES) {
|
|
717
|
-
return bytesToHex(expectNonZeroBytes(bytes, "operatorSealKey"));
|
|
718
|
-
}
|
|
719
|
-
const sealEk = decodeDynamicBytesResult(
|
|
720
|
-
bytes,
|
|
721
|
-
NODE_REGISTRY_OPERATOR_SEAL_EK_BYTES,
|
|
722
|
-
"operatorSealKey"
|
|
723
|
-
);
|
|
724
|
-
return bytesToHex(expectNonZeroBytes(sealEk, "operatorSealKey"));
|
|
725
|
-
}
|
|
726
681
|
function encodeCancelClusterJoinCalldata(args) {
|
|
727
682
|
return bytesToHex(
|
|
728
683
|
concatBytes(
|
|
@@ -1651,30 +1606,6 @@ function expectLength2(value, len, name) {
|
|
|
1651
1606
|
}
|
|
1652
1607
|
return value;
|
|
1653
1608
|
}
|
|
1654
|
-
function expectNonZeroBytes(value, name) {
|
|
1655
|
-
if (value.every((byte) => byte === 0)) {
|
|
1656
|
-
throw new NodeRegistryError(`${name} must not be all-zero`);
|
|
1657
|
-
}
|
|
1658
|
-
return value;
|
|
1659
|
-
}
|
|
1660
|
-
function decodeDynamicBytesResult(bytes, expectedLength, label) {
|
|
1661
|
-
if (bytes.length < 64) {
|
|
1662
|
-
throw new NodeRegistryError(`${label} return must be ABI-encoded dynamic bytes`);
|
|
1663
|
-
}
|
|
1664
|
-
const offset = uintFromWord(bytes.slice(0, 32));
|
|
1665
|
-
if (offset !== 32n) {
|
|
1666
|
-
throw new NodeRegistryError(`${label} return offset must be 0x20`);
|
|
1667
|
-
}
|
|
1668
|
-
const len = uintFromWord(bytes.slice(32, 64));
|
|
1669
|
-
if (len !== BigInt(expectedLength)) {
|
|
1670
|
-
throw new NodeRegistryError(`${label} must be ${expectedLength} bytes, got ${len}`);
|
|
1671
|
-
}
|
|
1672
|
-
const paddedLen = Math.ceil(expectedLength / 32) * 32;
|
|
1673
|
-
if (bytes.length < 64 + paddedLen) {
|
|
1674
|
-
throw new NodeRegistryError(`${label} body is truncated`);
|
|
1675
|
-
}
|
|
1676
|
-
return bytes.slice(64, 64 + expectedLength);
|
|
1677
|
-
}
|
|
1678
1609
|
|
|
1679
1610
|
// src/native-events.ts
|
|
1680
1611
|
var NATIVE_MARKET_EVENT_FAMILY = "market";
|
|
@@ -1816,6 +1747,40 @@ function parseBigint(value, label) {
|
|
|
1816
1747
|
return BigInt(value);
|
|
1817
1748
|
}
|
|
1818
1749
|
|
|
1750
|
+
// src/crypto/submission.ts
|
|
1751
|
+
function buildPlaintextSubmission(args) {
|
|
1752
|
+
const signed = args.backend.signEvmTx(args.tx);
|
|
1753
|
+
return {
|
|
1754
|
+
signedTxWireHex: `0x${signed.wireHex}`,
|
|
1755
|
+
innerTxHashHex: bytesToHex2(signed.txHash),
|
|
1756
|
+
innerSighashHex: bytesToHex2(signed.sighash),
|
|
1757
|
+
innerWireBytes: signed.wireBytes.length
|
|
1758
|
+
};
|
|
1759
|
+
}
|
|
1760
|
+
async function submitPlaintextTransaction(client, signedTxWireHex, expectedTxHashHex) {
|
|
1761
|
+
const returned = await client.call("mesh_submitTx", [signedTxWireHex]);
|
|
1762
|
+
const returnedBytes = hexToBytes2(returned, "mesh_submitTx tx hash");
|
|
1763
|
+
if (returnedBytes.length !== 32) {
|
|
1764
|
+
throw new Error(
|
|
1765
|
+
`mesh_submitTx tx hash must be 32 bytes, got ${returnedBytes.length}`
|
|
1766
|
+
);
|
|
1767
|
+
}
|
|
1768
|
+
const expectedBytes = hexToBytes2(expectedTxHashHex, "expected tx hash");
|
|
1769
|
+
if (!bytesEqual(returnedBytes, expectedBytes)) {
|
|
1770
|
+
throw new Error(
|
|
1771
|
+
`mesh_submitTx returned tx hash ${bytesToHex2(returnedBytes)} but the locally computed canonical hash is ${bytesToHex2(expectedBytes)}`
|
|
1772
|
+
);
|
|
1773
|
+
}
|
|
1774
|
+
return bytesToHex2(returnedBytes);
|
|
1775
|
+
}
|
|
1776
|
+
function bytesEqual(a, b) {
|
|
1777
|
+
if (a.length !== b.length) return false;
|
|
1778
|
+
for (let i = 0; i < a.length; i++) {
|
|
1779
|
+
if (a[i] !== b[i]) return false;
|
|
1780
|
+
}
|
|
1781
|
+
return true;
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1819
1784
|
// src/crypto/bincode.ts
|
|
1820
1785
|
var BincodeWriter = class {
|
|
1821
1786
|
#chunks = [];
|
|
@@ -1875,782 +1840,115 @@ var BincodeWriter = class {
|
|
|
1875
1840
|
}
|
|
1876
1841
|
};
|
|
1877
1842
|
|
|
1878
|
-
// src/
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1843
|
+
// src/mrv.ts
|
|
1844
|
+
var MRV_FORMAT_VERSION = 1;
|
|
1845
|
+
var MRV_DEPLOY_PAYLOAD_VERSION = 1;
|
|
1846
|
+
var MRV_PROFILE_MONO_RV32IM_V1 = "mono_rv32im_v1";
|
|
1847
|
+
var MRV_MEMORY_PAGE_BYTES = 65536;
|
|
1848
|
+
var MRV_MAX_CODE_BYTES = 16 * 1024 * 1024;
|
|
1849
|
+
var MRV_MAX_DEBUG_BYTES = 16 * 1024 * 1024;
|
|
1850
|
+
var MRV_MAX_MEMORY_PAGES = 1024;
|
|
1851
|
+
var MRV_MAX_ABI_SYMBOLS = 1024;
|
|
1852
|
+
var MRV_MAX_STORAGE_NAMESPACE_BYTES = 64;
|
|
1853
|
+
var LYTH_DECIMALS = 18;
|
|
1854
|
+
var NATIVE_LYTH_DECIMALS = LYTH_DECIMALS;
|
|
1855
|
+
var LYTHOSHI_PER_LYTH = 1000000000000000000n;
|
|
1856
|
+
var MRV_TX_EXTENSION_KIND = 48;
|
|
1857
|
+
var MRV_TX_EXTENSION_V1 = 1;
|
|
1858
|
+
var MRV_CODE_HASH_DOMAIN = new TextEncoder().encode("MONO_MRV_CODE_V1");
|
|
1859
|
+
var MRV_CONTRACT_ADDRESS_DOMAIN = new TextEncoder().encode("mono:riscv:contract-address:v1");
|
|
1860
|
+
var MONO_SYSCALL_MODULE = "mono";
|
|
1861
|
+
var SYSCALLS = [
|
|
1862
|
+
[257, "storage_read"],
|
|
1863
|
+
[258, "storage_write"],
|
|
1864
|
+
[259, "storage_delete"],
|
|
1865
|
+
[513, "caller"],
|
|
1866
|
+
[514, "contract_address"],
|
|
1867
|
+
[515, "block_height"],
|
|
1868
|
+
[516, "block_hash"],
|
|
1869
|
+
[769, "call_contract"],
|
|
1870
|
+
[770, "emit_event"],
|
|
1871
|
+
[771, "transfer_native"],
|
|
1872
|
+
[1025, "verify_signature"],
|
|
1873
|
+
[1026, "hash"],
|
|
1874
|
+
[1281, "revert"]
|
|
1875
|
+
];
|
|
1876
|
+
var SYSCALL_NAME_BY_ID = new Map(SYSCALLS);
|
|
1877
|
+
var SYSCALL_ID_BY_NAME = new Map(SYSCALLS.map(([id, name]) => [name, id]));
|
|
1878
|
+
var MrvValidationError = class extends Error {
|
|
1879
|
+
constructor(message) {
|
|
1880
|
+
super(message);
|
|
1881
|
+
this.name = "MrvValidationError";
|
|
1912
1882
|
}
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
function
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1883
|
+
};
|
|
1884
|
+
var MRV_STRUCTURED_FEE_FIELDS = [
|
|
1885
|
+
"total_lythoshi",
|
|
1886
|
+
"cycles_used",
|
|
1887
|
+
"base_price_per_cycle_lythoshi",
|
|
1888
|
+
"state_io_units",
|
|
1889
|
+
"state_io_price_per_unit_lythoshi",
|
|
1890
|
+
"priority_tip_lythoshi"
|
|
1891
|
+
];
|
|
1892
|
+
function formatLyth(lythoshi, options = {}) {
|
|
1893
|
+
const amount = BigInt(normalizeDecimalLike("lythoshi", lythoshi));
|
|
1894
|
+
const whole = amount / LYTHOSHI_PER_LYTH;
|
|
1895
|
+
const fraction = amount % LYTHOSHI_PER_LYTH;
|
|
1896
|
+
let formatted = formatWholeWithCommas(whole);
|
|
1897
|
+
if (fraction !== 0n) {
|
|
1898
|
+
formatted += `.${fraction.toString().padStart(NATIVE_LYTH_DECIMALS, "0").replace(/0+$/, "")}`;
|
|
1899
|
+
}
|
|
1900
|
+
if (options.includeUnit !== false) {
|
|
1901
|
+
formatted += " LYTH";
|
|
1902
|
+
}
|
|
1903
|
+
return formatted;
|
|
1934
1904
|
}
|
|
1935
|
-
function
|
|
1936
|
-
|
|
1937
|
-
const bytes = normalizeBytes(value, "to");
|
|
1938
|
-
return expectBytes(bytes, 20, "to");
|
|
1905
|
+
function formatLythoshi(lythoshi, options = {}) {
|
|
1906
|
+
return formatLyth(lythoshi, options);
|
|
1939
1907
|
}
|
|
1940
|
-
function
|
|
1941
|
-
|
|
1942
|
-
|
|
1908
|
+
function parseLythToLythoshi(input) {
|
|
1909
|
+
const numeric = stripLythUnit(input);
|
|
1910
|
+
const parts = numeric.split(".");
|
|
1911
|
+
if (parts.length > 2) {
|
|
1912
|
+
throw new MrvValidationError("lyth amount must be a canonical LYTH decimal");
|
|
1913
|
+
}
|
|
1914
|
+
const [wholeRaw, fractionRaw = ""] = parts;
|
|
1915
|
+
if (!isCanonicalWholeLyth(wholeRaw)) {
|
|
1916
|
+
throw new MrvValidationError("lyth amount must be a canonical LYTH decimal");
|
|
1917
|
+
}
|
|
1918
|
+
if (numeric.includes(".") && fractionRaw.length === 0) {
|
|
1919
|
+
throw new MrvValidationError("lyth amount must be a canonical LYTH decimal");
|
|
1920
|
+
}
|
|
1921
|
+
if (fractionRaw.length > NATIVE_LYTH_DECIMALS || !/^[0-9]*$/.test(fractionRaw)) {
|
|
1922
|
+
throw new MrvValidationError(`lyth amount supports at most ${NATIVE_LYTH_DECIMALS} decimal places`);
|
|
1923
|
+
}
|
|
1924
|
+
const whole = BigInt(wholeRaw.replaceAll(",", ""));
|
|
1925
|
+
const fraction = fractionRaw === "" ? 0n : BigInt(fractionRaw.padEnd(NATIVE_LYTH_DECIMALS, "0"));
|
|
1926
|
+
return whole * LYTHOSHI_PER_LYTH + fraction;
|
|
1943
1927
|
}
|
|
1944
|
-
function
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1928
|
+
function checkMrvFeeDisplayConformance(input) {
|
|
1929
|
+
const expectedTotalLythoshi = normalizeDecimalLike("expectedTotalLythoshi", input.expectedTotalLythoshi);
|
|
1930
|
+
const expectedDefaultFeeText = formatLyth(expectedTotalLythoshi);
|
|
1931
|
+
const failures = [];
|
|
1932
|
+
const amountCandidates = extractLythAmountCandidates(input.defaultFeeText);
|
|
1933
|
+
if (amountCandidates.length !== 1) {
|
|
1934
|
+
failures.push("defaultFeeText must contain exactly one LYTH-denominated fee amount");
|
|
1935
|
+
} else {
|
|
1936
|
+
const renderedCandidate = `${amountCandidates[0]} LYTH`;
|
|
1937
|
+
if (renderedCandidate !== expectedDefaultFeeText) {
|
|
1938
|
+
failures.push(`defaultFeeText fee must be ${expectedDefaultFeeText}`);
|
|
1949
1939
|
}
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1940
|
+
try {
|
|
1941
|
+
const parsed = parseLythToLythoshi(renderedCandidate);
|
|
1942
|
+
if (parsed.toString() !== expectedTotalLythoshi) {
|
|
1943
|
+
failures.push(`defaultFeeText fee must total ${expectedTotalLythoshi} lythoshi`);
|
|
1944
|
+
}
|
|
1945
|
+
} catch {
|
|
1946
|
+
failures.push(`defaultFeeText fee must be a canonical ${NATIVE_LYTH_DECIMALS}-decimal LYTH amount`);
|
|
1953
1947
|
}
|
|
1954
|
-
return { kind: ext.kind, body };
|
|
1955
|
-
});
|
|
1956
|
-
}
|
|
1957
|
-
function encodeExtensionsForHash(extensions) {
|
|
1958
|
-
const chunks = [bigintToBeBytes(BigInt(extensions.length), 4, "extensions.length")];
|
|
1959
|
-
for (const ext of extensions) {
|
|
1960
|
-
chunks.push(
|
|
1961
|
-
Uint8Array.of(ext.kind),
|
|
1962
|
-
bigintToBeBytes(BigInt(ext.body.length), 4, "extension.body.length"),
|
|
1963
|
-
ext.body
|
|
1964
|
-
);
|
|
1965
1948
|
}
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
if (value < 0n || value >= 1n << 256n) throw new Error(`${label} out of u256 range`);
|
|
1970
|
-
const out = new Uint8Array(32);
|
|
1971
|
-
let v = value;
|
|
1972
|
-
for (let i = 31; i >= 0; i--) {
|
|
1973
|
-
out[i] = Number(v & 0xffn);
|
|
1974
|
-
v >>= 8n;
|
|
1975
|
-
}
|
|
1976
|
-
return out;
|
|
1977
|
-
}
|
|
1978
|
-
function bincodeMlDsa65OpaqueInto(w, raw) {
|
|
1979
|
-
w.enumVariant(ENUM_VARIANT_INDEX_ML_DSA_65);
|
|
1980
|
-
w.u16(STANDARD_ALGO_NUMBER_ML_DSA_65);
|
|
1981
|
-
w.bytes(raw);
|
|
1982
|
-
}
|
|
1983
|
-
function bincodeTypedExtensionInto(w, ext) {
|
|
1984
|
-
w.u8(ext.kind);
|
|
1985
|
-
w.bytes(ext.body);
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
|
-
// src/crypto/ml-dsa.ts
|
|
1989
|
-
var ML_DSA_65_SEED_LEN = 32;
|
|
1990
|
-
var ML_DSA_65_SIGNING_KEY_LEN = 4032;
|
|
1991
|
-
var ML_DSA_65_PUBLIC_KEY_LEN = 1952;
|
|
1992
|
-
var ML_DSA_65_SIGNATURE_LEN = 3309;
|
|
1993
|
-
var STANDARD_ALGO_NUMBER_ML_DSA_65 = 1001;
|
|
1994
|
-
var ENUM_VARIANT_INDEX_ML_DSA_65 = 3;
|
|
1995
|
-
var ADDRESS_DERIVATION_DOMAIN = "MONO_ADDRESS_BLAKE3_20_V1";
|
|
1996
|
-
var ADDRESS_DERIVATION_DOMAIN_BYTES = new TextEncoder().encode(ADDRESS_DERIVATION_DOMAIN);
|
|
1997
|
-
var MlDsa65Backend = class _MlDsa65Backend {
|
|
1998
|
-
#secretKey;
|
|
1999
|
-
#publicKey;
|
|
2000
|
-
#addressBytes;
|
|
2001
|
-
#disposed = false;
|
|
2002
|
-
constructor(secretKey, publicKey) {
|
|
2003
|
-
this.#secretKey = expectBytes(secretKey, ML_DSA_65_SIGNING_KEY_LEN, "ML-DSA-65 secret key").slice();
|
|
2004
|
-
this.#publicKey = expectBytes(publicKey, ML_DSA_65_PUBLIC_KEY_LEN, "ML-DSA-65 public key").slice();
|
|
2005
|
-
this.#addressBytes = mlDsa65AddressBytes(this.#publicKey);
|
|
2006
|
-
}
|
|
2007
|
-
static fromSeed(seed) {
|
|
2008
|
-
const kp = mlDsa_js.ml_dsa65.keygen(expectBytes(seed, ML_DSA_65_SEED_LEN, "ML-DSA-65 seed"));
|
|
2009
|
-
return new _MlDsa65Backend(kp.secretKey, kp.publicKey);
|
|
2010
|
-
}
|
|
2011
|
-
publicKey() {
|
|
2012
|
-
return this.#publicKey.slice();
|
|
2013
|
-
}
|
|
2014
|
-
addressBytes() {
|
|
2015
|
-
return this.#addressBytes.slice();
|
|
2016
|
-
}
|
|
2017
|
-
getAddress() {
|
|
2018
|
-
return bytesToHex2(this.#addressBytes);
|
|
2019
|
-
}
|
|
2020
|
-
sign(message) {
|
|
2021
|
-
if (this.#disposed) {
|
|
2022
|
-
throw new Error("MlDsa65Backend disposed");
|
|
2023
|
-
}
|
|
2024
|
-
return mlDsa_js.ml_dsa65.sign(message, this.#secretKey, { extraEntropy: false });
|
|
2025
|
-
}
|
|
2026
|
-
/**
|
|
2027
|
-
* Best-effort deterministic wipe of the in-memory secret key. Zeroes the
|
|
2028
|
-
* SDK-held `#secretKey` copy and makes any subsequent `sign()` /
|
|
2029
|
-
* `signPrehash()` / `signEvmTx()` throw `"MlDsa65Backend disposed"` rather
|
|
2030
|
-
* than signing with a zeroed key. Idempotent. Public material
|
|
2031
|
-
* (`publicKey()` / `getAddress()` / `verify()`) stays usable.
|
|
2032
|
-
*
|
|
2033
|
-
* Defense-in-depth (S1-01): narrows the post-lock residency window of the
|
|
2034
|
-
* ML-DSA-65 secret in the JS heap. `@noble/post-quantum`'s internal
|
|
2035
|
-
* transient keygen/sign buffers are out of scope; the SDK-held copy is the
|
|
2036
|
-
* meaningful residency win.
|
|
2037
|
-
*/
|
|
2038
|
-
dispose() {
|
|
2039
|
-
this.#secretKey.fill(0);
|
|
2040
|
-
this.#disposed = true;
|
|
2041
|
-
}
|
|
2042
|
-
/** Alias for {@link dispose}. */
|
|
2043
|
-
zeroize() {
|
|
2044
|
-
this.dispose();
|
|
2045
|
-
}
|
|
2046
|
-
/** Whether {@link dispose} has been called (the secret key is wiped). */
|
|
2047
|
-
get disposed() {
|
|
2048
|
-
return this.#disposed;
|
|
2049
|
-
}
|
|
2050
|
-
signPrehash(digest) {
|
|
2051
|
-
return this.sign(expectBytes(digest, 32, "prehash"));
|
|
2052
|
-
}
|
|
2053
|
-
verify(message, signature) {
|
|
2054
|
-
return mlDsa_js.ml_dsa65.verify(
|
|
2055
|
-
expectBytes(signature, ML_DSA_65_SIGNATURE_LEN, "ML-DSA-65 signature"),
|
|
2056
|
-
message,
|
|
2057
|
-
this.#publicKey
|
|
2058
|
-
);
|
|
2059
|
-
}
|
|
2060
|
-
signEvmTx(fields) {
|
|
2061
|
-
const txHashPreimage = encodeTransactionForHash(fields, 1);
|
|
2062
|
-
const sighash = sha3_js.keccak_256(txHashPreimage);
|
|
2063
|
-
const signature = this.sign(sighash);
|
|
2064
|
-
const wireBytes = bincodeSignedTransaction(fields, signature, this.#publicKey);
|
|
2065
|
-
const txHash = sha3_js.keccak_256(
|
|
2066
|
-
concatBytes2(
|
|
2067
|
-
encodeTransactionForHash(fields, 2),
|
|
2068
|
-
signature,
|
|
2069
|
-
this.#publicKey
|
|
2070
|
-
)
|
|
2071
|
-
);
|
|
2072
|
-
return {
|
|
2073
|
-
wireHex: bytesToHex2(wireBytes).slice(2),
|
|
2074
|
-
wireBytes,
|
|
2075
|
-
sighash,
|
|
2076
|
-
txHash
|
|
2077
|
-
};
|
|
2078
|
-
}
|
|
2079
|
-
};
|
|
2080
|
-
function mlDsa65AddressFromPublicKey(publicKey) {
|
|
2081
|
-
return bytesToHex2(mlDsa65AddressBytes(publicKey));
|
|
2082
|
-
}
|
|
2083
|
-
function mlDsa65AddressBytes(publicKey) {
|
|
2084
|
-
const bytes = expectBytes(publicKey, ML_DSA_65_PUBLIC_KEY_LEN, "ML-DSA-65 public key");
|
|
2085
|
-
return blake3_js.blake3(concatBytes2(
|
|
2086
|
-
ADDRESS_DERIVATION_DOMAIN_BYTES,
|
|
2087
|
-
bigintToBeBytes(BigInt(STANDARD_ALGO_NUMBER_ML_DSA_65), 2, "ML-DSA-65 algo id"),
|
|
2088
|
-
bytes
|
|
2089
|
-
)).slice(0, 20);
|
|
2090
|
-
}
|
|
2091
|
-
|
|
2092
|
-
// src/crypto/envelope.ts
|
|
2093
|
-
new TextEncoder().encode("protocore/v2/mempool/dkg-mlkem768/1");
|
|
2094
|
-
var MempoolClass = {
|
|
2095
|
-
Transfer: 0,
|
|
2096
|
-
ContractCall: 1,
|
|
2097
|
-
CLOBOp: 3};
|
|
2098
|
-
function bincodeNonceAad(aad) {
|
|
2099
|
-
const w = new BincodeWriter();
|
|
2100
|
-
w.bytes(expectBytes(aad.sender, 20, "NonceAad.sender"));
|
|
2101
|
-
w.u64(aad.nonce);
|
|
2102
|
-
w.u64(aad.chainId);
|
|
2103
|
-
w.enumVariant(aad.class);
|
|
2104
|
-
w.u128(aad.maxFeePerGas);
|
|
2105
|
-
w.u128(aad.maxPriorityFeePerGas);
|
|
2106
|
-
w.u64(aad.gasLimit);
|
|
2107
|
-
return w.toBytes();
|
|
2108
|
-
}
|
|
2109
|
-
function bincodeDecryptHint(hint) {
|
|
2110
|
-
const w = new BincodeWriter();
|
|
2111
|
-
w.u64(hint.epoch);
|
|
2112
|
-
w.u16(hint.scheme);
|
|
2113
|
-
return w.toBytes();
|
|
2114
|
-
}
|
|
2115
|
-
function bincodeEncryptedEnvelope(env) {
|
|
2116
|
-
const w = new BincodeWriter();
|
|
2117
|
-
w.rawBytes(bincodeNonceAad(env.nonceAad));
|
|
2118
|
-
w.bytes(env.ciphertext);
|
|
2119
|
-
w.rawBytes(bincodeDecryptHint(env.decryptionHint));
|
|
2120
|
-
bincodeMlDsa65OpaqueInto2(w, expectBytes(env.senderPubkey, ML_DSA_65_PUBLIC_KEY_LEN, "senderPubkey"));
|
|
2121
|
-
bincodeMlDsa65OpaqueInto2(w, expectBytes(env.outerSignature, ML_DSA_65_SIGNATURE_LEN, "outerSignature"));
|
|
2122
|
-
w.bytes(expectBytes(env.sender, 20, "sender"));
|
|
2123
|
-
return w.toBytes();
|
|
2124
|
-
}
|
|
2125
|
-
function outerSigDigest(nonceAad, ciphertext, decryptionHint, senderPubkey) {
|
|
2126
|
-
const aad = bincodeNonceAad(nonceAad);
|
|
2127
|
-
const hint = bincodeDecryptHint(decryptionHint);
|
|
2128
|
-
return sha3_js.keccak_256(concatBytes2(aad, ciphertext, hint, expectBytes(senderPubkey, ML_DSA_65_PUBLIC_KEY_LEN, "senderPubkey")));
|
|
2129
|
-
}
|
|
2130
|
-
function bincodeMlDsa65OpaqueInto2(w, raw) {
|
|
2131
|
-
w.enumVariant(ENUM_VARIANT_INDEX_ML_DSA_65);
|
|
2132
|
-
w.u16(STANDARD_ALGO_NUMBER_ML_DSA_65);
|
|
2133
|
-
w.bytes(raw);
|
|
2134
|
-
}
|
|
2135
|
-
var SEAL_EK_LEN = 1184;
|
|
2136
|
-
var SEAL_KEY_LEN = 32;
|
|
2137
|
-
var SEAL_NONCE_LEN = 12;
|
|
2138
|
-
var SEAL_COMMIT_LEN = 32;
|
|
2139
|
-
var SEAL_SECRET_LEN = 32;
|
|
2140
|
-
var SEAL_SHARE_LEN = 1 + SEAL_SECRET_LEN;
|
|
2141
|
-
var CLUSTER_MLKEM_SHAMIR = 3;
|
|
2142
|
-
var COMMIT_DOMAIN = new TextEncoder().encode("lythiumseal/commit/v1");
|
|
2143
|
-
var KEK_DOMAIN = new TextEncoder().encode("lythiumseal/kek/v1");
|
|
2144
|
-
var NONCE_DOMAIN = new TextEncoder().encode("lythiumseal/nonce/v1");
|
|
2145
|
-
var BODY_AAD_DOMAIN = new TextEncoder().encode("lythiumseal/body/v1");
|
|
2146
|
-
var SHARE_AAD_DOMAIN = new TextEncoder().encode("lythiumseal/share/v1");
|
|
2147
|
-
var ROSTER_DOMAIN = new TextEncoder().encode("lythiumseal/roster/v1");
|
|
2148
|
-
function cryptoRandomSource() {
|
|
2149
|
-
return {
|
|
2150
|
-
fillBytes(dest) {
|
|
2151
|
-
crypto.getRandomValues(dest);
|
|
2152
|
-
}
|
|
2153
|
-
};
|
|
2154
|
-
}
|
|
2155
|
-
function u32le(n) {
|
|
2156
|
-
const out = new Uint8Array(4);
|
|
2157
|
-
out[0] = n & 255;
|
|
2158
|
-
out[1] = n >>> 8 & 255;
|
|
2159
|
-
out[2] = n >>> 16 & 255;
|
|
2160
|
-
out[3] = n >>> 24 & 255;
|
|
2161
|
-
return out;
|
|
2162
|
-
}
|
|
2163
|
-
function u64le(n) {
|
|
2164
|
-
const out = new Uint8Array(8);
|
|
2165
|
-
let v = n;
|
|
2166
|
-
for (let i = 0; i < 8; i++) {
|
|
2167
|
-
out[i] = Number(v & 0xffn);
|
|
2168
|
-
v >>= 8n;
|
|
2169
|
-
}
|
|
2170
|
-
return out;
|
|
2171
|
-
}
|
|
2172
|
-
function framed(field2) {
|
|
2173
|
-
return concatBytes2(u32le(field2.length), field2);
|
|
2174
|
-
}
|
|
2175
|
-
function keyCommitment(key) {
|
|
2176
|
-
return sha3_js.shake256(concatBytes2(framed(COMMIT_DOMAIN), key), { dkLen: SEAL_COMMIT_LEN });
|
|
2177
|
-
}
|
|
2178
|
-
function deriveKek(sharedSecret, domain, clusterId, epoch, opIndex) {
|
|
2179
|
-
const input = concatBytes2(
|
|
2180
|
-
framed(KEK_DOMAIN),
|
|
2181
|
-
framed(sharedSecret),
|
|
2182
|
-
framed(domain),
|
|
2183
|
-
u32le(clusterId),
|
|
2184
|
-
u64le(epoch),
|
|
2185
|
-
Uint8Array.of(opIndex)
|
|
2186
|
-
);
|
|
2187
|
-
return sha3_js.shake256(input, { dkLen: SEAL_KEY_LEN });
|
|
2188
|
-
}
|
|
2189
|
-
function deriveNonce(domain, context) {
|
|
2190
|
-
const input = concatBytes2(framed(NONCE_DOMAIN), framed(domain), framed(context));
|
|
2191
|
-
return sha3_js.shake256(input, { dkLen: SEAL_NONCE_LEN });
|
|
2192
|
-
}
|
|
2193
|
-
function bodyAad(ctx, k, n) {
|
|
2194
|
-
return concatBytes2(
|
|
2195
|
-
BODY_AAD_DOMAIN,
|
|
2196
|
-
u32le(ctx.clusterId),
|
|
2197
|
-
u64le(ctx.epoch),
|
|
2198
|
-
Uint8Array.of(k),
|
|
2199
|
-
Uint8Array.of(n),
|
|
2200
|
-
ctx.rosterHash
|
|
2201
|
-
);
|
|
2202
|
-
}
|
|
2203
|
-
function shareAad(ctx, opIndex) {
|
|
2204
|
-
return concatBytes2(
|
|
2205
|
-
SHARE_AAD_DOMAIN,
|
|
2206
|
-
u32le(ctx.clusterId),
|
|
2207
|
-
u64le(ctx.epoch),
|
|
2208
|
-
Uint8Array.of(opIndex),
|
|
2209
|
-
ctx.rosterHash
|
|
2210
|
-
);
|
|
2211
|
-
}
|
|
2212
|
-
function aeadSeal(key, nonce, plaintext, aad) {
|
|
2213
|
-
const cipher = chacha_js.chacha20poly1305(key, nonce, aad);
|
|
2214
|
-
const ct = cipher.encrypt(plaintext);
|
|
2215
|
-
return { nonce, ct, commitment: keyCommitment(key) };
|
|
2216
|
-
}
|
|
2217
|
-
function gfMul(a, b) {
|
|
2218
|
-
let product = 0;
|
|
2219
|
-
let x = a & 255;
|
|
2220
|
-
let y = b & 255;
|
|
2221
|
-
for (let i = 0; i < 8; i++) {
|
|
2222
|
-
const mask = -(y & 1) & 255;
|
|
2223
|
-
product ^= x & mask;
|
|
2224
|
-
const high = -(x >> 7 & 1) & 255;
|
|
2225
|
-
x = x << 1 & 255;
|
|
2226
|
-
x ^= 27 & high;
|
|
2227
|
-
y >>= 1;
|
|
2228
|
-
}
|
|
2229
|
-
return product & 255;
|
|
2230
|
-
}
|
|
2231
|
-
function polyEval(coeffs, x) {
|
|
2232
|
-
let acc = 0;
|
|
2233
|
-
for (let i = coeffs.length - 1; i >= 0; i--) {
|
|
2234
|
-
acc = gfMul(acc, x) ^ coeffs[i];
|
|
2235
|
-
}
|
|
2236
|
-
return acc & 255;
|
|
2237
|
-
}
|
|
2238
|
-
function shamirSplit(secret, t, n, rng) {
|
|
2239
|
-
const byteCoeffs = [];
|
|
2240
|
-
for (let j = 0; j < SEAL_SECRET_LEN; j++) {
|
|
2241
|
-
const c = new Uint8Array(t);
|
|
2242
|
-
c[0] = secret[j];
|
|
2243
|
-
if (t > 1) {
|
|
2244
|
-
const tail = new Uint8Array(t - 1);
|
|
2245
|
-
rng.fillBytes(tail);
|
|
2246
|
-
c.set(tail, 1);
|
|
2247
|
-
}
|
|
2248
|
-
byteCoeffs.push(c);
|
|
2249
|
-
}
|
|
2250
|
-
const shares = [];
|
|
2251
|
-
for (let k = 0; k < n; k++) {
|
|
2252
|
-
const x = k + 1 & 255;
|
|
2253
|
-
const value = new Uint8Array(SEAL_SECRET_LEN);
|
|
2254
|
-
for (let j = 0; j < SEAL_SECRET_LEN; j++) {
|
|
2255
|
-
value[j] = polyEval(byteCoeffs[j], x);
|
|
2256
|
-
}
|
|
2257
|
-
shares.push({ index: x, value });
|
|
2258
|
-
}
|
|
2259
|
-
return shares;
|
|
2260
|
-
}
|
|
2261
|
-
function shareToBytes(s) {
|
|
2262
|
-
const out = new Uint8Array(SEAL_SHARE_LEN);
|
|
2263
|
-
out[0] = s.index;
|
|
2264
|
-
out.set(s.value, 1);
|
|
2265
|
-
return out;
|
|
2266
|
-
}
|
|
2267
|
-
function sealRosterHash(keccak2562, clusterId, t, n, roster) {
|
|
2268
|
-
const chunks = [ROSTER_DOMAIN, u32le(clusterId), Uint8Array.of(t), Uint8Array.of(n)];
|
|
2269
|
-
for (const { operatorIndex, ek } of roster) {
|
|
2270
|
-
chunks.push(Uint8Array.of(operatorIndex), ek);
|
|
2271
|
-
}
|
|
2272
|
-
return keccak2562(concatBytes2(...chunks));
|
|
2273
|
-
}
|
|
2274
|
-
function encodeSealEnvelope(env) {
|
|
2275
|
-
const chunks = [];
|
|
2276
|
-
chunks.push(u32le(env.clusterId));
|
|
2277
|
-
chunks.push(u64le(env.epoch));
|
|
2278
|
-
chunks.push(expectBytes(env.rosterHash, 32, "rosterHash"));
|
|
2279
|
-
chunks.push(Uint8Array.of(env.t));
|
|
2280
|
-
chunks.push(Uint8Array.of(env.n));
|
|
2281
|
-
pushAeadBody(chunks, env.aeadBody);
|
|
2282
|
-
chunks.push(u64le(BigInt(env.recipients.length)));
|
|
2283
|
-
for (const r of env.recipients) {
|
|
2284
|
-
chunks.push(Uint8Array.of(r.operatorIndex));
|
|
2285
|
-
chunks.push(u64le(BigInt(r.kemCt.length)));
|
|
2286
|
-
chunks.push(r.kemCt);
|
|
2287
|
-
pushAeadBody(chunks, r.wrapped);
|
|
2288
|
-
}
|
|
2289
|
-
return concatBytes2(...chunks);
|
|
2290
|
-
}
|
|
2291
|
-
function pushAeadBody(chunks, body) {
|
|
2292
|
-
chunks.push(expectBytes(body.nonce, SEAL_NONCE_LEN, "aead nonce"));
|
|
2293
|
-
chunks.push(u64le(BigInt(body.ct.length)));
|
|
2294
|
-
chunks.push(body.ct);
|
|
2295
|
-
chunks.push(expectBytes(body.commitment, SEAL_COMMIT_LEN, "aead commitment"));
|
|
2296
|
-
}
|
|
2297
|
-
function sealToCluster(args) {
|
|
2298
|
-
const { plaintext, recipientEks, t, clusterId } = args;
|
|
2299
|
-
const epoch = args.epoch;
|
|
2300
|
-
const rosterHash = expectBytes(args.rosterHash, 32, "rosterHash");
|
|
2301
|
-
const rng = args.rng ?? cryptoRandomSource();
|
|
2302
|
-
const n = recipientEks.length;
|
|
2303
|
-
if (!Number.isInteger(t) || t < 1 || t > n || n < 1 || n > 255) {
|
|
2304
|
-
throw new Error(`invalid threshold/recipient count: t=${t} n=${n}`);
|
|
2305
|
-
}
|
|
2306
|
-
for (let i = 0; i < n; i++) {
|
|
2307
|
-
expectBytes(recipientEks[i], SEAL_EK_LEN, `recipientEks[${i}]`);
|
|
2308
|
-
}
|
|
2309
|
-
const ctx = { clusterId, epoch, rosterHash };
|
|
2310
|
-
const bodyKey = new Uint8Array(SEAL_KEY_LEN);
|
|
2311
|
-
rng.fillBytes(bodyKey);
|
|
2312
|
-
const aad = bodyAad(ctx, t, n);
|
|
2313
|
-
const bodyNonce = deriveNonce(new TextEncoder().encode("body"), aad);
|
|
2314
|
-
const aeadBody = aeadSeal(bodyKey, bodyNonce, plaintext, aad);
|
|
2315
|
-
const shares = shamirSplit(bodyKey, t, n, rng);
|
|
2316
|
-
const recipients = [];
|
|
2317
|
-
for (let i = 0; i < n; i++) {
|
|
2318
|
-
const opIndex = i + 1 & 255;
|
|
2319
|
-
const m = new Uint8Array(32);
|
|
2320
|
-
rng.fillBytes(m);
|
|
2321
|
-
const { cipherText: kemCt, sharedSecret } = mlKem_js.ml_kem768.encapsulate(recipientEks[i], m);
|
|
2322
|
-
const kek = deriveKek(sharedSecret, rosterHash, clusterId, epoch, opIndex);
|
|
2323
|
-
const sAad = shareAad(ctx, opIndex);
|
|
2324
|
-
const wrapNonce = deriveNonce(new TextEncoder().encode("share"), sAad);
|
|
2325
|
-
const wrapped = aeadSeal(kek, wrapNonce, shareToBytes(shares[i]), sAad);
|
|
2326
|
-
recipients.push({ operatorIndex: opIndex, kemCt, wrapped });
|
|
2327
|
-
sharedSecret.fill(0);
|
|
2328
|
-
kek.fill(0);
|
|
2329
|
-
}
|
|
2330
|
-
bodyKey.fill(0);
|
|
2331
|
-
return {
|
|
2332
|
-
clusterId,
|
|
2333
|
-
epoch,
|
|
2334
|
-
rosterHash,
|
|
2335
|
-
t,
|
|
2336
|
-
n,
|
|
2337
|
-
aeadBody,
|
|
2338
|
-
recipients
|
|
2339
|
-
};
|
|
2340
|
-
}
|
|
2341
|
-
|
|
2342
|
-
// src/crypto/seal.ts
|
|
2343
|
-
var CLUSTER_MLKEM_SHAMIR_ALGO = "cluster-mlkem768-shamir";
|
|
2344
|
-
function parseClusterSealKeys(source) {
|
|
2345
|
-
const n = source.roster.length;
|
|
2346
|
-
if (n === 0) {
|
|
2347
|
-
throw new Error("cluster seal roster is empty");
|
|
2348
|
-
}
|
|
2349
|
-
if (source.n !== n) {
|
|
2350
|
-
throw new Error(`cluster seal roster n=${source.n} disagrees with ${n} entries`);
|
|
2351
|
-
}
|
|
2352
|
-
if (!Number.isInteger(source.t) || source.t < 2 || source.t > n) {
|
|
2353
|
-
throw new Error(`cluster seal threshold t=${source.t} out of range 2..=${n}`);
|
|
2354
|
-
}
|
|
2355
|
-
const sorted = [...source.roster].sort((a, b) => a.operatorIndex - b.operatorIndex);
|
|
2356
|
-
const recipientEks = [];
|
|
2357
|
-
const hashInput = [];
|
|
2358
|
-
for (let i = 0; i < n; i++) {
|
|
2359
|
-
const entry = sorted[i];
|
|
2360
|
-
if (entry.operatorIndex !== i + 1) {
|
|
2361
|
-
throw new Error(
|
|
2362
|
-
`cluster seal roster operator indices must be 1..=${n}; got ${entry.operatorIndex} at slot ${i + 1}`
|
|
2363
|
-
);
|
|
2364
|
-
}
|
|
2365
|
-
const ek = expectBytes(hexToBytes2(entry.mlKemEk, `operator ${entry.operatorIndex} mlKemEk`), SEAL_EK_LEN, `operator ${entry.operatorIndex} ek`);
|
|
2366
|
-
recipientEks.push(ek);
|
|
2367
|
-
hashInput.push({ operatorIndex: entry.operatorIndex, ek });
|
|
2368
|
-
}
|
|
2369
|
-
const recomputed = sealRosterHash(keccak256, source.clusterId, source.t, n, hashInput);
|
|
2370
|
-
if (source.rosterHash !== void 0) {
|
|
2371
|
-
const supplied = expectBytes(hexToBytes2(source.rosterHash, "rosterHash"), 32, "rosterHash");
|
|
2372
|
-
if (!bytesEqual(supplied, recomputed)) {
|
|
2373
|
-
throw new Error(
|
|
2374
|
-
`cluster seal roster hash mismatch: source ${bytesToHex2(supplied)} != recomputed ${bytesToHex2(recomputed)} (the roster hash does not commit to this ek set)`
|
|
2375
|
-
);
|
|
2376
|
-
}
|
|
2377
|
-
}
|
|
2378
|
-
return {
|
|
2379
|
-
algo: source.algo ?? CLUSTER_MLKEM_SHAMIR_ALGO,
|
|
2380
|
-
clusterId: source.clusterId,
|
|
2381
|
-
epoch: toBigInt(source.epoch),
|
|
2382
|
-
rosterHash: recomputed,
|
|
2383
|
-
t: source.t,
|
|
2384
|
-
n,
|
|
2385
|
-
recipientEks
|
|
2386
|
-
};
|
|
2387
|
-
}
|
|
2388
|
-
async function sealTransaction(args) {
|
|
2389
|
-
const keys = args.clusterSealKeys;
|
|
2390
|
-
const senderPubkey = expectBytes(args.senderPubkey, ML_DSA_65_PUBLIC_KEY_LEN, "senderPubkey");
|
|
2391
|
-
const senderAddress = expectBytes(args.senderAddress, 20, "senderAddress");
|
|
2392
|
-
const env = sealToCluster({
|
|
2393
|
-
plaintext: args.signedTxBincode,
|
|
2394
|
-
recipientEks: keys.recipientEks,
|
|
2395
|
-
t: keys.t,
|
|
2396
|
-
clusterId: keys.clusterId,
|
|
2397
|
-
epoch: keys.epoch,
|
|
2398
|
-
rosterHash: keys.rosterHash,
|
|
2399
|
-
rng: args.rng
|
|
2400
|
-
});
|
|
2401
|
-
const ciphertext = encodeSealEnvelope(env);
|
|
2402
|
-
const decryptionHint = { epoch: keys.epoch, scheme: CLUSTER_MLKEM_SHAMIR };
|
|
2403
|
-
const digest = outerSigDigest(args.aad, ciphertext, decryptionHint, senderPubkey);
|
|
2404
|
-
const outerSignature = expectBytes(
|
|
2405
|
-
await args.signOuterDigest(digest),
|
|
2406
|
-
ML_DSA_65_SIGNATURE_LEN,
|
|
2407
|
-
"outerSignature"
|
|
2408
|
-
);
|
|
2409
|
-
const envelope = {
|
|
2410
|
-
nonceAad: args.aad,
|
|
2411
|
-
ciphertext,
|
|
2412
|
-
decryptionHint,
|
|
2413
|
-
senderPubkey,
|
|
2414
|
-
outerSignature,
|
|
2415
|
-
sender: senderAddress
|
|
2416
|
-
};
|
|
2417
|
-
const envelopeWireBytes = bincodeEncryptedEnvelope(envelope);
|
|
2418
|
-
return {
|
|
2419
|
-
envelopeWireHex: `0x${bytesToHex2(envelopeWireBytes).slice(2)}`,
|
|
2420
|
-
envelopeWireBytes,
|
|
2421
|
-
ciphertextBytes: ciphertext.length
|
|
2422
|
-
};
|
|
2423
|
-
}
|
|
2424
|
-
function keccak256(input) {
|
|
2425
|
-
return sha3_js.keccak_256(input);
|
|
2426
|
-
}
|
|
2427
|
-
function toBigInt(value) {
|
|
2428
|
-
if (typeof value === "bigint") return value;
|
|
2429
|
-
return BigInt(value);
|
|
2430
|
-
}
|
|
2431
|
-
function bytesEqual(a, b) {
|
|
2432
|
-
if (a.length !== b.length) return false;
|
|
2433
|
-
for (let i = 0; i < a.length; i++) {
|
|
2434
|
-
if (a[i] !== b[i]) return false;
|
|
2435
|
-
}
|
|
2436
|
-
return true;
|
|
2437
|
-
}
|
|
2438
|
-
|
|
2439
|
-
// src/crypto/submission.ts
|
|
2440
|
-
async function fetchEncryptionKey(client) {
|
|
2441
|
-
const result = await client.call(
|
|
2442
|
-
"lyth_getEncryptionKey",
|
|
2443
|
-
[]
|
|
2444
|
-
);
|
|
2445
|
-
return {
|
|
2446
|
-
algo: result.algo ?? "ml-kem-768",
|
|
2447
|
-
epoch: typeof result.epoch === "string" ? BigInt(result.epoch) : BigInt(result.epoch),
|
|
2448
|
-
encapsulationKey: hexToBytes2(result.encapsulationKey, "encapsulationKey")
|
|
2449
|
-
};
|
|
2450
|
-
}
|
|
2451
|
-
var ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE = "private submission requires cluster seal keys; pass clusterSealKeysSource or enable lyth_getClusterSealKeys";
|
|
2452
|
-
async function buildEncryptedSubmission(args) {
|
|
2453
|
-
const signed = args.backend.signEvmTx(args.tx);
|
|
2454
|
-
const clusterSealKeys = await resolveClusterSealKeys(args);
|
|
2455
|
-
const aad = nonceAadForTx(args.tx, args.backend.addressBytes(), args.class);
|
|
2456
|
-
const sealed = await sealTransaction({
|
|
2457
|
-
signedTxBincode: signed.wireBytes,
|
|
2458
|
-
clusterSealKeys,
|
|
2459
|
-
aad,
|
|
2460
|
-
senderAddress: args.backend.addressBytes(),
|
|
2461
|
-
senderPubkey: args.backend.publicKey(),
|
|
2462
|
-
signOuterDigest: (digest) => args.backend.signPrehash(digest)
|
|
2463
|
-
});
|
|
2464
|
-
return {
|
|
2465
|
-
envelopeWireHex: sealed.envelopeWireHex,
|
|
2466
|
-
innerSighashHex: bytesToHex2(signed.sighash),
|
|
2467
|
-
innerTxHashHex: bytesToHex2(signed.txHash),
|
|
2468
|
-
innerWireBytes: signed.wireBytes.length
|
|
2469
|
-
};
|
|
2470
|
-
}
|
|
2471
|
-
async function submitEncryptedEnvelope(client, envelopeWireHex) {
|
|
2472
|
-
return client.call("lyth_submitEncrypted", [envelopeWireHex]);
|
|
2473
|
-
}
|
|
2474
|
-
function buildPlaintextSubmission(args) {
|
|
2475
|
-
const signed = args.backend.signEvmTx(args.tx);
|
|
2476
|
-
return {
|
|
2477
|
-
signedTxWireHex: `0x${signed.wireHex}`,
|
|
2478
|
-
innerTxHashHex: bytesToHex2(signed.txHash),
|
|
2479
|
-
innerSighashHex: bytesToHex2(signed.sighash),
|
|
2480
|
-
innerWireBytes: signed.wireBytes.length
|
|
2481
|
-
};
|
|
2482
|
-
}
|
|
2483
|
-
async function submitPlaintextTransaction(client, signedTxWireHex, expectedTxHashHex) {
|
|
2484
|
-
const returned = await client.call("mesh_submitTx", [signedTxWireHex]);
|
|
2485
|
-
const returnedBytes = hexToBytes2(returned, "mesh_submitTx tx hash");
|
|
2486
|
-
if (returnedBytes.length !== 32) {
|
|
2487
|
-
throw new Error(
|
|
2488
|
-
`mesh_submitTx tx hash must be 32 bytes, got ${returnedBytes.length}`
|
|
2489
|
-
);
|
|
2490
|
-
}
|
|
2491
|
-
const expectedBytes = hexToBytes2(expectedTxHashHex, "expected tx hash");
|
|
2492
|
-
if (!bytesEqual2(returnedBytes, expectedBytes)) {
|
|
2493
|
-
throw new Error(
|
|
2494
|
-
`mesh_submitTx returned tx hash ${bytesToHex2(returnedBytes)} but the locally computed canonical hash is ${bytesToHex2(expectedBytes)}`
|
|
2495
|
-
);
|
|
2496
|
-
}
|
|
2497
|
-
return bytesToHex2(returnedBytes);
|
|
2498
|
-
}
|
|
2499
|
-
function bytesEqual2(a, b) {
|
|
2500
|
-
if (a.length !== b.length) return false;
|
|
2501
|
-
for (let i = 0; i < a.length; i++) {
|
|
2502
|
-
if (a[i] !== b[i]) return false;
|
|
2503
|
-
}
|
|
2504
|
-
return true;
|
|
2505
|
-
}
|
|
2506
|
-
async function resolveClusterSealKeys(args) {
|
|
2507
|
-
if (args.clusterSealKeys !== void 0) return args.clusterSealKeys;
|
|
2508
|
-
if (args.clusterSealKeysSource !== void 0) {
|
|
2509
|
-
return parseClusterSealKeys(args.clusterSealKeysSource);
|
|
2510
|
-
}
|
|
2511
|
-
if (args.client === void 0) {
|
|
2512
|
-
throw new Error(ENCRYPTED_SUBMISSION_UNAVAILABLE_MESSAGE);
|
|
2513
|
-
}
|
|
2514
|
-
const clusterId = args.clusterId ?? 0;
|
|
2515
|
-
const result = await args.client.call(
|
|
2516
|
-
"lyth_getClusterSealKeys",
|
|
2517
|
-
[clusterId]
|
|
2518
|
-
);
|
|
2519
|
-
return parseClusterSealKeys({ ...result, clusterId: result.clusterId ?? clusterId });
|
|
2520
|
-
}
|
|
2521
|
-
function nonceAadForTx(tx, sender, mempoolClass) {
|
|
2522
|
-
return {
|
|
2523
|
-
sender,
|
|
2524
|
-
nonce: parseBigint(tx.nonce, "nonce"),
|
|
2525
|
-
chainId: parseBigint(tx.chainId, "chainId"),
|
|
2526
|
-
class: mempoolClass ?? inferMempoolClass(tx),
|
|
2527
|
-
maxFeePerGas: parseBigint(tx.maxFeePerGas, "maxFeePerGas"),
|
|
2528
|
-
maxPriorityFeePerGas: parseBigint(tx.maxPriorityFeePerGas, "maxPriorityFeePerGas"),
|
|
2529
|
-
gasLimit: parseBigint(tx.gasLimit, "gasLimit")
|
|
2530
|
-
};
|
|
2531
|
-
}
|
|
2532
|
-
function inferMempoolClass(tx) {
|
|
2533
|
-
if (tx.to === null || hasInput(tx.input)) return MempoolClass.ContractCall;
|
|
2534
|
-
return MempoolClass.Transfer;
|
|
2535
|
-
}
|
|
2536
|
-
function hasInput(input) {
|
|
2537
|
-
if (input === void 0) return false;
|
|
2538
|
-
if (typeof input === "string") {
|
|
2539
|
-
const stripped = input.startsWith("0x") || input.startsWith("0X") ? input.slice(2) : input;
|
|
2540
|
-
return stripped.length > 0;
|
|
2541
|
-
}
|
|
2542
|
-
return input.length > 0;
|
|
2543
|
-
}
|
|
2544
|
-
|
|
2545
|
-
// src/mrv.ts
|
|
2546
|
-
var MRV_FORMAT_VERSION = 1;
|
|
2547
|
-
var MRV_DEPLOY_PAYLOAD_VERSION = 1;
|
|
2548
|
-
var MRV_PROFILE_MONO_RV32IM_V1 = "mono_rv32im_v1";
|
|
2549
|
-
var MRV_MEMORY_PAGE_BYTES = 65536;
|
|
2550
|
-
var MRV_MAX_CODE_BYTES = 16 * 1024 * 1024;
|
|
2551
|
-
var MRV_MAX_DEBUG_BYTES = 16 * 1024 * 1024;
|
|
2552
|
-
var MRV_MAX_MEMORY_PAGES = 1024;
|
|
2553
|
-
var MRV_MAX_ABI_SYMBOLS = 1024;
|
|
2554
|
-
var MRV_MAX_STORAGE_NAMESPACE_BYTES = 64;
|
|
2555
|
-
var LYTH_DECIMALS = 18;
|
|
2556
|
-
var NATIVE_LYTH_DECIMALS = LYTH_DECIMALS;
|
|
2557
|
-
var LYTHOSHI_PER_LYTH = 1000000000000000000n;
|
|
2558
|
-
var MRV_TX_EXTENSION_KIND = 48;
|
|
2559
|
-
var MRV_TX_EXTENSION_V1 = 1;
|
|
2560
|
-
var MRV_CODE_HASH_DOMAIN = new TextEncoder().encode("MONO_MRV_CODE_V1");
|
|
2561
|
-
var MRV_CONTRACT_ADDRESS_DOMAIN = new TextEncoder().encode("mono:riscv:contract-address:v1");
|
|
2562
|
-
var MONO_SYSCALL_MODULE = "mono";
|
|
2563
|
-
var SYSCALLS = [
|
|
2564
|
-
[257, "storage_read"],
|
|
2565
|
-
[258, "storage_write"],
|
|
2566
|
-
[259, "storage_delete"],
|
|
2567
|
-
[513, "caller"],
|
|
2568
|
-
[514, "contract_address"],
|
|
2569
|
-
[515, "block_height"],
|
|
2570
|
-
[516, "block_hash"],
|
|
2571
|
-
[769, "call_contract"],
|
|
2572
|
-
[770, "emit_event"],
|
|
2573
|
-
[771, "transfer_native"],
|
|
2574
|
-
[1025, "verify_signature"],
|
|
2575
|
-
[1026, "hash"],
|
|
2576
|
-
[1281, "revert"]
|
|
2577
|
-
];
|
|
2578
|
-
var SYSCALL_NAME_BY_ID = new Map(SYSCALLS);
|
|
2579
|
-
var SYSCALL_ID_BY_NAME = new Map(SYSCALLS.map(([id, name]) => [name, id]));
|
|
2580
|
-
var MrvValidationError = class extends Error {
|
|
2581
|
-
constructor(message) {
|
|
2582
|
-
super(message);
|
|
2583
|
-
this.name = "MrvValidationError";
|
|
2584
|
-
}
|
|
2585
|
-
};
|
|
2586
|
-
var MRV_STRUCTURED_FEE_FIELDS = [
|
|
2587
|
-
"total_lythoshi",
|
|
2588
|
-
"cycles_used",
|
|
2589
|
-
"base_price_per_cycle_lythoshi",
|
|
2590
|
-
"state_io_units",
|
|
2591
|
-
"state_io_price_per_unit_lythoshi",
|
|
2592
|
-
"priority_tip_lythoshi"
|
|
2593
|
-
];
|
|
2594
|
-
function formatLyth(lythoshi, options = {}) {
|
|
2595
|
-
const amount = BigInt(normalizeDecimalLike("lythoshi", lythoshi));
|
|
2596
|
-
const whole = amount / LYTHOSHI_PER_LYTH;
|
|
2597
|
-
const fraction = amount % LYTHOSHI_PER_LYTH;
|
|
2598
|
-
let formatted = formatWholeWithCommas(whole);
|
|
2599
|
-
if (fraction !== 0n) {
|
|
2600
|
-
formatted += `.${fraction.toString().padStart(NATIVE_LYTH_DECIMALS, "0").replace(/0+$/, "")}`;
|
|
2601
|
-
}
|
|
2602
|
-
if (options.includeUnit !== false) {
|
|
2603
|
-
formatted += " LYTH";
|
|
2604
|
-
}
|
|
2605
|
-
return formatted;
|
|
2606
|
-
}
|
|
2607
|
-
function formatLythoshi(lythoshi, options = {}) {
|
|
2608
|
-
return formatLyth(lythoshi, options);
|
|
2609
|
-
}
|
|
2610
|
-
function parseLythToLythoshi(input) {
|
|
2611
|
-
const numeric = stripLythUnit(input);
|
|
2612
|
-
const parts = numeric.split(".");
|
|
2613
|
-
if (parts.length > 2) {
|
|
2614
|
-
throw new MrvValidationError("lyth amount must be a canonical LYTH decimal");
|
|
2615
|
-
}
|
|
2616
|
-
const [wholeRaw, fractionRaw = ""] = parts;
|
|
2617
|
-
if (!isCanonicalWholeLyth(wholeRaw)) {
|
|
2618
|
-
throw new MrvValidationError("lyth amount must be a canonical LYTH decimal");
|
|
2619
|
-
}
|
|
2620
|
-
if (numeric.includes(".") && fractionRaw.length === 0) {
|
|
2621
|
-
throw new MrvValidationError("lyth amount must be a canonical LYTH decimal");
|
|
2622
|
-
}
|
|
2623
|
-
if (fractionRaw.length > NATIVE_LYTH_DECIMALS || !/^[0-9]*$/.test(fractionRaw)) {
|
|
2624
|
-
throw new MrvValidationError(`lyth amount supports at most ${NATIVE_LYTH_DECIMALS} decimal places`);
|
|
2625
|
-
}
|
|
2626
|
-
const whole = BigInt(wholeRaw.replaceAll(",", ""));
|
|
2627
|
-
const fraction = fractionRaw === "" ? 0n : BigInt(fractionRaw.padEnd(NATIVE_LYTH_DECIMALS, "0"));
|
|
2628
|
-
return whole * LYTHOSHI_PER_LYTH + fraction;
|
|
2629
|
-
}
|
|
2630
|
-
function checkMrvFeeDisplayConformance(input) {
|
|
2631
|
-
const expectedTotalLythoshi = normalizeDecimalLike("expectedTotalLythoshi", input.expectedTotalLythoshi);
|
|
2632
|
-
const expectedDefaultFeeText = formatLyth(expectedTotalLythoshi);
|
|
2633
|
-
const failures = [];
|
|
2634
|
-
const amountCandidates = extractLythAmountCandidates(input.defaultFeeText);
|
|
2635
|
-
if (amountCandidates.length !== 1) {
|
|
2636
|
-
failures.push("defaultFeeText must contain exactly one LYTH-denominated fee amount");
|
|
2637
|
-
} else {
|
|
2638
|
-
const renderedCandidate = `${amountCandidates[0]} LYTH`;
|
|
2639
|
-
if (renderedCandidate !== expectedDefaultFeeText) {
|
|
2640
|
-
failures.push(`defaultFeeText fee must be ${expectedDefaultFeeText}`);
|
|
2641
|
-
}
|
|
2642
|
-
try {
|
|
2643
|
-
const parsed = parseLythToLythoshi(renderedCandidate);
|
|
2644
|
-
if (parsed.toString() !== expectedTotalLythoshi) {
|
|
2645
|
-
failures.push(`defaultFeeText fee must total ${expectedTotalLythoshi} lythoshi`);
|
|
2646
|
-
}
|
|
2647
|
-
} catch {
|
|
2648
|
-
failures.push(`defaultFeeText fee must be a canonical ${NATIVE_LYTH_DECIMALS}-decimal LYTH amount`);
|
|
2649
|
-
}
|
|
2650
|
-
}
|
|
2651
|
-
const defaultForbidden = firstForbiddenDefaultFeeTerm(input.defaultFeeText);
|
|
2652
|
-
if (defaultForbidden !== void 0) {
|
|
2653
|
-
failures.push(`defaultFeeText exposes detail-only fee term '${defaultForbidden}'`);
|
|
1949
|
+
const defaultForbidden = firstForbiddenDefaultFeeTerm(input.defaultFeeText);
|
|
1950
|
+
if (defaultForbidden !== void 0) {
|
|
1951
|
+
failures.push(`defaultFeeText exposes detail-only fee term '${defaultForbidden}'`);
|
|
2654
1952
|
}
|
|
2655
1953
|
for (const [index, detailText] of (input.detailTexts ?? []).entries()) {
|
|
2656
1954
|
const detailForbidden = firstForbiddenDetailFeeTerm(detailText);
|
|
@@ -3029,29 +2327,28 @@ function buildMrvNativeFeePreview(executionUnitLimit, maxExecutionFeeLythoshi, p
|
|
|
3029
2327
|
async function submitMrvDeployNativeTx(client, backend, artifactBytes, options) {
|
|
3030
2328
|
const plan = buildMrvDeployNativeTxPlan(artifactBytes, options);
|
|
3031
2329
|
assertMrvDeployNativeSubmissionPlan(plan);
|
|
3032
|
-
return
|
|
2330
|
+
return submitMrvPlaintextNativeTx(client, backend, plan);
|
|
3033
2331
|
}
|
|
3034
2332
|
async function submitMrvDeployPayloadNativeTx(client, backend, artifactBytes, options) {
|
|
3035
2333
|
const plan = buildMrvDeployPayloadNativeTxPlan(artifactBytes, options);
|
|
3036
2334
|
assertMrvDeployNativeSubmissionPlan(plan);
|
|
3037
|
-
return
|
|
2335
|
+
return submitMrvPlaintextNativeTx(client, backend, plan);
|
|
3038
2336
|
}
|
|
3039
2337
|
async function submitMrvCallNativeTx(client, backend, contractAddress, input, options) {
|
|
3040
2338
|
const plan = buildMrvCallNativeTxPlan(contractAddress, input, options);
|
|
3041
2339
|
assertMrvCallNativeSubmissionPlan(plan);
|
|
3042
|
-
return
|
|
3043
|
-
}
|
|
3044
|
-
async function
|
|
3045
|
-
const submission =
|
|
3046
|
-
backend,
|
|
3047
|
-
tx: plan.tx,
|
|
3048
|
-
encryptionKey: options.encryptionKey ?? await fetchEncryptionKey(client),
|
|
3049
|
-
class: options.class
|
|
3050
|
-
});
|
|
2340
|
+
return submitMrvPlaintextNativeTx(client, backend, plan);
|
|
2341
|
+
}
|
|
2342
|
+
async function submitMrvPlaintextNativeTx(client, backend, plan) {
|
|
2343
|
+
const submission = buildPlaintextSubmission({ backend, tx: plan.tx });
|
|
3051
2344
|
return {
|
|
3052
2345
|
...plan,
|
|
3053
2346
|
...submission,
|
|
3054
|
-
txHash: await
|
|
2347
|
+
txHash: await submitPlaintextTransaction(
|
|
2348
|
+
client,
|
|
2349
|
+
submission.signedTxWireHex,
|
|
2350
|
+
submission.innerTxHashHex
|
|
2351
|
+
)
|
|
3055
2352
|
};
|
|
3056
2353
|
}
|
|
3057
2354
|
function assertMrvNativeSubmissionEnvelope(plan) {
|
|
@@ -3321,84 +2618,298 @@ function isCanonicalUnsignedDecimalString(value) {
|
|
|
3321
2618
|
} catch {
|
|
3322
2619
|
return false;
|
|
3323
2620
|
}
|
|
3324
|
-
}
|
|
3325
|
-
function normalizeDecimalLike(field2, value, defaultValue) {
|
|
3326
|
-
if (value === void 0) {
|
|
3327
|
-
if (defaultValue === void 0) throw new MrvValidationError(`${field2} is required`);
|
|
3328
|
-
return defaultValue;
|
|
2621
|
+
}
|
|
2622
|
+
function normalizeDecimalLike(field2, value, defaultValue) {
|
|
2623
|
+
if (value === void 0) {
|
|
2624
|
+
if (defaultValue === void 0) throw new MrvValidationError(`${field2} is required`);
|
|
2625
|
+
return defaultValue;
|
|
2626
|
+
}
|
|
2627
|
+
if (typeof value === "string") {
|
|
2628
|
+
validateDecimal(field2, value);
|
|
2629
|
+
return value;
|
|
2630
|
+
}
|
|
2631
|
+
if (typeof value === "number" && !Number.isSafeInteger(value)) {
|
|
2632
|
+
throw new MrvValidationError(`${field2} must be a safe unsigned integer`);
|
|
2633
|
+
}
|
|
2634
|
+
const out = BigInt(value);
|
|
2635
|
+
if (out < 0n) throw new MrvValidationError(`${field2} must be a canonical unsigned decimal string`);
|
|
2636
|
+
return out.toString();
|
|
2637
|
+
}
|
|
2638
|
+
function normalizeOptionalU64(field2, value) {
|
|
2639
|
+
return value === void 0 ? void 0 : normalizeU64(value, field2);
|
|
2640
|
+
}
|
|
2641
|
+
function validateDecimal(field2, value) {
|
|
2642
|
+
if (!/^(0|[1-9][0-9]*)$/.test(value)) {
|
|
2643
|
+
throw new MrvValidationError(`${field2} must be a canonical unsigned decimal string`);
|
|
2644
|
+
}
|
|
2645
|
+
try {
|
|
2646
|
+
BigInt(value);
|
|
2647
|
+
} catch {
|
|
2648
|
+
throw new MrvValidationError(`${field2} must be a canonical unsigned decimal string`);
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
function validateExecutionUnitLimit(field2, value) {
|
|
2652
|
+
if (value !== void 0 && BigInt(value) === 0n) {
|
|
2653
|
+
throw new MrvValidationError(`${field2} must be greater than zero`);
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
function normalizeU64(value, field2) {
|
|
2657
|
+
if (typeof value === "number" && !Number.isSafeInteger(value)) {
|
|
2658
|
+
throw new MrvValidationError(`${field2} must be a safe unsigned integer`);
|
|
2659
|
+
}
|
|
2660
|
+
const out = BigInt(value);
|
|
2661
|
+
if (out < 0n || out > 0xffffffffffffffffn) {
|
|
2662
|
+
throw new MrvValidationError(`${field2} must fit in u64`);
|
|
2663
|
+
}
|
|
2664
|
+
return out;
|
|
2665
|
+
}
|
|
2666
|
+
function validateHexLength(field2, value, expected) {
|
|
2667
|
+
const bytes = hexToBytes3(value, field2);
|
|
2668
|
+
if (bytes.length !== expected) throw new MrvValidationError(`${field2} must be ${expected} bytes`);
|
|
2669
|
+
}
|
|
2670
|
+
function bytesFrom(value, field2) {
|
|
2671
|
+
if (typeof value === "string") return hexToBytes3(value, field2);
|
|
2672
|
+
return value instanceof Uint8Array ? value : Uint8Array.from(value);
|
|
2673
|
+
}
|
|
2674
|
+
function hexToBytes3(value, field2) {
|
|
2675
|
+
if (!/^0x(?:[0-9a-fA-F]{2})*$/.test(value)) {
|
|
2676
|
+
throw new MrvValidationError(`${field2} must be 0x-prefixed even-length hex`);
|
|
2677
|
+
}
|
|
2678
|
+
const out = new Uint8Array((value.length - 2) / 2);
|
|
2679
|
+
for (let i = 0; i < out.length; i++) {
|
|
2680
|
+
out[i] = Number.parseInt(value.slice(2 + i * 2, 4 + i * 2), 16);
|
|
2681
|
+
}
|
|
2682
|
+
return out;
|
|
2683
|
+
}
|
|
2684
|
+
function bytesToHex3(bytes) {
|
|
2685
|
+
return `0x${[...bytes].map((b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
2686
|
+
}
|
|
2687
|
+
function concatBytes3(...parts) {
|
|
2688
|
+
const len = parts.reduce((sum, item) => sum + item.length, 0);
|
|
2689
|
+
const out = new Uint8Array(len);
|
|
2690
|
+
let offset = 0;
|
|
2691
|
+
for (const part of parts) {
|
|
2692
|
+
out.set(part, offset);
|
|
2693
|
+
offset += part.length;
|
|
2694
|
+
}
|
|
2695
|
+
return out;
|
|
2696
|
+
}
|
|
2697
|
+
function isIdentifier(value) {
|
|
2698
|
+
return /^[a-z][a-z0-9_]*$/.test(value);
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
// src/crypto/tx.ts
|
|
2702
|
+
function encodeTransactionForHash(fields, tag) {
|
|
2703
|
+
const n = normalizeTxFields(fields);
|
|
2704
|
+
return concatBytes2(
|
|
2705
|
+
Uint8Array.of(tag),
|
|
2706
|
+
bigintToBeBytes(n.chainId, 8, "chainId"),
|
|
2707
|
+
bigintToBeBytes(n.nonce, 8, "nonce"),
|
|
2708
|
+
bigintToBeBytes(n.maxPriorityFeePerGas, 32, "maxPriorityFeePerGas"),
|
|
2709
|
+
bigintToBeBytes(n.maxFeePerGas, 32, "maxFeePerGas"),
|
|
2710
|
+
bigintToBeBytes(n.gasLimit, 8, "gasLimit"),
|
|
2711
|
+
n.to === null ? Uint8Array.of(0) : concatBytes2(Uint8Array.of(1), n.to),
|
|
2712
|
+
bigintToBeBytes(n.value, 32, "value"),
|
|
2713
|
+
bigintToBeBytes(BigInt(n.input.length), 4, "input.length"),
|
|
2714
|
+
n.input,
|
|
2715
|
+
new Uint8Array(4),
|
|
2716
|
+
// access_list length
|
|
2717
|
+
encodeExtensionsForHash(n.extensions)
|
|
2718
|
+
);
|
|
2719
|
+
}
|
|
2720
|
+
function bincodeSignedTransaction(fields, signature, publicKey) {
|
|
2721
|
+
const n = normalizeTxFields(fields);
|
|
2722
|
+
const sig = expectBytes(signature, ML_DSA_65_SIGNATURE_LEN, "ML-DSA-65 signature");
|
|
2723
|
+
const pk = expectBytes(publicKey, ML_DSA_65_PUBLIC_KEY_LEN, "ML-DSA-65 public key");
|
|
2724
|
+
const w = new BincodeWriter();
|
|
2725
|
+
w.u64(n.chainId);
|
|
2726
|
+
w.u64(n.nonce);
|
|
2727
|
+
w.bytes(uint256Be(n.maxPriorityFeePerGas, "maxPriorityFeePerGas"));
|
|
2728
|
+
w.bytes(uint256Be(n.maxFeePerGas, "maxFeePerGas"));
|
|
2729
|
+
w.u64(n.gasLimit);
|
|
2730
|
+
if (n.to === null) {
|
|
2731
|
+
w.u8(0);
|
|
2732
|
+
} else {
|
|
2733
|
+
w.u8(1);
|
|
2734
|
+
w.bytes(n.to);
|
|
2735
|
+
}
|
|
2736
|
+
w.bytes(uint256Be(n.value, "value"));
|
|
2737
|
+
w.bytes(n.input);
|
|
2738
|
+
w.u64(0n);
|
|
2739
|
+
w.u64(BigInt(n.extensions.length));
|
|
2740
|
+
for (const ext of n.extensions) bincodeTypedExtensionInto(w, ext);
|
|
2741
|
+
bincodeMlDsa65OpaqueInto(w, sig);
|
|
2742
|
+
bincodeMlDsa65OpaqueInto(w, pk);
|
|
2743
|
+
return w.toBytes();
|
|
2744
|
+
}
|
|
2745
|
+
function normalizeTxFields(fields) {
|
|
2746
|
+
return {
|
|
2747
|
+
chainId: parseBigint(fields.chainId, "chainId"),
|
|
2748
|
+
nonce: parseBigint(fields.nonce, "nonce"),
|
|
2749
|
+
maxPriorityFeePerGas: parseBigint(fields.maxPriorityFeePerGas, "maxPriorityFeePerGas"),
|
|
2750
|
+
maxFeePerGas: parseBigint(fields.maxFeePerGas, "maxFeePerGas"),
|
|
2751
|
+
gasLimit: parseBigint(fields.gasLimit, "gasLimit"),
|
|
2752
|
+
to: normalizeTo(fields.to),
|
|
2753
|
+
value: parseBigint(fields.value, "value"),
|
|
2754
|
+
input: normalizeBytes(fields.input ?? new Uint8Array(0), "input"),
|
|
2755
|
+
extensions: normalizeExtensions(fields.extensions)
|
|
2756
|
+
};
|
|
2757
|
+
}
|
|
2758
|
+
function normalizeTo(value) {
|
|
2759
|
+
if (value === null) return null;
|
|
2760
|
+
const bytes = normalizeBytes(value, "to");
|
|
2761
|
+
return expectBytes(bytes, 20, "to");
|
|
2762
|
+
}
|
|
2763
|
+
function normalizeBytes(value, label) {
|
|
2764
|
+
if (typeof value === "string") return hexToBytes2(value, label);
|
|
2765
|
+
return value instanceof Uint8Array ? value : Uint8Array.from(value);
|
|
2766
|
+
}
|
|
2767
|
+
function normalizeExtensions(value) {
|
|
2768
|
+
if (value === void 0) return [];
|
|
2769
|
+
return value.map((ext, index) => {
|
|
2770
|
+
if (!Number.isInteger(ext.kind) || ext.kind < 0 || ext.kind > 255) {
|
|
2771
|
+
throw new Error(`extensions[${index}].kind out of u8 range`);
|
|
2772
|
+
}
|
|
2773
|
+
const body = normalizeBytes("bodyHex" in ext ? ext.bodyHex : ext.body, `extensions[${index}].body`);
|
|
2774
|
+
if (body.length > 4294967295) {
|
|
2775
|
+
throw new Error(`extensions[${index}].body exceeds u32 length`);
|
|
2776
|
+
}
|
|
2777
|
+
return { kind: ext.kind, body };
|
|
2778
|
+
});
|
|
2779
|
+
}
|
|
2780
|
+
function encodeExtensionsForHash(extensions) {
|
|
2781
|
+
const chunks = [bigintToBeBytes(BigInt(extensions.length), 4, "extensions.length")];
|
|
2782
|
+
for (const ext of extensions) {
|
|
2783
|
+
chunks.push(
|
|
2784
|
+
Uint8Array.of(ext.kind),
|
|
2785
|
+
bigintToBeBytes(BigInt(ext.body.length), 4, "extension.body.length"),
|
|
2786
|
+
ext.body
|
|
2787
|
+
);
|
|
2788
|
+
}
|
|
2789
|
+
return concatBytes2(...chunks);
|
|
2790
|
+
}
|
|
2791
|
+
function uint256Be(value, label) {
|
|
2792
|
+
if (value < 0n || value >= 1n << 256n) throw new Error(`${label} out of u256 range`);
|
|
2793
|
+
const out = new Uint8Array(32);
|
|
2794
|
+
let v = value;
|
|
2795
|
+
for (let i = 31; i >= 0; i--) {
|
|
2796
|
+
out[i] = Number(v & 0xffn);
|
|
2797
|
+
v >>= 8n;
|
|
2798
|
+
}
|
|
2799
|
+
return out;
|
|
2800
|
+
}
|
|
2801
|
+
function bincodeMlDsa65OpaqueInto(w, raw) {
|
|
2802
|
+
w.enumVariant(ENUM_VARIANT_INDEX_ML_DSA_65);
|
|
2803
|
+
w.u16(STANDARD_ALGO_NUMBER_ML_DSA_65);
|
|
2804
|
+
w.bytes(raw);
|
|
2805
|
+
}
|
|
2806
|
+
function bincodeTypedExtensionInto(w, ext) {
|
|
2807
|
+
w.u8(ext.kind);
|
|
2808
|
+
w.bytes(ext.body);
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
// src/crypto/ml-dsa.ts
|
|
2812
|
+
var ML_DSA_65_SEED_LEN = 32;
|
|
2813
|
+
var ML_DSA_65_SIGNING_KEY_LEN = 4032;
|
|
2814
|
+
var ML_DSA_65_PUBLIC_KEY_LEN = 1952;
|
|
2815
|
+
var ML_DSA_65_SIGNATURE_LEN = 3309;
|
|
2816
|
+
var STANDARD_ALGO_NUMBER_ML_DSA_65 = 1001;
|
|
2817
|
+
var ENUM_VARIANT_INDEX_ML_DSA_65 = 3;
|
|
2818
|
+
var ADDRESS_DERIVATION_DOMAIN = "MONO_ADDRESS_BLAKE3_20_V1";
|
|
2819
|
+
var ADDRESS_DERIVATION_DOMAIN_BYTES = new TextEncoder().encode(ADDRESS_DERIVATION_DOMAIN);
|
|
2820
|
+
var MlDsa65Backend = class _MlDsa65Backend {
|
|
2821
|
+
#secretKey;
|
|
2822
|
+
#publicKey;
|
|
2823
|
+
#addressBytes;
|
|
2824
|
+
#disposed = false;
|
|
2825
|
+
constructor(secretKey, publicKey) {
|
|
2826
|
+
this.#secretKey = expectBytes(secretKey, ML_DSA_65_SIGNING_KEY_LEN, "ML-DSA-65 secret key").slice();
|
|
2827
|
+
this.#publicKey = expectBytes(publicKey, ML_DSA_65_PUBLIC_KEY_LEN, "ML-DSA-65 public key").slice();
|
|
2828
|
+
this.#addressBytes = mlDsa65AddressBytes(this.#publicKey);
|
|
2829
|
+
}
|
|
2830
|
+
static fromSeed(seed) {
|
|
2831
|
+
const kp = mlDsa_js.ml_dsa65.keygen(expectBytes(seed, ML_DSA_65_SEED_LEN, "ML-DSA-65 seed"));
|
|
2832
|
+
return new _MlDsa65Backend(kp.secretKey, kp.publicKey);
|
|
3329
2833
|
}
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
return value;
|
|
2834
|
+
publicKey() {
|
|
2835
|
+
return this.#publicKey.slice();
|
|
3333
2836
|
}
|
|
3334
|
-
|
|
3335
|
-
|
|
2837
|
+
addressBytes() {
|
|
2838
|
+
return this.#addressBytes.slice();
|
|
3336
2839
|
}
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
return out.toString();
|
|
3340
|
-
}
|
|
3341
|
-
function normalizeOptionalU64(field2, value) {
|
|
3342
|
-
return value === void 0 ? void 0 : normalizeU64(value, field2);
|
|
3343
|
-
}
|
|
3344
|
-
function validateDecimal(field2, value) {
|
|
3345
|
-
if (!/^(0|[1-9][0-9]*)$/.test(value)) {
|
|
3346
|
-
throw new MrvValidationError(`${field2} must be a canonical unsigned decimal string`);
|
|
2840
|
+
getAddress() {
|
|
2841
|
+
return bytesToHex2(this.#addressBytes);
|
|
3347
2842
|
}
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
2843
|
+
sign(message) {
|
|
2844
|
+
if (this.#disposed) {
|
|
2845
|
+
throw new Error("MlDsa65Backend disposed");
|
|
2846
|
+
}
|
|
2847
|
+
return mlDsa_js.ml_dsa65.sign(message, this.#secretKey, { extraEntropy: false });
|
|
3352
2848
|
}
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
2849
|
+
/**
|
|
2850
|
+
* Best-effort deterministic wipe of the in-memory secret key. Zeroes the
|
|
2851
|
+
* SDK-held `#secretKey` copy and makes any subsequent `sign()` /
|
|
2852
|
+
* `signPrehash()` / `signEvmTx()` throw `"MlDsa65Backend disposed"` rather
|
|
2853
|
+
* than signing with a zeroed key. Idempotent. Public material
|
|
2854
|
+
* (`publicKey()` / `getAddress()` / `verify()`) stays usable.
|
|
2855
|
+
*
|
|
2856
|
+
* Defense-in-depth (S1-01): narrows the post-lock residency window of the
|
|
2857
|
+
* ML-DSA-65 secret in the JS heap. `@noble/post-quantum`'s internal
|
|
2858
|
+
* transient keygen/sign buffers are out of scope; the SDK-held copy is the
|
|
2859
|
+
* meaningful residency win.
|
|
2860
|
+
*/
|
|
2861
|
+
dispose() {
|
|
2862
|
+
this.#secretKey.fill(0);
|
|
2863
|
+
this.#disposed = true;
|
|
3357
2864
|
}
|
|
3358
|
-
}
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
throw new MrvValidationError(`${field2} must be a safe unsigned integer`);
|
|
2865
|
+
/** Alias for {@link dispose}. */
|
|
2866
|
+
zeroize() {
|
|
2867
|
+
this.dispose();
|
|
3362
2868
|
}
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
2869
|
+
/** Whether {@link dispose} has been called (the secret key is wiped). */
|
|
2870
|
+
get disposed() {
|
|
2871
|
+
return this.#disposed;
|
|
3366
2872
|
}
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
function validateHexLength(field2, value, expected) {
|
|
3370
|
-
const bytes = hexToBytes3(value, field2);
|
|
3371
|
-
if (bytes.length !== expected) throw new MrvValidationError(`${field2} must be ${expected} bytes`);
|
|
3372
|
-
}
|
|
3373
|
-
function bytesFrom(value, field2) {
|
|
3374
|
-
if (typeof value === "string") return hexToBytes3(value, field2);
|
|
3375
|
-
return value instanceof Uint8Array ? value : Uint8Array.from(value);
|
|
3376
|
-
}
|
|
3377
|
-
function hexToBytes3(value, field2) {
|
|
3378
|
-
if (!/^0x(?:[0-9a-fA-F]{2})*$/.test(value)) {
|
|
3379
|
-
throw new MrvValidationError(`${field2} must be 0x-prefixed even-length hex`);
|
|
2873
|
+
signPrehash(digest) {
|
|
2874
|
+
return this.sign(expectBytes(digest, 32, "prehash"));
|
|
3380
2875
|
}
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
2876
|
+
verify(message, signature) {
|
|
2877
|
+
return mlDsa_js.ml_dsa65.verify(
|
|
2878
|
+
expectBytes(signature, ML_DSA_65_SIGNATURE_LEN, "ML-DSA-65 signature"),
|
|
2879
|
+
message,
|
|
2880
|
+
this.#publicKey
|
|
2881
|
+
);
|
|
3384
2882
|
}
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
2883
|
+
signEvmTx(fields) {
|
|
2884
|
+
const txHashPreimage = encodeTransactionForHash(fields, 1);
|
|
2885
|
+
const sighash = sha3_js.keccak_256(txHashPreimage);
|
|
2886
|
+
const signature = this.sign(sighash);
|
|
2887
|
+
const wireBytes = bincodeSignedTransaction(fields, signature, this.#publicKey);
|
|
2888
|
+
const txHash = sha3_js.keccak_256(
|
|
2889
|
+
concatBytes2(
|
|
2890
|
+
encodeTransactionForHash(fields, 2),
|
|
2891
|
+
signature,
|
|
2892
|
+
this.#publicKey
|
|
2893
|
+
)
|
|
2894
|
+
);
|
|
2895
|
+
return {
|
|
2896
|
+
wireHex: bytesToHex2(wireBytes).slice(2),
|
|
2897
|
+
wireBytes,
|
|
2898
|
+
sighash,
|
|
2899
|
+
txHash
|
|
2900
|
+
};
|
|
3397
2901
|
}
|
|
3398
|
-
|
|
2902
|
+
};
|
|
2903
|
+
function mlDsa65AddressFromPublicKey(publicKey) {
|
|
2904
|
+
return bytesToHex2(mlDsa65AddressBytes(publicKey));
|
|
3399
2905
|
}
|
|
3400
|
-
function
|
|
3401
|
-
|
|
2906
|
+
function mlDsa65AddressBytes(publicKey) {
|
|
2907
|
+
const bytes = expectBytes(publicKey, ML_DSA_65_PUBLIC_KEY_LEN, "ML-DSA-65 public key");
|
|
2908
|
+
return blake3_js.blake3(concatBytes2(
|
|
2909
|
+
ADDRESS_DERIVATION_DOMAIN_BYTES,
|
|
2910
|
+
bigintToBeBytes(BigInt(STANDARD_ALGO_NUMBER_ML_DSA_65), 2, "ML-DSA-65 algo id"),
|
|
2911
|
+
bytes
|
|
2912
|
+
)).slice(0, 20);
|
|
3402
2913
|
}
|
|
3403
2914
|
|
|
3404
2915
|
// src/registry.ts
|
|
@@ -3408,8 +2919,8 @@ var TESTNET_69420 = {
|
|
|
3408
2919
|
network: "testnet-69420",
|
|
3409
2920
|
display_name: "Monolythium Testnet",
|
|
3410
2921
|
description: "Public Monolythium testnet. Testnet state may reset without notice; do not store value on this network.",
|
|
3411
|
-
genesis_hash: "
|
|
3412
|
-
binary_sha: "
|
|
2922
|
+
genesis_hash: "0xb52b59d667a0ad97c531607b840b7082547ba3151aa11a819eb6916b080b1ca9",
|
|
2923
|
+
binary_sha: "6f33aa30",
|
|
3413
2924
|
rpc: [
|
|
3414
2925
|
{
|
|
3415
2926
|
url: "http://178.105.12.9:8545",
|
|
@@ -4989,14 +4500,6 @@ var RpcClient = class _RpcClient {
|
|
|
4989
4500
|
async lythSubmitPendingChange(envelope) {
|
|
4990
4501
|
return this.call("lyth_submitPendingChange", [envelope]);
|
|
4991
4502
|
}
|
|
4992
|
-
/** `lyth_submitEncrypted` — submit a bincode-encoded encrypted envelope hex. */
|
|
4993
|
-
async lythSubmitEncrypted(envelopeHex) {
|
|
4994
|
-
return this.call("lyth_submitEncrypted", [envelopeHex]);
|
|
4995
|
-
}
|
|
4996
|
-
/** `lyth_getEncryptionKey` — cluster ML-KEM encapsulation key. */
|
|
4997
|
-
async lythGetEncryptionKey() {
|
|
4998
|
-
return this.call("lyth_getEncryptionKey", []);
|
|
4999
|
-
}
|
|
5000
4503
|
/** `lyth_syncStatus` — DAG-sync driver snapshot. */
|
|
5001
4504
|
async lythSyncStatus() {
|
|
5002
4505
|
const v = await this.call("lyth_syncStatus", []);
|
|
@@ -8153,7 +7656,7 @@ function verifyBoundedReceiptProof(proof) {
|
|
|
8153
7656
|
}
|
|
8154
7657
|
const actualRoot = computeNoEvmReceiptsRoot(receipts);
|
|
8155
7658
|
const expectedRoot = decodeHash(proof.receiptsRoot, "receiptsRoot");
|
|
8156
|
-
if (!
|
|
7659
|
+
if (!bytesEqual2(expectedRoot, decodeHash(actualRoot, "computedReceiptsRoot"))) {
|
|
8157
7660
|
throw new NoEvmReceiptProofError(
|
|
8158
7661
|
"receipts_root_mismatch",
|
|
8159
7662
|
`receiptsRoot mismatch: expected ${proof.receiptsRoot}, computed ${actualRoot}`
|
|
@@ -8161,7 +7664,7 @@ function verifyBoundedReceiptProof(proof) {
|
|
|
8161
7664
|
}
|
|
8162
7665
|
const actualTargetHash = computeNoEvmTargetReceiptHash(targetReceipt);
|
|
8163
7666
|
const expectedTargetHash = decodeHash(proof.targetReceiptHash, "targetReceiptHash");
|
|
8164
|
-
if (!
|
|
7667
|
+
if (!bytesEqual2(expectedTargetHash, decodeHash(actualTargetHash, "computedTargetReceiptHash"))) {
|
|
8165
7668
|
throw new NoEvmReceiptProofError(
|
|
8166
7669
|
"target_receipt_hash_mismatch",
|
|
8167
7670
|
`targetReceiptHash mismatch: expected ${proof.targetReceiptHash}, computed ${actualTargetHash}`
|
|
@@ -8218,7 +7721,7 @@ function verifyCompactReceiptProof(proof) {
|
|
|
8218
7721
|
const targetReceipt = decodeHexBytes(targetReceiptBytes, "targetReceiptBytes");
|
|
8219
7722
|
const actualTargetHash = computeNoEvmTargetReceiptHash(targetReceipt);
|
|
8220
7723
|
const expectedTargetHash = decodeHash(proof.targetReceiptHash, "targetReceiptHash");
|
|
8221
|
-
if (!
|
|
7724
|
+
if (!bytesEqual2(expectedTargetHash, decodeHash(actualTargetHash, "computedTargetReceiptHash"))) {
|
|
8222
7725
|
throw new NoEvmReceiptProofError(
|
|
8223
7726
|
"target_receipt_hash_mismatch",
|
|
8224
7727
|
`targetReceiptHash mismatch: expected ${proof.targetReceiptHash}, computed ${actualTargetHash}`
|
|
@@ -8229,7 +7732,7 @@ function verifyCompactReceiptProof(proof) {
|
|
|
8229
7732
|
compactProof.leafHash,
|
|
8230
7733
|
"compactInclusionProof.leafHash"
|
|
8231
7734
|
);
|
|
8232
|
-
if (!
|
|
7735
|
+
if (!bytesEqual2(expectedLeafHashBytes, actualLeafHashBytes)) {
|
|
8233
7736
|
throw new NoEvmReceiptProofError(
|
|
8234
7737
|
"compact_leaf_hash_mismatch",
|
|
8235
7738
|
`compactInclusionProof.leafHash mismatch: expected ${compactProof.leafHash}, computed ${bytesToHex6(
|
|
@@ -8239,7 +7742,7 @@ function verifyCompactReceiptProof(proof) {
|
|
|
8239
7742
|
}
|
|
8240
7743
|
const compactRootBytes = decodeHash(compactProof.root, "compactInclusionProof.root");
|
|
8241
7744
|
const receiptsRootBytes = decodeHash(proof.receiptsRoot, "receiptsRoot");
|
|
8242
|
-
if (!
|
|
7745
|
+
if (!bytesEqual2(receiptsRootBytes, compactRootBytes)) {
|
|
8243
7746
|
throw new NoEvmReceiptProofError(
|
|
8244
7747
|
"compact_root_mismatch",
|
|
8245
7748
|
`receiptsRoot must equal compactInclusionProof.root: receiptsRoot ${proof.receiptsRoot}, compact root ${compactProof.root}`
|
|
@@ -8262,7 +7765,7 @@ function verifyCompactReceiptProof(proof) {
|
|
|
8262
7765
|
siblingHashes,
|
|
8263
7766
|
pathSides
|
|
8264
7767
|
);
|
|
8265
|
-
if (!
|
|
7768
|
+
if (!bytesEqual2(actualRootBytes, compactRootBytes)) {
|
|
8266
7769
|
throw new NoEvmReceiptProofError(
|
|
8267
7770
|
"compact_path_mismatch",
|
|
8268
7771
|
`compact inclusion path mismatch: expected ${compactProof.root}, computed ${bytesToHex6(
|
|
@@ -8416,7 +7919,7 @@ function validateCoveringSnapshotObject(snapshot, archiveContentHash, proofBlock
|
|
|
8416
7919
|
"archiveProof.coveringSnapshot.checkpointTo must match blockHeight"
|
|
8417
7920
|
);
|
|
8418
7921
|
}
|
|
8419
|
-
if (!
|
|
7922
|
+
if (!bytesEqual2(checkpointContentHash, archiveContentHash)) {
|
|
8420
7923
|
throw new NoEvmReceiptProofError(
|
|
8421
7924
|
"invalid_proof_shape",
|
|
8422
7925
|
"archiveProof.coveringSnapshot.checkpointContentHash must match archiveProof.contentHash"
|
|
@@ -8615,7 +8118,7 @@ function validateFinalityBlockReference(blockReference, round, proofBlockHash) {
|
|
|
8615
8118
|
);
|
|
8616
8119
|
if (proofBlockHash !== void 0) {
|
|
8617
8120
|
const blockHash = decodeHash(proofBlockHash, "blockHash");
|
|
8618
|
-
if (!
|
|
8121
|
+
if (!bytesEqual2(digest, blockHash)) {
|
|
8619
8122
|
throw new NoEvmReceiptProofError(
|
|
8620
8123
|
"invalid_proof_shape",
|
|
8621
8124
|
"finalityEvidence.blockReference.digest must match blockHash"
|
|
@@ -8965,7 +8468,7 @@ function assertHashBytes(value, field2) {
|
|
|
8965
8468
|
function isRecord3(value) {
|
|
8966
8469
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8967
8470
|
}
|
|
8968
|
-
function
|
|
8471
|
+
function bytesEqual2(a, b) {
|
|
8969
8472
|
if (a.length !== b.length) return false;
|
|
8970
8473
|
let diff = 0;
|
|
8971
8474
|
for (let index = 0; index < a.length; index++) {
|
|
@@ -8980,6 +8483,191 @@ function bytesToHex6(bytes) {
|
|
|
8980
8483
|
}
|
|
8981
8484
|
return out;
|
|
8982
8485
|
}
|
|
8486
|
+
var TREE_TAG_LEAF = 0;
|
|
8487
|
+
var TREE_TAG_INTERNAL = 1;
|
|
8488
|
+
var TREE_TERMINATOR = new Uint8Array(32);
|
|
8489
|
+
var HASH_BYTE_LENGTH2 = 32;
|
|
8490
|
+
var PROOF_KIND_BINARY = "binary";
|
|
8491
|
+
var ProofVerifyError = class extends Error {
|
|
8492
|
+
constructor(code, message) {
|
|
8493
|
+
super(message);
|
|
8494
|
+
this.code = code;
|
|
8495
|
+
this.name = "ProofVerifyError";
|
|
8496
|
+
}
|
|
8497
|
+
code;
|
|
8498
|
+
};
|
|
8499
|
+
function hashValue(data) {
|
|
8500
|
+
return blake3_js.blake3(data);
|
|
8501
|
+
}
|
|
8502
|
+
function hashLeaf(path, valueHash) {
|
|
8503
|
+
const buf = new Uint8Array(1 + 32 + 32);
|
|
8504
|
+
buf[0] = TREE_TAG_LEAF;
|
|
8505
|
+
buf.set(path, 1);
|
|
8506
|
+
buf.set(valueHash, 33);
|
|
8507
|
+
return blake3_js.blake3(buf);
|
|
8508
|
+
}
|
|
8509
|
+
function compress(left, right) {
|
|
8510
|
+
if (isTerminator(left) && isTerminator(right)) {
|
|
8511
|
+
return TREE_TERMINATOR;
|
|
8512
|
+
}
|
|
8513
|
+
const buf = new Uint8Array(1 + 32 + 32);
|
|
8514
|
+
buf[0] = TREE_TAG_INTERNAL;
|
|
8515
|
+
buf.set(left, 1);
|
|
8516
|
+
buf.set(right, 33);
|
|
8517
|
+
return blake3_js.blake3(buf);
|
|
8518
|
+
}
|
|
8519
|
+
function isTerminator(hash) {
|
|
8520
|
+
for (let i = 0; i < hash.length; i++) {
|
|
8521
|
+
if (hash[i] !== 0) return false;
|
|
8522
|
+
}
|
|
8523
|
+
return true;
|
|
8524
|
+
}
|
|
8525
|
+
function pathBit(path, depth) {
|
|
8526
|
+
const byte = path[depth >>> 3];
|
|
8527
|
+
return byte >>> 7 - (depth & 7) & 1;
|
|
8528
|
+
}
|
|
8529
|
+
function foldToRoot(target, current, siblings) {
|
|
8530
|
+
const depth = siblings.length;
|
|
8531
|
+
let node = current;
|
|
8532
|
+
for (let i = 0; i < depth; i++) {
|
|
8533
|
+
const level = depth - 1 - i;
|
|
8534
|
+
const sibling = siblings[i];
|
|
8535
|
+
node = pathBit(target, level) === 0 ? compress(node, sibling) : compress(sibling, node);
|
|
8536
|
+
}
|
|
8537
|
+
return node;
|
|
8538
|
+
}
|
|
8539
|
+
function bytesEqual3(a, b) {
|
|
8540
|
+
if (a.length !== b.length) return false;
|
|
8541
|
+
for (let i = 0; i < a.length; i++) {
|
|
8542
|
+
if (a[i] !== b[i]) return false;
|
|
8543
|
+
}
|
|
8544
|
+
return true;
|
|
8545
|
+
}
|
|
8546
|
+
function decodeHash2(value, field2) {
|
|
8547
|
+
let bytes;
|
|
8548
|
+
try {
|
|
8549
|
+
bytes = hexToBytes2(value, field2);
|
|
8550
|
+
} catch (cause) {
|
|
8551
|
+
throw new ProofVerifyError("invalid_hex", `${field2} is not valid hex: ${String(cause)}`);
|
|
8552
|
+
}
|
|
8553
|
+
if (bytes.length !== HASH_BYTE_LENGTH2) {
|
|
8554
|
+
throw new ProofVerifyError(
|
|
8555
|
+
"invalid_hash_length",
|
|
8556
|
+
`${field2} must be ${HASH_BYTE_LENGTH2} bytes, got ${bytes.length}`
|
|
8557
|
+
);
|
|
8558
|
+
}
|
|
8559
|
+
return bytes;
|
|
8560
|
+
}
|
|
8561
|
+
function decodeSiblings(siblings) {
|
|
8562
|
+
return siblings.map((sib, index) => decodeHash2(sib, `siblings[${index}]`));
|
|
8563
|
+
}
|
|
8564
|
+
function assertBinaryKind(proofKind) {
|
|
8565
|
+
if (proofKind !== PROOF_KIND_BINARY) {
|
|
8566
|
+
throw new ProofVerifyError(
|
|
8567
|
+
"unsupported_proof_kind",
|
|
8568
|
+
`unsupported proofKind: ${proofKind} (expected ${PROOF_KIND_BINARY})`
|
|
8569
|
+
);
|
|
8570
|
+
}
|
|
8571
|
+
}
|
|
8572
|
+
var ProofVerifier = class {
|
|
8573
|
+
/**
|
|
8574
|
+
* Verify a {@link ProofEnvelope} inclusion proof against `stateRoot`.
|
|
8575
|
+
*
|
|
8576
|
+
* @returns `true` when the proof binds `(key, value)` to `stateRoot`.
|
|
8577
|
+
*/
|
|
8578
|
+
verifyInclusion(stateRoot, proof) {
|
|
8579
|
+
assertBinaryKind(proof.proofKind);
|
|
8580
|
+
const root = toHashBytes(stateRoot, "stateRoot");
|
|
8581
|
+
const key = decodeHex(proof.key, "proof.key");
|
|
8582
|
+
const value = decodeHex(proof.value, "proof.value");
|
|
8583
|
+
const siblings = decodeSiblings(proof.siblings);
|
|
8584
|
+
const target = hashValue(key);
|
|
8585
|
+
const leaf = hashLeaf(target, hashValue(value));
|
|
8586
|
+
return bytesEqual3(foldToRoot(target, leaf, siblings), root);
|
|
8587
|
+
}
|
|
8588
|
+
/**
|
|
8589
|
+
* Verify a {@link ProofEnvelope} inclusion proof, throwing a
|
|
8590
|
+
* {@link ProofVerifyError} on failure (the loud variant for wallets).
|
|
8591
|
+
*/
|
|
8592
|
+
assertInclusion(stateRoot, proof) {
|
|
8593
|
+
if (!this.verifyInclusion(stateRoot, proof)) {
|
|
8594
|
+
throw new ProofVerifyError(
|
|
8595
|
+
"proof_verify_failed",
|
|
8596
|
+
`inclusion proof for key ${proof.key} does not verify against the state root`
|
|
8597
|
+
);
|
|
8598
|
+
}
|
|
8599
|
+
}
|
|
8600
|
+
/**
|
|
8601
|
+
* Verify a {@link NonInclusionProofEnvelope} against `stateRoot`.
|
|
8602
|
+
*
|
|
8603
|
+
* Returns `false` for a `found` endpoint (that is an inclusion, not
|
|
8604
|
+
* absence) or an `otherLeaf` whose path equals the queried key. Mirrors
|
|
8605
|
+
* `protocore_state::verify_binary_non_inclusion`.
|
|
8606
|
+
*/
|
|
8607
|
+
verifyNonInclusion(stateRoot, proof) {
|
|
8608
|
+
assertBinaryKind(proof.proofKind);
|
|
8609
|
+
const root = toHashBytes(stateRoot, "stateRoot");
|
|
8610
|
+
const key = decodeHex(proof.key, "proof.key");
|
|
8611
|
+
const siblings = decodeSiblings(proof.siblings);
|
|
8612
|
+
const target = hashValue(key);
|
|
8613
|
+
let endpointHash;
|
|
8614
|
+
switch (proof.endpoint.kind) {
|
|
8615
|
+
case "found":
|
|
8616
|
+
return false;
|
|
8617
|
+
case "terminator":
|
|
8618
|
+
endpointHash = TREE_TERMINATOR;
|
|
8619
|
+
break;
|
|
8620
|
+
case "otherLeaf": {
|
|
8621
|
+
const path = decodeHash2(proof.endpoint.path, "endpoint.path");
|
|
8622
|
+
if (bytesEqual3(path, target)) return false;
|
|
8623
|
+
endpointHash = hashLeaf(path, decodeHash2(proof.endpoint.valueHash, "endpoint.valueHash"));
|
|
8624
|
+
break;
|
|
8625
|
+
}
|
|
8626
|
+
}
|
|
8627
|
+
return bytesEqual3(foldToRoot(target, endpointHash, siblings), root);
|
|
8628
|
+
}
|
|
8629
|
+
/**
|
|
8630
|
+
* Verify a non-inclusion proof, throwing a {@link ProofVerifyError} on
|
|
8631
|
+
* failure.
|
|
8632
|
+
*/
|
|
8633
|
+
assertNonInclusion(stateRoot, proof) {
|
|
8634
|
+
if (!this.verifyNonInclusion(stateRoot, proof)) {
|
|
8635
|
+
throw new ProofVerifyError(
|
|
8636
|
+
"non_inclusion_verify_failed",
|
|
8637
|
+
`non-inclusion proof for key ${proof.key} does not verify against the state root`
|
|
8638
|
+
);
|
|
8639
|
+
}
|
|
8640
|
+
}
|
|
8641
|
+
};
|
|
8642
|
+
var proofVerifier = new ProofVerifier();
|
|
8643
|
+
function toHashBytes(value, field2) {
|
|
8644
|
+
if (typeof value === "string") return decodeHash2(value, field2);
|
|
8645
|
+
return expectBytes(value, HASH_BYTE_LENGTH2, field2);
|
|
8646
|
+
}
|
|
8647
|
+
function decodeHex(value, field2) {
|
|
8648
|
+
try {
|
|
8649
|
+
return hexToBytes2(value, field2);
|
|
8650
|
+
} catch (cause) {
|
|
8651
|
+
throw new ProofVerifyError("invalid_hex", `${field2} is not valid hex: ${String(cause)}`);
|
|
8652
|
+
}
|
|
8653
|
+
}
|
|
8654
|
+
function asBinaryProofEnvelope(proof) {
|
|
8655
|
+
if (proof == null || typeof proof !== "object") return null;
|
|
8656
|
+
const obj = proof;
|
|
8657
|
+
if (obj.proofKind !== PROOF_KIND_BINARY) return null;
|
|
8658
|
+
if (typeof obj.key !== "string" || typeof obj.value !== "string" || !Array.isArray(obj.siblings) || obj.siblings.some((s) => typeof s !== "string")) {
|
|
8659
|
+
return null;
|
|
8660
|
+
}
|
|
8661
|
+
return {
|
|
8662
|
+
proofKind: PROOF_KIND_BINARY,
|
|
8663
|
+
siblings: obj.siblings,
|
|
8664
|
+
key: obj.key,
|
|
8665
|
+
value: obj.value
|
|
8666
|
+
};
|
|
8667
|
+
}
|
|
8668
|
+
function hashToHex(hash) {
|
|
8669
|
+
return bytesToHex2(hash);
|
|
8670
|
+
}
|
|
8983
8671
|
|
|
8984
8672
|
// src/native-dev.ts
|
|
8985
8673
|
var NATIVE_DEV_HOST_API_VERSION = "0.1.0";
|
|
@@ -9238,7 +8926,6 @@ function pqm1MnemonicToMlDsa65Backend(mnemonic) {
|
|
|
9238
8926
|
|
|
9239
8927
|
// src/cluster-join.ts
|
|
9240
8928
|
var DEFAULT_CLUSTER_JOIN_EXECUTION_UNIT_LIMIT = REGISTRY_DEFAULT_EXECUTION_UNIT_LIMIT;
|
|
9241
|
-
var DEFAULT_OPERATOR_SEAL_KEY_EXECUTION_UNIT_LIMIT = REGISTRY_DEFAULT_EXECUTION_UNIT_LIMIT;
|
|
9242
8929
|
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
9243
8930
|
var MAX_UINT32 = (1n << 32n) - 1n;
|
|
9244
8931
|
function deriveClusterJoinOperatorId(operatorPubkey) {
|
|
@@ -9346,24 +9033,6 @@ function buildVoteClusterAdmitTxFields(args) {
|
|
|
9346
9033
|
})
|
|
9347
9034
|
};
|
|
9348
9035
|
}
|
|
9349
|
-
function buildPublishOperatorSealKeyTxFields(args) {
|
|
9350
|
-
return {
|
|
9351
|
-
chainId: args.chainId,
|
|
9352
|
-
nonce: args.nonce,
|
|
9353
|
-
maxFeePerGas: parseBigint(args.fee.maxFeePerGas, "maxFeePerGas"),
|
|
9354
|
-
maxPriorityFeePerGas: parseBigint(args.fee.maxPriorityFeePerGas, "maxPriorityFeePerGas"),
|
|
9355
|
-
gasLimit: parseBigint(
|
|
9356
|
-
args.fee.gasLimit ?? DEFAULT_OPERATOR_SEAL_KEY_EXECUTION_UNIT_LIMIT,
|
|
9357
|
-
"gasLimit"
|
|
9358
|
-
),
|
|
9359
|
-
to: nodeRegistryAddressHex(),
|
|
9360
|
-
value: 0n,
|
|
9361
|
-
input: encodePublishOperatorSealKeyCalldata({
|
|
9362
|
-
peerId: normalizeOperatorId(args.peerId),
|
|
9363
|
-
sealEk: normalizeOperatorSealEk(args.sealEk)
|
|
9364
|
-
})
|
|
9365
|
-
};
|
|
9366
|
-
}
|
|
9367
9036
|
async function submitRequestClusterJoin(args) {
|
|
9368
9037
|
const clusterId = parseUint32(args.clusterId, "clusterId");
|
|
9369
9038
|
const operatorPubkey = normalizeConsensusPubkey(args.operatorPubkey, "operatorPubkey");
|
|
@@ -9390,7 +9059,7 @@ async function submitRequestClusterJoin(args) {
|
|
|
9390
9059
|
operatorPubkey,
|
|
9391
9060
|
bondLythoshi: args.bondLythoshi
|
|
9392
9061
|
});
|
|
9393
|
-
return submitClusterJoinTx(args.client, backend, tx, clusterId, operatorIdHex
|
|
9062
|
+
return submitClusterJoinTx(args.client, backend, tx, clusterId, operatorIdHex);
|
|
9394
9063
|
}
|
|
9395
9064
|
async function submitVoteClusterAdmit(args) {
|
|
9396
9065
|
const clusterId = parseUint32(args.clusterId, "clusterId");
|
|
@@ -9417,62 +9086,9 @@ async function submitVoteClusterAdmit(args) {
|
|
|
9417
9086
|
operatorId: operatorIdHex,
|
|
9418
9087
|
voterPubkey: args.voterPubkey
|
|
9419
9088
|
});
|
|
9420
|
-
return submitClusterJoinTx(args.client, backend, tx, clusterId, operatorIdHex
|
|
9421
|
-
}
|
|
9422
|
-
async function submitPublishOperatorSealKey(args) {
|
|
9423
|
-
const operatorIdHex = normalizeOperatorId(args.peerId);
|
|
9424
|
-
const sealEk = normalizeOperatorSealEk(args.sealEk);
|
|
9425
|
-
const backend = pqm1MnemonicToMlDsa65Backend(args.mnemonic);
|
|
9426
|
-
const senderAddress = addressToTypedBech32("user", backend.addressBytes());
|
|
9427
|
-
const [chainId, nonce, quote] = await Promise.all([
|
|
9428
|
-
args.client.ethChainId(),
|
|
9429
|
-
args.client.lythGetTransactionCount(senderAddress),
|
|
9430
|
-
args.client.lythExecutionUnitPrice()
|
|
9431
|
-
]);
|
|
9432
|
-
const tx = buildPublishOperatorSealKeyTxFields({
|
|
9433
|
-
chainId,
|
|
9434
|
-
nonce,
|
|
9435
|
-
fee: resolveClusterJoinExecutionFee(quote, {
|
|
9436
|
-
...args,
|
|
9437
|
-
executionUnitLimit: args.executionUnitLimit ?? DEFAULT_OPERATOR_SEAL_KEY_EXECUTION_UNIT_LIMIT
|
|
9438
|
-
}),
|
|
9439
|
-
peerId: operatorIdHex,
|
|
9440
|
-
sealEk
|
|
9441
|
-
});
|
|
9442
|
-
const plaintext = buildPlaintextSubmission({ backend, tx });
|
|
9443
|
-
const txHash = await submitPlaintextTransaction(
|
|
9444
|
-
args.client,
|
|
9445
|
-
plaintext.signedTxWireHex,
|
|
9446
|
-
plaintext.innerTxHashHex
|
|
9447
|
-
);
|
|
9448
|
-
return {
|
|
9449
|
-
txHash,
|
|
9450
|
-
operatorIdHex,
|
|
9451
|
-
innerSighashHex: plaintext.innerSighashHex,
|
|
9452
|
-
signedTxWireBytes: plaintext.innerWireBytes
|
|
9453
|
-
};
|
|
9089
|
+
return submitClusterJoinTx(args.client, backend, tx, clusterId, operatorIdHex);
|
|
9454
9090
|
}
|
|
9455
|
-
async function submitClusterJoinTx(client, backend, tx, clusterId, operatorIdHex
|
|
9456
|
-
if (options.private !== false) {
|
|
9457
|
-
const encrypted = await buildEncryptedSubmission({
|
|
9458
|
-
client,
|
|
9459
|
-
backend,
|
|
9460
|
-
tx,
|
|
9461
|
-
clusterId: Number(clusterId),
|
|
9462
|
-
clusterSealKeys: options.clusterSealKeys,
|
|
9463
|
-
clusterSealKeysSource: options.clusterSealKeysSource,
|
|
9464
|
-
class: MempoolClass.ContractCall
|
|
9465
|
-
});
|
|
9466
|
-
assertRpcHash(await submitEncryptedEnvelope(client, encrypted.envelopeWireHex));
|
|
9467
|
-
return {
|
|
9468
|
-
txHash: encrypted.innerTxHashHex,
|
|
9469
|
-
clusterId: clusterId.toString(10),
|
|
9470
|
-
operatorIdHex,
|
|
9471
|
-
innerSighashHex: encrypted.innerSighashHex,
|
|
9472
|
-
signedTxWireBytes: encrypted.innerWireBytes,
|
|
9473
|
-
envelopeWireBytes: hexByteLength(encrypted.envelopeWireHex)
|
|
9474
|
-
};
|
|
9475
|
-
}
|
|
9091
|
+
async function submitClusterJoinTx(client, backend, tx, clusterId, operatorIdHex) {
|
|
9476
9092
|
const plaintext = buildPlaintextSubmission({ backend, tx });
|
|
9477
9093
|
const txHash = await submitPlaintextTransaction(
|
|
9478
9094
|
client,
|
|
@@ -9487,16 +9103,6 @@ async function submitClusterJoinTx(client, backend, tx, clusterId, operatorIdHex
|
|
|
9487
9103
|
signedTxWireBytes: plaintext.innerWireBytes
|
|
9488
9104
|
};
|
|
9489
9105
|
}
|
|
9490
|
-
function hexByteLength(value) {
|
|
9491
|
-
const clean = value.startsWith("0x") || value.startsWith("0X") ? value.slice(2) : value;
|
|
9492
|
-
return clean.length / 2;
|
|
9493
|
-
}
|
|
9494
|
-
function assertRpcHash(value) {
|
|
9495
|
-
const bytes = hexToBytes2(value, "lyth_submitEncrypted tx hash");
|
|
9496
|
-
if (bytes.length !== 32) {
|
|
9497
|
-
throw new Error(`lyth_submitEncrypted tx hash must be 32 bytes, got ${bytes.length}`);
|
|
9498
|
-
}
|
|
9499
|
-
}
|
|
9500
9106
|
function adaptNativeClusterJoinRequest(request) {
|
|
9501
9107
|
return {
|
|
9502
9108
|
owner: request.owner ?? ZERO_ADDRESS,
|
|
@@ -9539,10 +9145,6 @@ function normalizeOperatorId(value) {
|
|
|
9539
9145
|
const bytes = typeof value === "string" ? hexToBytes2(value, "operatorId") : value;
|
|
9540
9146
|
return bytesToHex2(expectBytes(bytes, 32, "operatorId"));
|
|
9541
9147
|
}
|
|
9542
|
-
function normalizeOperatorSealEk(value) {
|
|
9543
|
-
const bytes = typeof value === "string" ? hexToBytes2(value, "sealEk") : value;
|
|
9544
|
-
return expectBytes(bytes, NODE_REGISTRY_OPERATOR_SEAL_EK_BYTES, "sealEk").slice();
|
|
9545
|
-
}
|
|
9546
9148
|
function parseUint32(value, label) {
|
|
9547
9149
|
const parsed = parseBigint(value, label);
|
|
9548
9150
|
if (parsed < 0n || parsed > MAX_UINT32) {
|
|
@@ -11051,6 +10653,12 @@ function wordToBigint(word) {
|
|
|
11051
10653
|
}
|
|
11052
10654
|
return out;
|
|
11053
10655
|
}
|
|
10656
|
+
|
|
10657
|
+
// src/crypto/envelope.ts
|
|
10658
|
+
var MempoolClass = {
|
|
10659
|
+
CLOBOp: 3};
|
|
10660
|
+
|
|
10661
|
+
// src/market-actions.ts
|
|
11054
10662
|
var CLOB_MARKET_ID_DOMAIN_TAG = 193;
|
|
11055
10663
|
var NATIVE_MARKET_MODULE_ADDRESS_BYTES = "0x4d41524b45545f4e41544956455f4d4f445f5631";
|
|
11056
10664
|
var NATIVE_MARKET_MODULE_ADDRESS = addressToTypedBech32(
|
|
@@ -12402,7 +12010,6 @@ exports.CLOB_MARKET_ID_DOMAIN_TAG = CLOB_MARKET_ID_DOMAIN_TAG;
|
|
|
12402
12010
|
exports.CLOB_SELECTORS = CLOB_SELECTORS;
|
|
12403
12011
|
exports.CLUSTER_FORMED_EVENT_SIG = CLUSTER_FORMED_EVENT_SIG;
|
|
12404
12012
|
exports.DEFAULT_CLUSTER_JOIN_EXECUTION_UNIT_LIMIT = DEFAULT_CLUSTER_JOIN_EXECUTION_UNIT_LIMIT;
|
|
12405
|
-
exports.DEFAULT_OPERATOR_SEAL_KEY_EXECUTION_UNIT_LIMIT = DEFAULT_OPERATOR_SEAL_KEY_EXECUTION_UNIT_LIMIT;
|
|
12406
12013
|
exports.DELEGATION_REVERT_TAGS = DELEGATION_REVERT_TAGS;
|
|
12407
12014
|
exports.DELEGATION_SELECTORS = DELEGATION_SELECTORS;
|
|
12408
12015
|
exports.DIVERSITY_SCORE_MAX = DIVERSITY_SCORE_MAX;
|
|
@@ -12491,7 +12098,6 @@ exports.NODE_REGISTRY_MERKLE_LEAF_DOMAIN = NODE_REGISTRY_MERKLE_LEAF_DOMAIN;
|
|
|
12491
12098
|
exports.NODE_REGISTRY_MIN_ARCHIVE_LEAF_COUNT = NODE_REGISTRY_MIN_ARCHIVE_LEAF_COUNT;
|
|
12492
12099
|
exports.NODE_REGISTRY_OPERATOR_ALIAS_MAX_BYTES = NODE_REGISTRY_OPERATOR_ALIAS_MAX_BYTES;
|
|
12493
12100
|
exports.NODE_REGISTRY_OPERATOR_MONIKER_MAX_BYTES = NODE_REGISTRY_OPERATOR_MONIKER_MAX_BYTES;
|
|
12494
|
-
exports.NODE_REGISTRY_OPERATOR_SEAL_EK_BYTES = NODE_REGISTRY_OPERATOR_SEAL_EK_BYTES;
|
|
12495
12101
|
exports.NODE_REGISTRY_PENDING_CHANGE_MAX_INTENT_ID = NODE_REGISTRY_PENDING_CHANGE_MAX_INTENT_ID;
|
|
12496
12102
|
exports.NODE_REGISTRY_PUBLIC_SERVICE_MASK = NODE_REGISTRY_PUBLIC_SERVICE_MASK;
|
|
12497
12103
|
exports.NODE_REGISTRY_SELECTORS = NODE_REGISTRY_SELECTORS;
|
|
@@ -12524,6 +12130,7 @@ exports.OperatorTrustError = OperatorTrustError;
|
|
|
12524
12130
|
exports.OracleEventError = OracleEventError;
|
|
12525
12131
|
exports.PENDING_CHANGE_KIND_CODES = PENDING_CHANGE_KIND_CODES;
|
|
12526
12132
|
exports.PRECOMPILE_ADDRESSES = PRECOMPILE_ADDRESSES;
|
|
12133
|
+
exports.PROOF_KIND_BINARY = PROOF_KIND_BINARY;
|
|
12527
12134
|
exports.PROTOCOL_MAX_OPERATOR_FEE_BPS = PROTOCOL_MAX_OPERATOR_FEE_BPS;
|
|
12528
12135
|
exports.PROVER_MARKET_ADDRESS = PROVER_MARKET_ADDRESS;
|
|
12529
12136
|
exports.PROVER_MARKET_BID_DOMAIN = PROVER_MARKET_BID_DOMAIN;
|
|
@@ -12535,6 +12142,8 @@ exports.PROVER_SLASH_REASON_BAD_PROOF = PROVER_SLASH_REASON_BAD_PROOF;
|
|
|
12535
12142
|
exports.PROVER_SLASH_REASON_NON_DELIVERY = PROVER_SLASH_REASON_NON_DELIVERY;
|
|
12536
12143
|
exports.PUBKEY_REGISTRY_ML_DSA_65_PUBLIC_KEY_LEN = PUBKEY_REGISTRY_ML_DSA_65_PUBLIC_KEY_LEN;
|
|
12537
12144
|
exports.PUBKEY_REGISTRY_SELECTORS = PUBKEY_REGISTRY_SELECTORS;
|
|
12145
|
+
exports.ProofVerifier = ProofVerifier;
|
|
12146
|
+
exports.ProofVerifyError = ProofVerifyError;
|
|
12538
12147
|
exports.ProverMarketError = ProverMarketError;
|
|
12539
12148
|
exports.PubkeyRegistryError = PubkeyRegistryError;
|
|
12540
12149
|
exports.QUARANTINED_RPC_CODE = QUARANTINED_RPC_CODE;
|
|
@@ -12575,6 +12184,7 @@ exports.allowRootFor = allowRootFor;
|
|
|
12575
12184
|
exports.apiEndpointFromRpcEndpoint = apiEndpointFromRpcEndpoint;
|
|
12576
12185
|
exports.archiveMerkleInnerHash = archiveMerkleInnerHash;
|
|
12577
12186
|
exports.archiveMerkleLeafHash = archiveMerkleLeafHash;
|
|
12187
|
+
exports.asBinaryProofEnvelope = asBinaryProofEnvelope;
|
|
12578
12188
|
exports.assembleMultisigSigned = assembleMultisigSigned;
|
|
12579
12189
|
exports.assembleMultisigWitness = assembleMultisigWitness;
|
|
12580
12190
|
exports.assertMrvCallNativeSubmissionPlan = assertMrvCallNativeSubmissionPlan;
|
|
@@ -12640,7 +12250,6 @@ exports.buildPlaceLimitOrderViaPlan = buildPlaceLimitOrderViaPlan;
|
|
|
12640
12250
|
exports.buildPlaceSpotLimitOrderPlan = buildPlaceSpotLimitOrderPlan;
|
|
12641
12251
|
exports.buildPlaceSpotMarketOrderExPlan = buildPlaceSpotMarketOrderExPlan;
|
|
12642
12252
|
exports.buildPlaceSpotMarketOrderPlan = buildPlaceSpotMarketOrderPlan;
|
|
12643
|
-
exports.buildPublishOperatorSealKeyTxFields = buildPublishOperatorSealKeyTxFields;
|
|
12644
12253
|
exports.buildRequestClusterJoinTxFields = buildRequestClusterJoinTxFields;
|
|
12645
12254
|
exports.buildVoteClusterAdmitTxFields = buildVoteClusterAdmitTxFields;
|
|
12646
12255
|
exports.categoryRoot = categoryRoot;
|
|
@@ -12673,7 +12282,6 @@ exports.decodeNativeReceiptResponse = decodeNativeReceiptResponse;
|
|
|
12673
12282
|
exports.decodeNoEvmReceiptTranscript = decodeNoEvmReceiptTranscript;
|
|
12674
12283
|
exports.decodeOperatorFeeChargedEvent = decodeOperatorFeeChargedEvent;
|
|
12675
12284
|
exports.decodeOperatorNetworkMetadata = decodeOperatorNetworkMetadata;
|
|
12676
|
-
exports.decodeOperatorSealKey = decodeOperatorSealKey;
|
|
12677
12285
|
exports.decodeOracleEvent = decodeOracleEvent;
|
|
12678
12286
|
exports.decodePendingCharter = decodePendingCharter;
|
|
12679
12287
|
exports.decodeProbeAuthority = decodeProbeAuthority;
|
|
@@ -12720,7 +12328,6 @@ exports.encodeExpireClusterJoinCalldata = encodeExpireClusterJoinCalldata;
|
|
|
12720
12328
|
exports.encodeFormClusterCalldata = encodeFormClusterCalldata;
|
|
12721
12329
|
exports.encodeFormClusterV2Calldata = encodeFormClusterV2Calldata;
|
|
12722
12330
|
exports.encodeGetClusterJoinRequestCalldata = encodeGetClusterJoinRequestCalldata;
|
|
12723
|
-
exports.encodeGetOperatorSealKeyCalldata = encodeGetOperatorSealKeyCalldata;
|
|
12724
12331
|
exports.encodeGetPendingCharterCalldata = encodeGetPendingCharterCalldata;
|
|
12725
12332
|
exports.encodeGetProbeAuthorityCalldata = encodeGetProbeAuthorityCalldata;
|
|
12726
12333
|
exports.encodeHasPubkeyCalldata = encodeHasPubkeyCalldata;
|
|
@@ -12780,7 +12387,6 @@ exports.encodePlaceLimitOrderCalldata = encodePlaceLimitOrderCalldata;
|
|
|
12780
12387
|
exports.encodePlaceLimitOrderViaCalldata = encodePlaceLimitOrderViaCalldata;
|
|
12781
12388
|
exports.encodePlaceMarketOrderCalldata = encodePlaceMarketOrderCalldata;
|
|
12782
12389
|
exports.encodePlaceMarketOrderExCalldata = encodePlaceMarketOrderExCalldata;
|
|
12783
|
-
exports.encodePublishOperatorSealKeyCalldata = encodePublishOperatorSealKeyCalldata;
|
|
12784
12390
|
exports.encodeRecoverOperatorNodeCalldata = encodeRecoverOperatorNodeCalldata;
|
|
12785
12391
|
exports.encodeRedelegateCalldata = encodeRedelegateCalldata;
|
|
12786
12392
|
exports.encodeRegisterPubkeyCalldata = encodeRegisterPubkeyCalldata;
|
|
@@ -12831,6 +12437,7 @@ exports.getChainInfo = getChainInfo;
|
|
|
12831
12437
|
exports.getNoEvmReceiptTrustPolicy = getNoEvmReceiptTrustPolicy;
|
|
12832
12438
|
exports.getP2pSeeds = getP2pSeeds;
|
|
12833
12439
|
exports.getRpcEndpoints = getRpcEndpoints;
|
|
12440
|
+
exports.hashToHex = hashToHex;
|
|
12834
12441
|
exports.hexToAddressBytes = hexToAddressBytes;
|
|
12835
12442
|
exports.isBridgeAdminLockedRevert = isBridgeAdminLockedRevert;
|
|
12836
12443
|
exports.isBridgeCooldownZeroRevert = isBridgeCooldownZeroRevert;
|
|
@@ -12886,6 +12493,7 @@ exports.parseQuantityBig = parseQuantityBig;
|
|
|
12886
12493
|
exports.preflightClusterJoinRequest = preflightClusterJoinRequest;
|
|
12887
12494
|
exports.previewRequestClusterJoin = previewRequestClusterJoin;
|
|
12888
12495
|
exports.previewVoteClusterAdmit = previewVoteClusterAdmit;
|
|
12496
|
+
exports.proofVerifier = proofVerifier;
|
|
12889
12497
|
exports.protocolNonceForEpoch = protocolNonceForEpoch;
|
|
12890
12498
|
exports.proverMarketStateFromByte = proverMarketStateFromByte;
|
|
12891
12499
|
exports.pubkeyRegistryAddressHex = pubkeyRegistryAddressHex;
|
|
@@ -12919,7 +12527,6 @@ exports.spendingPolicyAddressHex = spendingPolicyAddressHex;
|
|
|
12919
12527
|
exports.submitMrvCallNativeTx = submitMrvCallNativeTx;
|
|
12920
12528
|
exports.submitMrvDeployNativeTx = submitMrvDeployNativeTx;
|
|
12921
12529
|
exports.submitMrvDeployPayloadNativeTx = submitMrvDeployPayloadNativeTx;
|
|
12922
|
-
exports.submitPublishOperatorSealKey = submitPublishOperatorSealKey;
|
|
12923
12530
|
exports.submitRequestClusterJoin = submitRequestClusterJoin;
|
|
12924
12531
|
exports.submitSighash = submitSighash;
|
|
12925
12532
|
exports.submitVoteClusterAdmit = submitVoteClusterAdmit;
|