@orbinum/sdk 0.14.1 → 0.16.0
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/index.d.mts +93 -4
- package/dist/index.d.ts +93 -4
- package/dist/index.js +125 -35
- package/dist/index.mjs +129 -42
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
|
@@ -664,6 +664,13 @@ type NoteInput = {
|
|
|
664
664
|
counterpartyPk?: bigint;
|
|
665
665
|
/** Circuit version to stamp on the note. Defaults to `CURRENT_CIRCUIT_VERSION`. */
|
|
666
666
|
circuitVersion?: number;
|
|
667
|
+
/**
|
|
668
|
+
* 32-byte ephemeral secret for the memo ECDH. Self-notes pass a
|
|
669
|
+
* deterministic one (deriveSelfEphSk) so a cold restore recognizes them by
|
|
670
|
+
* ephPk equality with no trial ECDH. Ignored on the stealth path (it
|
|
671
|
+
* generates its own coordinated ephSk). Default: random.
|
|
672
|
+
*/
|
|
673
|
+
ephSkOverride?: Uint8Array;
|
|
667
674
|
};
|
|
668
675
|
/**
|
|
669
676
|
* Circuit version notes are created under today. A note carries its version
|
|
@@ -1920,11 +1927,17 @@ declare class NoteBuilder {
|
|
|
1920
1927
|
/**
|
|
1921
1928
|
* EncryptedMemo — TypeScript implementation of Orbinum's encrypted note memo.
|
|
1922
1929
|
*
|
|
1923
|
-
*
|
|
1930
|
+
* Native TypeScript implementation — no WASM required. This file IS the
|
|
1931
|
+
* normative memo format: the chain treats memos as opaque 180-byte blobs.
|
|
1924
1932
|
*
|
|
1925
1933
|
* Layout (180 bytes, ECDH):
|
|
1926
1934
|
* nonce(12) || ciphertext+MAC(136) || ephPk_packed(32) = 180
|
|
1927
1935
|
*
|
|
1936
|
+
* View tag (memos built by SDK ≥ 0.15): nonce[0] = deriveViewTag(sharedSecret)
|
|
1937
|
+
* — see memo.ts. Layout and size are unchanged; legacy memos carry a random
|
|
1938
|
+
* byte there instead, so the filter is only sound at/after the wallet's
|
|
1939
|
+
* tagActivationLeaf.
|
|
1940
|
+
*
|
|
1928
1941
|
* Plaintext layout (120 bytes):
|
|
1929
1942
|
* value_lo(8 LE) || value_hi(8 LE) || owner_pk(32) || blinding(32) || asset_id(4 LE) || counterparty_pk(32) || circuit_version(4 LE)
|
|
1930
1943
|
*
|
|
@@ -2007,10 +2020,67 @@ declare const EncryptedMemo: {
|
|
|
2007
2020
|
* @param viewingSecretKey 32-byte HKDF viewing secret key from deriveViewingSecretKey().
|
|
2008
2021
|
*/
|
|
2009
2022
|
extractSharedSecret(memoBytes: Uint8Array, viewingSecretKey: Uint8Array): Uint8Array | null;
|
|
2023
|
+
/**
|
|
2024
|
+
* Cheap view-tag check: does memo nonce[0] match the tag derived from
|
|
2025
|
+
* `sharedSecret`? One SHA256 + one byte compare — no AEAD work.
|
|
2026
|
+
*
|
|
2027
|
+
* Only meaningful for memos built with view tags (commitments at/after
|
|
2028
|
+
* the wallet's tagActivationLeaf): a legacy memo carries a random byte
|
|
2029
|
+
* there and would false-negative 255/256 of the time.
|
|
2030
|
+
*/
|
|
2031
|
+
checkViewTag(memoBytes: Uint8Array, sharedSecret: Uint8Array): boolean;
|
|
2032
|
+
/**
|
|
2033
|
+
* Decrypt with an already-computed shared secret (from
|
|
2034
|
+
* extractSharedSecret), skipping the ECDH. Pair with checkViewTag for the
|
|
2035
|
+
* fast scan path: ECDH once → tag check → decrypt only on match.
|
|
2036
|
+
*/
|
|
2037
|
+
decryptWithSharedSecret(memoBytes: Uint8Array, commitment: Uint8Array, sharedSecret: Uint8Array): DecryptedMemo | null;
|
|
2010
2038
|
/** @internal */
|
|
2011
2039
|
_decrypt(memoBytes: Uint8Array, commitment: Uint8Array, viewingSecretKey: Uint8Array): DecryptedMemo | null;
|
|
2012
2040
|
};
|
|
2013
2041
|
|
|
2042
|
+
/**
|
|
2043
|
+
* Derive the 1-byte view tag (Monero-style fast-scan filter) from the ECDH
|
|
2044
|
+
* shared secret:
|
|
2045
|
+
* view_tag = SHA256("orbinum-view-tag-v1" || sharedSecret)[0]
|
|
2046
|
+
*
|
|
2047
|
+
* The sender embeds it as the memo's first nonce byte (nonce[0]); a scanner
|
|
2048
|
+
* that has computed the shared secret compares one byte and skips the AEAD
|
|
2049
|
+
* decrypt on mismatch — 255/256 of foreign notes. Safe to publish: without
|
|
2050
|
+
* the viewing key the shared secret is unknowable, so the byte reads as
|
|
2051
|
+
* uniform noise to any observer.
|
|
2052
|
+
*
|
|
2053
|
+
* Nonce safety: the encryption key is unique per note (see
|
|
2054
|
+
* deriveEncryptionKey), so each key encrypts exactly one message and the
|
|
2055
|
+
* remaining 11 random nonce bytes are more than enough.
|
|
2056
|
+
*/
|
|
2057
|
+
declare function deriveViewTag(sharedSecret: Uint8Array): number;
|
|
2058
|
+
|
|
2059
|
+
/**
|
|
2060
|
+
* Derive the deterministic 32-byte ephemeral secret for self-note `index`.
|
|
2061
|
+
* Feed it to EncryptedMemo.encrypt / NoteBuilder.build as `ephSkOverride`.
|
|
2062
|
+
*/
|
|
2063
|
+
declare function deriveSelfEphSk(spendingKey: bigint, index: number): Uint8Array;
|
|
2064
|
+
/** One precomputed self-note window entry. */
|
|
2065
|
+
interface SelfEphWindowEntry {
|
|
2066
|
+
index: number;
|
|
2067
|
+
/** 0x-prefixed LE-packed ephPk — byte-identical to the memo's last 32 bytes. */
|
|
2068
|
+
ephPkHex: string;
|
|
2069
|
+
/** ECDH shared secret vs the wallet's own ivk — feeds decryptWithSharedSecret. */
|
|
2070
|
+
sharedSecret: Uint8Array;
|
|
2071
|
+
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Precompute the self-note discovery window [from, from+count): for each
|
|
2074
|
+
* index, the ephPk the wallet would have published and the shared secret
|
|
2075
|
+
* needed to decrypt the memo. One EC pass up front; scanning then matches
|
|
2076
|
+
* hints by ephPk hex equality with no per-hint EC work.
|
|
2077
|
+
*
|
|
2078
|
+
* @param spendingKey Wallet spending key (the seed of the derivation).
|
|
2079
|
+
* @param ivkPacked The wallet's OWN 32-byte LE packed viewing public key —
|
|
2080
|
+
* self memos are encrypted to it.
|
|
2081
|
+
*/
|
|
2082
|
+
declare function selfEphWindow(spendingKey: bigint, ivkPacked: Uint8Array, from: number, count: number): SelfEphWindowEntry[];
|
|
2083
|
+
|
|
2014
2084
|
/**
|
|
2015
2085
|
* NoteDecryptor
|
|
2016
2086
|
*
|
|
@@ -2034,6 +2104,24 @@ declare const EncryptedMemo: {
|
|
|
2034
2104
|
* deriveSpendingKeyFromSignature.
|
|
2035
2105
|
*/
|
|
2036
2106
|
declare function computeNullifier(commitment: bigint, spendingKey: bigint): bigint;
|
|
2107
|
+
interface TryDecryptOptions {
|
|
2108
|
+
/**
|
|
2109
|
+
* View-tag fast path: compute the ECDH shared secret once, compare the
|
|
2110
|
+
* 1-byte tag in memo nonce[0], and skip the AEAD decrypt on mismatch
|
|
2111
|
+
* (255/256 of foreign notes; `reason: 'view_tag_mismatch'`).
|
|
2112
|
+
*
|
|
2113
|
+
* Only enable for commitments at/after the wallet's tagActivationLeaf —
|
|
2114
|
+
* legacy memos carry a random byte there and would be silently dropped.
|
|
2115
|
+
*/
|
|
2116
|
+
viewTag?: boolean;
|
|
2117
|
+
/**
|
|
2118
|
+
* Precomputed ECDH shared secret (self-note discovery: the caller matched
|
|
2119
|
+
* the hint's ephPk against a selfEphWindow and already holds the secret).
|
|
2120
|
+
* Skips the ECDH and the view-tag gate entirely; the decrypt + commitment
|
|
2121
|
+
* check still validate the note as usual.
|
|
2122
|
+
*/
|
|
2123
|
+
sharedSecret?: Uint8Array;
|
|
2124
|
+
}
|
|
2037
2125
|
/**
|
|
2038
2126
|
* Attempt to decrypt an on-chain commitment using the recipient's viewing secret key.
|
|
2039
2127
|
*
|
|
@@ -2047,13 +2135,14 @@ declare function computeNullifier(commitment: bigint, spendingKey: bigint): bigi
|
|
|
2047
2135
|
* @param spendingKey Spending key bigint (for nullifier computation).
|
|
2048
2136
|
* @param ownOwnerPk The viewer's global BabyJubJub Ax (ownerPk). Required for stealth detection.
|
|
2049
2137
|
* Pass 0n to disable stealth detection (legacy/own-note-only scanning).
|
|
2138
|
+
* @param opts See TryDecryptOptions (view-tag fast path).
|
|
2050
2139
|
*/
|
|
2051
|
-
declare function tryDecryptNote(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint): ZkNote | null;
|
|
2140
|
+
declare function tryDecryptNote(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint, opts?: TryDecryptOptions): ZkNote | null;
|
|
2052
2141
|
/**
|
|
2053
2142
|
* Like tryDecryptNote but also returns a human-readable reason for failure.
|
|
2054
2143
|
* Useful for debugging scan issues (wrong key, corrupted memo, commitment mismatch).
|
|
2055
2144
|
*/
|
|
2056
|
-
declare function tryDecryptNoteVerbose(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint): {
|
|
2145
|
+
declare function tryDecryptNoteVerbose(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint, opts?: TryDecryptOptions): {
|
|
2057
2146
|
note: ZkNote | null;
|
|
2058
2147
|
reason?: string;
|
|
2059
2148
|
};
|
|
@@ -4172,4 +4261,4 @@ interface ExtrinsicFailedData {
|
|
|
4172
4261
|
dispatch_info: DispatchInfo;
|
|
4173
4262
|
}
|
|
4174
4263
|
|
|
4175
|
-
export { type AccountListing, type AccountMappedData, type AccountMappedEvent, type AccountMappingCall, type AccountMappingEvent, AccountMappingModule, AccountMappingPrecompile, type AccountMetadata, type AccountUnmappedEvent, type ActiveVersionSetEvent, type AddChainLinkArgs, type AddChainLinkParams, type AddSupportedChainArgs, type AliasFullIdentity, type AliasInfo, type AliasListedForSaleEvent, type AliasOnSaleData, type AliasRegisteredData, type AliasRegisteredEvent, type AliasReleasedEvent, type AliasSaleCancelledEvent, type AliasSoldData, type AliasSoldEvent, type AliasTransferredData, type AliasTransferredEvent, type AssetRegisteredEvent, type AssetUnverifiedEvent, type AssetVerifiedEvent, BABYJUB_SUBORDER, BN254_R, type BatchRegisterVerificationKeysArgs, type BatchVerificationKeysRegisteredEvent, type BlockInfo, type BuyAliasArgs, type Bytes32, CURRENT_CIRCUIT_VERSION, type ChainInfo, type ChainLink, type ChainLinkAddedEvent, type ChainLinkRemovedEvent, CircuitId, CircuitId as CircuitIdType, CircuitVersionResolver, type ClaimShieldedFeesParams, type ClientProviderConfig, type CommitmentsInsertedEvent, type CommitmentsInsertedEventData, type ConnectionStatus, CryptoPrecompiles, type DecodedAddChainLinkArgs, type DecodedBatchArgs, type DecodedDispatchAsPrivateLinkArgs, type DecodedEthereumTransactArgs, type DecodedEvmCallArgs, type DecodedPrecompile, type DecodedPrivateTransferArgs, type DecodedPutAliasForSaleArgs, type DecodedRegisterAliasArgs, type DecodedRemarkArgs, type DecodedRevealPrivateLinkArgs, type DecodedSetAccountMetadataArgs, type DecodedShieldArgs, type DecodedShieldBatchArgs, type DecodedShieldBatchOperation, type DecodedSudoArgs, type DecodedTransferAllArgs, type DecodedTransferArgs, type DecodedTransferKeepAliveArgs, type DecodedUnshieldArgs, type DecryptedMemo, type DispatchAsLinkedAccountArgs, type DispatchAsLinkedParams, type DispatchAsPrivateLinkArgs, type DispatchError, type DispatchInfo, type DynamicBuilder, ENCRYPTED_MEMO_SIZE, EncryptedMemo, type EncryptedNoteRecord, type EndowedEventData, type EthereumExecutedData, type EventData, type EventPhase, type EventRecord, type EvmAddressInfo, type EvmBlock, EvmClient, type EvmExecutedData, type EvmExitReason, EvmExplorer, type EvmLog, type EvmSigner, type EvmTransaction, type EvmTxRequest, type EvmTxSummary, type ExtrinsicDecoder, type ExtrinsicFailedData, type ExtrinsicSuccessData, type FeeClaimProofInputs, type FormatOptions, KNOWN_PRECOMPILES, type KnownPrecompileInfo, type ListingInfo, type MerkleRootUpdatedData, type MerkleRootUpdatedEvent, type MerkleTreeInfo, type MetadataUpdatedEvent, NoteBuilder, type NoteDisclosure, type NoteInput, type NoteStatusUpdate, type NullifiersSpentEvent, type NullifiersSpentEventData, OrbinumClient, type OrbinumClientConfig, OrbinumClientProvider, PRECOMPILE_ADDR, PrivacyKeyManager, type PrivacyMerkleProof, PrivacyModule, type PrivateChainLinkAddedEvent, type PrivateChainLinkRemovedEvent, type PrivateChainLinkRevealedEvent, type PrivateLink, type PrivateLinkDispatchExecutedEvent, type PrivateTransferArgs, type PrivateTransferInput, type PrivateTransferOutput, type PrivateTransferParams, type PrivateTransferProofInputs, type ProofVerificationFailedEvent, type ProofVerifiedEvent, type ProxyCallExecutedEvent, type PutAliasOnSaleArgs, type PutOnSaleParams, type RawBlock, type RawBlockHeader, type RawTransferInput, type RawTransferOutput, type RegisterAliasArgs, type RegisterAssetArgs, type RegisterPrivateLinkArgs, type RegisterVerificationKeyArgs, type RelayerInfo, RelayerStatusModule, type RemoveChainLinkArgs, type RemovePrivateLinkArgs, type RemoveSupportedChainArgs, type RemoveVerificationKeyArgs, type ReservedEventData, type ResolvedAlias, type ResolvedSpendVersion, type RevealPrivateLinkArgs, type RpcV2MerkleProof, type RpcV2NullifierStatus, type RpcV2PoolAssetBalance, type RpcV2PoolStats, SLIP0044_NAMESPACE, type ScanCommitment, type SetAccountMetadataArgs, type SetActiveVersionArgs, type SetMetadataParams, type ShieldArgs, type ShieldBatchArgs, type ShieldBatchItem, type ShieldBatchParams, type ShieldOperation, type ShieldParams, type ShieldedEvent, type ShieldedEventData, type ShieldedPoolCall, type ShieldedPoolEvent, ShieldedPoolModule, ShieldedPoolPrecompile, SignatureScheme, type StatusChangeEvent, type StatusListener, SubstrateClient, type SupportedChain, type SupportedChainAddedEvent, type SupportedChainRemovedEvent, type SystemHealth, type TokenInfo, type TokenTransfer, type TransferAliasArgs, type TransferEventData, type TransferInputNote, type TransferOutputNote, type TxResult, type UnsafeTxOptions, type UnshieldArgs, type UnshieldParams, type UnshieldProofInputs, type UnshieldedEvent, type UnshieldedEventData, type UnverifyAssetArgs, VaultLockedError, type VerificationKeyRegisteredEvent, type VerificationKeyRemovedEvent, type VerifyAssetArgs, type VerifyProofArgs, type VkEntry, type ZkNote, type ZkVerifierCall, type ZkVerifierCircuitVersionInfo, type ZkVerifierEvent, type ZkVerifierHistoricalVersion, ZkVerifierModule, type ZkVerifierVersionStats, type ZkVerifierVkHash, accountIdHexToSs58, addressToAccountIdHex, applyNoteStatus, bigintTo32Be, bigintTo32Le, bigintTo32LeArr, blindTag, buildDummyTransferInput, bytesToBigintLE, computeNullifier, computePathIndices, createNoteDisclosureKey, decodeNoteDisclosureKey, decodePrecompileCalldata, decryptJson, decryptNoteRecord, deriveMasterKeyBytes, deriveOwnerPk, deriveSpendingKeyFromSignature, deriveSpendingKeyMessage, deriveStealthOwnerPk, deriveStealthSk, deriveVaultBlindKey, deriveVaultKey, deriveViewingPublicKey, deriveViewingSecretKey, encryptJson, encryptNote, ensureHexPrefix, evmAddressToAccountId, evmToImplicitSubstrate, evmToMappedAccountHex, evmToSubstrate, formatBalance, formatORB, fromBase64, fromHex, generateFeeClaimProof, generateTransferProof, generateUnshieldProof, getPrecompileLabel, hexToBigint, hexToNumber, implicitSubstrateToEvm, isEvmAddress, isImplicitEvmAccount, isSs58, isSubstrateAddress, isUnifiedAddress, leHexToBigint, mapExtrinsicArgs, mapZkEventData, normalizeEvmAddress, noteBlindTag, randomBlinding, recoverOwnerPkPoint, selectNotes, shortHash, substrateSs58ToAccountIdHex, substrateToEvm, toBase64, toHex, toTxResult, truncateMiddle, tryDecryptNote, tryDecryptNoteVerbose, vaultReplacer, vaultReviver };
|
|
4264
|
+
export { type AccountListing, type AccountMappedData, type AccountMappedEvent, type AccountMappingCall, type AccountMappingEvent, AccountMappingModule, AccountMappingPrecompile, type AccountMetadata, type AccountUnmappedEvent, type ActiveVersionSetEvent, type AddChainLinkArgs, type AddChainLinkParams, type AddSupportedChainArgs, type AliasFullIdentity, type AliasInfo, type AliasListedForSaleEvent, type AliasOnSaleData, type AliasRegisteredData, type AliasRegisteredEvent, type AliasReleasedEvent, type AliasSaleCancelledEvent, type AliasSoldData, type AliasSoldEvent, type AliasTransferredData, type AliasTransferredEvent, type AssetRegisteredEvent, type AssetUnverifiedEvent, type AssetVerifiedEvent, BABYJUB_SUBORDER, BN254_R, type BatchRegisterVerificationKeysArgs, type BatchVerificationKeysRegisteredEvent, type BlockInfo, type BuyAliasArgs, type Bytes32, CURRENT_CIRCUIT_VERSION, type ChainInfo, type ChainLink, type ChainLinkAddedEvent, type ChainLinkRemovedEvent, CircuitId, CircuitId as CircuitIdType, CircuitVersionResolver, type ClaimShieldedFeesParams, type ClientProviderConfig, type CommitmentsInsertedEvent, type CommitmentsInsertedEventData, type ConnectionStatus, CryptoPrecompiles, type DecodedAddChainLinkArgs, type DecodedBatchArgs, type DecodedDispatchAsPrivateLinkArgs, type DecodedEthereumTransactArgs, type DecodedEvmCallArgs, type DecodedPrecompile, type DecodedPrivateTransferArgs, type DecodedPutAliasForSaleArgs, type DecodedRegisterAliasArgs, type DecodedRemarkArgs, type DecodedRevealPrivateLinkArgs, type DecodedSetAccountMetadataArgs, type DecodedShieldArgs, type DecodedShieldBatchArgs, type DecodedShieldBatchOperation, type DecodedSudoArgs, type DecodedTransferAllArgs, type DecodedTransferArgs, type DecodedTransferKeepAliveArgs, type DecodedUnshieldArgs, type DecryptedMemo, type DispatchAsLinkedAccountArgs, type DispatchAsLinkedParams, type DispatchAsPrivateLinkArgs, type DispatchError, type DispatchInfo, type DynamicBuilder, ENCRYPTED_MEMO_SIZE, EncryptedMemo, type EncryptedNoteRecord, type EndowedEventData, type EthereumExecutedData, type EventData, type EventPhase, type EventRecord, type EvmAddressInfo, type EvmBlock, EvmClient, type EvmExecutedData, type EvmExitReason, EvmExplorer, type EvmLog, type EvmSigner, type EvmTransaction, type EvmTxRequest, type EvmTxSummary, type ExtrinsicDecoder, type ExtrinsicFailedData, type ExtrinsicSuccessData, type FeeClaimProofInputs, type FormatOptions, KNOWN_PRECOMPILES, type KnownPrecompileInfo, type ListingInfo, type MerkleRootUpdatedData, type MerkleRootUpdatedEvent, type MerkleTreeInfo, type MetadataUpdatedEvent, NoteBuilder, type NoteDisclosure, type NoteInput, type NoteStatusUpdate, type NullifiersSpentEvent, type NullifiersSpentEventData, OrbinumClient, type OrbinumClientConfig, OrbinumClientProvider, PRECOMPILE_ADDR, PrivacyKeyManager, type PrivacyMerkleProof, PrivacyModule, type PrivateChainLinkAddedEvent, type PrivateChainLinkRemovedEvent, type PrivateChainLinkRevealedEvent, type PrivateLink, type PrivateLinkDispatchExecutedEvent, type PrivateTransferArgs, type PrivateTransferInput, type PrivateTransferOutput, type PrivateTransferParams, type PrivateTransferProofInputs, type ProofVerificationFailedEvent, type ProofVerifiedEvent, type ProxyCallExecutedEvent, type PutAliasOnSaleArgs, type PutOnSaleParams, type RawBlock, type RawBlockHeader, type RawTransferInput, type RawTransferOutput, type RegisterAliasArgs, type RegisterAssetArgs, type RegisterPrivateLinkArgs, type RegisterVerificationKeyArgs, type RelayerInfo, RelayerStatusModule, type RemoveChainLinkArgs, type RemovePrivateLinkArgs, type RemoveSupportedChainArgs, type RemoveVerificationKeyArgs, type ReservedEventData, type ResolvedAlias, type ResolvedSpendVersion, type RevealPrivateLinkArgs, type RpcV2MerkleProof, type RpcV2NullifierStatus, type RpcV2PoolAssetBalance, type RpcV2PoolStats, SLIP0044_NAMESPACE, type ScanCommitment, type SelfEphWindowEntry, type SetAccountMetadataArgs, type SetActiveVersionArgs, type SetMetadataParams, type ShieldArgs, type ShieldBatchArgs, type ShieldBatchItem, type ShieldBatchParams, type ShieldOperation, type ShieldParams, type ShieldedEvent, type ShieldedEventData, type ShieldedPoolCall, type ShieldedPoolEvent, ShieldedPoolModule, ShieldedPoolPrecompile, SignatureScheme, type StatusChangeEvent, type StatusListener, SubstrateClient, type SupportedChain, type SupportedChainAddedEvent, type SupportedChainRemovedEvent, type SystemHealth, type TokenInfo, type TokenTransfer, type TransferAliasArgs, type TransferEventData, type TransferInputNote, type TransferOutputNote, type TryDecryptOptions, type TxResult, type UnsafeTxOptions, type UnshieldArgs, type UnshieldParams, type UnshieldProofInputs, type UnshieldedEvent, type UnshieldedEventData, type UnverifyAssetArgs, VaultLockedError, type VerificationKeyRegisteredEvent, type VerificationKeyRemovedEvent, type VerifyAssetArgs, type VerifyProofArgs, type VkEntry, type ZkNote, type ZkVerifierCall, type ZkVerifierCircuitVersionInfo, type ZkVerifierEvent, type ZkVerifierHistoricalVersion, ZkVerifierModule, type ZkVerifierVersionStats, type ZkVerifierVkHash, accountIdHexToSs58, addressToAccountIdHex, applyNoteStatus, bigintTo32Be, bigintTo32Le, bigintTo32LeArr, blindTag, buildDummyTransferInput, bytesToBigintLE, computeNullifier, computePathIndices, createNoteDisclosureKey, decodeNoteDisclosureKey, decodePrecompileCalldata, decryptJson, decryptNoteRecord, deriveMasterKeyBytes, deriveOwnerPk, deriveSelfEphSk, deriveSpendingKeyFromSignature, deriveSpendingKeyMessage, deriveStealthOwnerPk, deriveStealthSk, deriveVaultBlindKey, deriveVaultKey, deriveViewTag, deriveViewingPublicKey, deriveViewingSecretKey, encryptJson, encryptNote, ensureHexPrefix, evmAddressToAccountId, evmToImplicitSubstrate, evmToMappedAccountHex, evmToSubstrate, formatBalance, formatORB, fromBase64, fromHex, generateFeeClaimProof, generateTransferProof, generateUnshieldProof, getPrecompileLabel, hexToBigint, hexToNumber, implicitSubstrateToEvm, isEvmAddress, isImplicitEvmAccount, isSs58, isSubstrateAddress, isUnifiedAddress, leHexToBigint, mapExtrinsicArgs, mapZkEventData, normalizeEvmAddress, noteBlindTag, randomBlinding, recoverOwnerPkPoint, selectNotes, selfEphWindow, shortHash, substrateSs58ToAccountIdHex, substrateToEvm, toBase64, toHex, toTxResult, truncateMiddle, tryDecryptNote, tryDecryptNoteVerbose, vaultReplacer, vaultReviver };
|
package/dist/index.d.ts
CHANGED
|
@@ -664,6 +664,13 @@ type NoteInput = {
|
|
|
664
664
|
counterpartyPk?: bigint;
|
|
665
665
|
/** Circuit version to stamp on the note. Defaults to `CURRENT_CIRCUIT_VERSION`. */
|
|
666
666
|
circuitVersion?: number;
|
|
667
|
+
/**
|
|
668
|
+
* 32-byte ephemeral secret for the memo ECDH. Self-notes pass a
|
|
669
|
+
* deterministic one (deriveSelfEphSk) so a cold restore recognizes them by
|
|
670
|
+
* ephPk equality with no trial ECDH. Ignored on the stealth path (it
|
|
671
|
+
* generates its own coordinated ephSk). Default: random.
|
|
672
|
+
*/
|
|
673
|
+
ephSkOverride?: Uint8Array;
|
|
667
674
|
};
|
|
668
675
|
/**
|
|
669
676
|
* Circuit version notes are created under today. A note carries its version
|
|
@@ -1920,11 +1927,17 @@ declare class NoteBuilder {
|
|
|
1920
1927
|
/**
|
|
1921
1928
|
* EncryptedMemo — TypeScript implementation of Orbinum's encrypted note memo.
|
|
1922
1929
|
*
|
|
1923
|
-
*
|
|
1930
|
+
* Native TypeScript implementation — no WASM required. This file IS the
|
|
1931
|
+
* normative memo format: the chain treats memos as opaque 180-byte blobs.
|
|
1924
1932
|
*
|
|
1925
1933
|
* Layout (180 bytes, ECDH):
|
|
1926
1934
|
* nonce(12) || ciphertext+MAC(136) || ephPk_packed(32) = 180
|
|
1927
1935
|
*
|
|
1936
|
+
* View tag (memos built by SDK ≥ 0.15): nonce[0] = deriveViewTag(sharedSecret)
|
|
1937
|
+
* — see memo.ts. Layout and size are unchanged; legacy memos carry a random
|
|
1938
|
+
* byte there instead, so the filter is only sound at/after the wallet's
|
|
1939
|
+
* tagActivationLeaf.
|
|
1940
|
+
*
|
|
1928
1941
|
* Plaintext layout (120 bytes):
|
|
1929
1942
|
* value_lo(8 LE) || value_hi(8 LE) || owner_pk(32) || blinding(32) || asset_id(4 LE) || counterparty_pk(32) || circuit_version(4 LE)
|
|
1930
1943
|
*
|
|
@@ -2007,10 +2020,67 @@ declare const EncryptedMemo: {
|
|
|
2007
2020
|
* @param viewingSecretKey 32-byte HKDF viewing secret key from deriveViewingSecretKey().
|
|
2008
2021
|
*/
|
|
2009
2022
|
extractSharedSecret(memoBytes: Uint8Array, viewingSecretKey: Uint8Array): Uint8Array | null;
|
|
2023
|
+
/**
|
|
2024
|
+
* Cheap view-tag check: does memo nonce[0] match the tag derived from
|
|
2025
|
+
* `sharedSecret`? One SHA256 + one byte compare — no AEAD work.
|
|
2026
|
+
*
|
|
2027
|
+
* Only meaningful for memos built with view tags (commitments at/after
|
|
2028
|
+
* the wallet's tagActivationLeaf): a legacy memo carries a random byte
|
|
2029
|
+
* there and would false-negative 255/256 of the time.
|
|
2030
|
+
*/
|
|
2031
|
+
checkViewTag(memoBytes: Uint8Array, sharedSecret: Uint8Array): boolean;
|
|
2032
|
+
/**
|
|
2033
|
+
* Decrypt with an already-computed shared secret (from
|
|
2034
|
+
* extractSharedSecret), skipping the ECDH. Pair with checkViewTag for the
|
|
2035
|
+
* fast scan path: ECDH once → tag check → decrypt only on match.
|
|
2036
|
+
*/
|
|
2037
|
+
decryptWithSharedSecret(memoBytes: Uint8Array, commitment: Uint8Array, sharedSecret: Uint8Array): DecryptedMemo | null;
|
|
2010
2038
|
/** @internal */
|
|
2011
2039
|
_decrypt(memoBytes: Uint8Array, commitment: Uint8Array, viewingSecretKey: Uint8Array): DecryptedMemo | null;
|
|
2012
2040
|
};
|
|
2013
2041
|
|
|
2042
|
+
/**
|
|
2043
|
+
* Derive the 1-byte view tag (Monero-style fast-scan filter) from the ECDH
|
|
2044
|
+
* shared secret:
|
|
2045
|
+
* view_tag = SHA256("orbinum-view-tag-v1" || sharedSecret)[0]
|
|
2046
|
+
*
|
|
2047
|
+
* The sender embeds it as the memo's first nonce byte (nonce[0]); a scanner
|
|
2048
|
+
* that has computed the shared secret compares one byte and skips the AEAD
|
|
2049
|
+
* decrypt on mismatch — 255/256 of foreign notes. Safe to publish: without
|
|
2050
|
+
* the viewing key the shared secret is unknowable, so the byte reads as
|
|
2051
|
+
* uniform noise to any observer.
|
|
2052
|
+
*
|
|
2053
|
+
* Nonce safety: the encryption key is unique per note (see
|
|
2054
|
+
* deriveEncryptionKey), so each key encrypts exactly one message and the
|
|
2055
|
+
* remaining 11 random nonce bytes are more than enough.
|
|
2056
|
+
*/
|
|
2057
|
+
declare function deriveViewTag(sharedSecret: Uint8Array): number;
|
|
2058
|
+
|
|
2059
|
+
/**
|
|
2060
|
+
* Derive the deterministic 32-byte ephemeral secret for self-note `index`.
|
|
2061
|
+
* Feed it to EncryptedMemo.encrypt / NoteBuilder.build as `ephSkOverride`.
|
|
2062
|
+
*/
|
|
2063
|
+
declare function deriveSelfEphSk(spendingKey: bigint, index: number): Uint8Array;
|
|
2064
|
+
/** One precomputed self-note window entry. */
|
|
2065
|
+
interface SelfEphWindowEntry {
|
|
2066
|
+
index: number;
|
|
2067
|
+
/** 0x-prefixed LE-packed ephPk — byte-identical to the memo's last 32 bytes. */
|
|
2068
|
+
ephPkHex: string;
|
|
2069
|
+
/** ECDH shared secret vs the wallet's own ivk — feeds decryptWithSharedSecret. */
|
|
2070
|
+
sharedSecret: Uint8Array;
|
|
2071
|
+
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Precompute the self-note discovery window [from, from+count): for each
|
|
2074
|
+
* index, the ephPk the wallet would have published and the shared secret
|
|
2075
|
+
* needed to decrypt the memo. One EC pass up front; scanning then matches
|
|
2076
|
+
* hints by ephPk hex equality with no per-hint EC work.
|
|
2077
|
+
*
|
|
2078
|
+
* @param spendingKey Wallet spending key (the seed of the derivation).
|
|
2079
|
+
* @param ivkPacked The wallet's OWN 32-byte LE packed viewing public key —
|
|
2080
|
+
* self memos are encrypted to it.
|
|
2081
|
+
*/
|
|
2082
|
+
declare function selfEphWindow(spendingKey: bigint, ivkPacked: Uint8Array, from: number, count: number): SelfEphWindowEntry[];
|
|
2083
|
+
|
|
2014
2084
|
/**
|
|
2015
2085
|
* NoteDecryptor
|
|
2016
2086
|
*
|
|
@@ -2034,6 +2104,24 @@ declare const EncryptedMemo: {
|
|
|
2034
2104
|
* deriveSpendingKeyFromSignature.
|
|
2035
2105
|
*/
|
|
2036
2106
|
declare function computeNullifier(commitment: bigint, spendingKey: bigint): bigint;
|
|
2107
|
+
interface TryDecryptOptions {
|
|
2108
|
+
/**
|
|
2109
|
+
* View-tag fast path: compute the ECDH shared secret once, compare the
|
|
2110
|
+
* 1-byte tag in memo nonce[0], and skip the AEAD decrypt on mismatch
|
|
2111
|
+
* (255/256 of foreign notes; `reason: 'view_tag_mismatch'`).
|
|
2112
|
+
*
|
|
2113
|
+
* Only enable for commitments at/after the wallet's tagActivationLeaf —
|
|
2114
|
+
* legacy memos carry a random byte there and would be silently dropped.
|
|
2115
|
+
*/
|
|
2116
|
+
viewTag?: boolean;
|
|
2117
|
+
/**
|
|
2118
|
+
* Precomputed ECDH shared secret (self-note discovery: the caller matched
|
|
2119
|
+
* the hint's ephPk against a selfEphWindow and already holds the secret).
|
|
2120
|
+
* Skips the ECDH and the view-tag gate entirely; the decrypt + commitment
|
|
2121
|
+
* check still validate the note as usual.
|
|
2122
|
+
*/
|
|
2123
|
+
sharedSecret?: Uint8Array;
|
|
2124
|
+
}
|
|
2037
2125
|
/**
|
|
2038
2126
|
* Attempt to decrypt an on-chain commitment using the recipient's viewing secret key.
|
|
2039
2127
|
*
|
|
@@ -2047,13 +2135,14 @@ declare function computeNullifier(commitment: bigint, spendingKey: bigint): bigi
|
|
|
2047
2135
|
* @param spendingKey Spending key bigint (for nullifier computation).
|
|
2048
2136
|
* @param ownOwnerPk The viewer's global BabyJubJub Ax (ownerPk). Required for stealth detection.
|
|
2049
2137
|
* Pass 0n to disable stealth detection (legacy/own-note-only scanning).
|
|
2138
|
+
* @param opts See TryDecryptOptions (view-tag fast path).
|
|
2050
2139
|
*/
|
|
2051
|
-
declare function tryDecryptNote(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint): ZkNote | null;
|
|
2140
|
+
declare function tryDecryptNote(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint, opts?: TryDecryptOptions): ZkNote | null;
|
|
2052
2141
|
/**
|
|
2053
2142
|
* Like tryDecryptNote but also returns a human-readable reason for failure.
|
|
2054
2143
|
* Useful for debugging scan issues (wrong key, corrupted memo, commitment mismatch).
|
|
2055
2144
|
*/
|
|
2056
|
-
declare function tryDecryptNoteVerbose(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint): {
|
|
2145
|
+
declare function tryDecryptNoteVerbose(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint, opts?: TryDecryptOptions): {
|
|
2057
2146
|
note: ZkNote | null;
|
|
2058
2147
|
reason?: string;
|
|
2059
2148
|
};
|
|
@@ -4172,4 +4261,4 @@ interface ExtrinsicFailedData {
|
|
|
4172
4261
|
dispatch_info: DispatchInfo;
|
|
4173
4262
|
}
|
|
4174
4263
|
|
|
4175
|
-
export { type AccountListing, type AccountMappedData, type AccountMappedEvent, type AccountMappingCall, type AccountMappingEvent, AccountMappingModule, AccountMappingPrecompile, type AccountMetadata, type AccountUnmappedEvent, type ActiveVersionSetEvent, type AddChainLinkArgs, type AddChainLinkParams, type AddSupportedChainArgs, type AliasFullIdentity, type AliasInfo, type AliasListedForSaleEvent, type AliasOnSaleData, type AliasRegisteredData, type AliasRegisteredEvent, type AliasReleasedEvent, type AliasSaleCancelledEvent, type AliasSoldData, type AliasSoldEvent, type AliasTransferredData, type AliasTransferredEvent, type AssetRegisteredEvent, type AssetUnverifiedEvent, type AssetVerifiedEvent, BABYJUB_SUBORDER, BN254_R, type BatchRegisterVerificationKeysArgs, type BatchVerificationKeysRegisteredEvent, type BlockInfo, type BuyAliasArgs, type Bytes32, CURRENT_CIRCUIT_VERSION, type ChainInfo, type ChainLink, type ChainLinkAddedEvent, type ChainLinkRemovedEvent, CircuitId, CircuitId as CircuitIdType, CircuitVersionResolver, type ClaimShieldedFeesParams, type ClientProviderConfig, type CommitmentsInsertedEvent, type CommitmentsInsertedEventData, type ConnectionStatus, CryptoPrecompiles, type DecodedAddChainLinkArgs, type DecodedBatchArgs, type DecodedDispatchAsPrivateLinkArgs, type DecodedEthereumTransactArgs, type DecodedEvmCallArgs, type DecodedPrecompile, type DecodedPrivateTransferArgs, type DecodedPutAliasForSaleArgs, type DecodedRegisterAliasArgs, type DecodedRemarkArgs, type DecodedRevealPrivateLinkArgs, type DecodedSetAccountMetadataArgs, type DecodedShieldArgs, type DecodedShieldBatchArgs, type DecodedShieldBatchOperation, type DecodedSudoArgs, type DecodedTransferAllArgs, type DecodedTransferArgs, type DecodedTransferKeepAliveArgs, type DecodedUnshieldArgs, type DecryptedMemo, type DispatchAsLinkedAccountArgs, type DispatchAsLinkedParams, type DispatchAsPrivateLinkArgs, type DispatchError, type DispatchInfo, type DynamicBuilder, ENCRYPTED_MEMO_SIZE, EncryptedMemo, type EncryptedNoteRecord, type EndowedEventData, type EthereumExecutedData, type EventData, type EventPhase, type EventRecord, type EvmAddressInfo, type EvmBlock, EvmClient, type EvmExecutedData, type EvmExitReason, EvmExplorer, type EvmLog, type EvmSigner, type EvmTransaction, type EvmTxRequest, type EvmTxSummary, type ExtrinsicDecoder, type ExtrinsicFailedData, type ExtrinsicSuccessData, type FeeClaimProofInputs, type FormatOptions, KNOWN_PRECOMPILES, type KnownPrecompileInfo, type ListingInfo, type MerkleRootUpdatedData, type MerkleRootUpdatedEvent, type MerkleTreeInfo, type MetadataUpdatedEvent, NoteBuilder, type NoteDisclosure, type NoteInput, type NoteStatusUpdate, type NullifiersSpentEvent, type NullifiersSpentEventData, OrbinumClient, type OrbinumClientConfig, OrbinumClientProvider, PRECOMPILE_ADDR, PrivacyKeyManager, type PrivacyMerkleProof, PrivacyModule, type PrivateChainLinkAddedEvent, type PrivateChainLinkRemovedEvent, type PrivateChainLinkRevealedEvent, type PrivateLink, type PrivateLinkDispatchExecutedEvent, type PrivateTransferArgs, type PrivateTransferInput, type PrivateTransferOutput, type PrivateTransferParams, type PrivateTransferProofInputs, type ProofVerificationFailedEvent, type ProofVerifiedEvent, type ProxyCallExecutedEvent, type PutAliasOnSaleArgs, type PutOnSaleParams, type RawBlock, type RawBlockHeader, type RawTransferInput, type RawTransferOutput, type RegisterAliasArgs, type RegisterAssetArgs, type RegisterPrivateLinkArgs, type RegisterVerificationKeyArgs, type RelayerInfo, RelayerStatusModule, type RemoveChainLinkArgs, type RemovePrivateLinkArgs, type RemoveSupportedChainArgs, type RemoveVerificationKeyArgs, type ReservedEventData, type ResolvedAlias, type ResolvedSpendVersion, type RevealPrivateLinkArgs, type RpcV2MerkleProof, type RpcV2NullifierStatus, type RpcV2PoolAssetBalance, type RpcV2PoolStats, SLIP0044_NAMESPACE, type ScanCommitment, type SetAccountMetadataArgs, type SetActiveVersionArgs, type SetMetadataParams, type ShieldArgs, type ShieldBatchArgs, type ShieldBatchItem, type ShieldBatchParams, type ShieldOperation, type ShieldParams, type ShieldedEvent, type ShieldedEventData, type ShieldedPoolCall, type ShieldedPoolEvent, ShieldedPoolModule, ShieldedPoolPrecompile, SignatureScheme, type StatusChangeEvent, type StatusListener, SubstrateClient, type SupportedChain, type SupportedChainAddedEvent, type SupportedChainRemovedEvent, type SystemHealth, type TokenInfo, type TokenTransfer, type TransferAliasArgs, type TransferEventData, type TransferInputNote, type TransferOutputNote, type TxResult, type UnsafeTxOptions, type UnshieldArgs, type UnshieldParams, type UnshieldProofInputs, type UnshieldedEvent, type UnshieldedEventData, type UnverifyAssetArgs, VaultLockedError, type VerificationKeyRegisteredEvent, type VerificationKeyRemovedEvent, type VerifyAssetArgs, type VerifyProofArgs, type VkEntry, type ZkNote, type ZkVerifierCall, type ZkVerifierCircuitVersionInfo, type ZkVerifierEvent, type ZkVerifierHistoricalVersion, ZkVerifierModule, type ZkVerifierVersionStats, type ZkVerifierVkHash, accountIdHexToSs58, addressToAccountIdHex, applyNoteStatus, bigintTo32Be, bigintTo32Le, bigintTo32LeArr, blindTag, buildDummyTransferInput, bytesToBigintLE, computeNullifier, computePathIndices, createNoteDisclosureKey, decodeNoteDisclosureKey, decodePrecompileCalldata, decryptJson, decryptNoteRecord, deriveMasterKeyBytes, deriveOwnerPk, deriveSpendingKeyFromSignature, deriveSpendingKeyMessage, deriveStealthOwnerPk, deriveStealthSk, deriveVaultBlindKey, deriveVaultKey, deriveViewingPublicKey, deriveViewingSecretKey, encryptJson, encryptNote, ensureHexPrefix, evmAddressToAccountId, evmToImplicitSubstrate, evmToMappedAccountHex, evmToSubstrate, formatBalance, formatORB, fromBase64, fromHex, generateFeeClaimProof, generateTransferProof, generateUnshieldProof, getPrecompileLabel, hexToBigint, hexToNumber, implicitSubstrateToEvm, isEvmAddress, isImplicitEvmAccount, isSs58, isSubstrateAddress, isUnifiedAddress, leHexToBigint, mapExtrinsicArgs, mapZkEventData, normalizeEvmAddress, noteBlindTag, randomBlinding, recoverOwnerPkPoint, selectNotes, shortHash, substrateSs58ToAccountIdHex, substrateToEvm, toBase64, toHex, toTxResult, truncateMiddle, tryDecryptNote, tryDecryptNoteVerbose, vaultReplacer, vaultReviver };
|
|
4264
|
+
export { type AccountListing, type AccountMappedData, type AccountMappedEvent, type AccountMappingCall, type AccountMappingEvent, AccountMappingModule, AccountMappingPrecompile, type AccountMetadata, type AccountUnmappedEvent, type ActiveVersionSetEvent, type AddChainLinkArgs, type AddChainLinkParams, type AddSupportedChainArgs, type AliasFullIdentity, type AliasInfo, type AliasListedForSaleEvent, type AliasOnSaleData, type AliasRegisteredData, type AliasRegisteredEvent, type AliasReleasedEvent, type AliasSaleCancelledEvent, type AliasSoldData, type AliasSoldEvent, type AliasTransferredData, type AliasTransferredEvent, type AssetRegisteredEvent, type AssetUnverifiedEvent, type AssetVerifiedEvent, BABYJUB_SUBORDER, BN254_R, type BatchRegisterVerificationKeysArgs, type BatchVerificationKeysRegisteredEvent, type BlockInfo, type BuyAliasArgs, type Bytes32, CURRENT_CIRCUIT_VERSION, type ChainInfo, type ChainLink, type ChainLinkAddedEvent, type ChainLinkRemovedEvent, CircuitId, CircuitId as CircuitIdType, CircuitVersionResolver, type ClaimShieldedFeesParams, type ClientProviderConfig, type CommitmentsInsertedEvent, type CommitmentsInsertedEventData, type ConnectionStatus, CryptoPrecompiles, type DecodedAddChainLinkArgs, type DecodedBatchArgs, type DecodedDispatchAsPrivateLinkArgs, type DecodedEthereumTransactArgs, type DecodedEvmCallArgs, type DecodedPrecompile, type DecodedPrivateTransferArgs, type DecodedPutAliasForSaleArgs, type DecodedRegisterAliasArgs, type DecodedRemarkArgs, type DecodedRevealPrivateLinkArgs, type DecodedSetAccountMetadataArgs, type DecodedShieldArgs, type DecodedShieldBatchArgs, type DecodedShieldBatchOperation, type DecodedSudoArgs, type DecodedTransferAllArgs, type DecodedTransferArgs, type DecodedTransferKeepAliveArgs, type DecodedUnshieldArgs, type DecryptedMemo, type DispatchAsLinkedAccountArgs, type DispatchAsLinkedParams, type DispatchAsPrivateLinkArgs, type DispatchError, type DispatchInfo, type DynamicBuilder, ENCRYPTED_MEMO_SIZE, EncryptedMemo, type EncryptedNoteRecord, type EndowedEventData, type EthereumExecutedData, type EventData, type EventPhase, type EventRecord, type EvmAddressInfo, type EvmBlock, EvmClient, type EvmExecutedData, type EvmExitReason, EvmExplorer, type EvmLog, type EvmSigner, type EvmTransaction, type EvmTxRequest, type EvmTxSummary, type ExtrinsicDecoder, type ExtrinsicFailedData, type ExtrinsicSuccessData, type FeeClaimProofInputs, type FormatOptions, KNOWN_PRECOMPILES, type KnownPrecompileInfo, type ListingInfo, type MerkleRootUpdatedData, type MerkleRootUpdatedEvent, type MerkleTreeInfo, type MetadataUpdatedEvent, NoteBuilder, type NoteDisclosure, type NoteInput, type NoteStatusUpdate, type NullifiersSpentEvent, type NullifiersSpentEventData, OrbinumClient, type OrbinumClientConfig, OrbinumClientProvider, PRECOMPILE_ADDR, PrivacyKeyManager, type PrivacyMerkleProof, PrivacyModule, type PrivateChainLinkAddedEvent, type PrivateChainLinkRemovedEvent, type PrivateChainLinkRevealedEvent, type PrivateLink, type PrivateLinkDispatchExecutedEvent, type PrivateTransferArgs, type PrivateTransferInput, type PrivateTransferOutput, type PrivateTransferParams, type PrivateTransferProofInputs, type ProofVerificationFailedEvent, type ProofVerifiedEvent, type ProxyCallExecutedEvent, type PutAliasOnSaleArgs, type PutOnSaleParams, type RawBlock, type RawBlockHeader, type RawTransferInput, type RawTransferOutput, type RegisterAliasArgs, type RegisterAssetArgs, type RegisterPrivateLinkArgs, type RegisterVerificationKeyArgs, type RelayerInfo, RelayerStatusModule, type RemoveChainLinkArgs, type RemovePrivateLinkArgs, type RemoveSupportedChainArgs, type RemoveVerificationKeyArgs, type ReservedEventData, type ResolvedAlias, type ResolvedSpendVersion, type RevealPrivateLinkArgs, type RpcV2MerkleProof, type RpcV2NullifierStatus, type RpcV2PoolAssetBalance, type RpcV2PoolStats, SLIP0044_NAMESPACE, type ScanCommitment, type SelfEphWindowEntry, type SetAccountMetadataArgs, type SetActiveVersionArgs, type SetMetadataParams, type ShieldArgs, type ShieldBatchArgs, type ShieldBatchItem, type ShieldBatchParams, type ShieldOperation, type ShieldParams, type ShieldedEvent, type ShieldedEventData, type ShieldedPoolCall, type ShieldedPoolEvent, ShieldedPoolModule, ShieldedPoolPrecompile, SignatureScheme, type StatusChangeEvent, type StatusListener, SubstrateClient, type SupportedChain, type SupportedChainAddedEvent, type SupportedChainRemovedEvent, type SystemHealth, type TokenInfo, type TokenTransfer, type TransferAliasArgs, type TransferEventData, type TransferInputNote, type TransferOutputNote, type TryDecryptOptions, type TxResult, type UnsafeTxOptions, type UnshieldArgs, type UnshieldParams, type UnshieldProofInputs, type UnshieldedEvent, type UnshieldedEventData, type UnverifyAssetArgs, VaultLockedError, type VerificationKeyRegisteredEvent, type VerificationKeyRemovedEvent, type VerifyAssetArgs, type VerifyProofArgs, type VkEntry, type ZkNote, type ZkVerifierCall, type ZkVerifierCircuitVersionInfo, type ZkVerifierEvent, type ZkVerifierHistoricalVersion, ZkVerifierModule, type ZkVerifierVersionStats, type ZkVerifierVkHash, accountIdHexToSs58, addressToAccountIdHex, applyNoteStatus, bigintTo32Be, bigintTo32Le, bigintTo32LeArr, blindTag, buildDummyTransferInput, bytesToBigintLE, computeNullifier, computePathIndices, createNoteDisclosureKey, decodeNoteDisclosureKey, decodePrecompileCalldata, decryptJson, decryptNoteRecord, deriveMasterKeyBytes, deriveOwnerPk, deriveSelfEphSk, deriveSpendingKeyFromSignature, deriveSpendingKeyMessage, deriveStealthOwnerPk, deriveStealthSk, deriveVaultBlindKey, deriveVaultKey, deriveViewTag, deriveViewingPublicKey, deriveViewingSecretKey, encryptJson, encryptNote, ensureHexPrefix, evmAddressToAccountId, evmToImplicitSubstrate, evmToMappedAccountHex, evmToSubstrate, formatBalance, formatORB, fromBase64, fromHex, generateFeeClaimProof, generateTransferProof, generateUnshieldProof, getPrecompileLabel, hexToBigint, hexToNumber, implicitSubstrateToEvm, isEvmAddress, isImplicitEvmAccount, isSs58, isSubstrateAddress, isUnifiedAddress, leHexToBigint, mapExtrinsicArgs, mapZkEventData, normalizeEvmAddress, noteBlindTag, randomBlinding, recoverOwnerPkPoint, selectNotes, selfEphWindow, shortHash, substrateSs58ToAccountIdHex, substrateToEvm, toBase64, toHex, toTxResult, truncateMiddle, tryDecryptNote, tryDecryptNoteVerbose, vaultReplacer, vaultReviver };
|
package/dist/index.js
CHANGED
|
@@ -73,12 +73,14 @@ __export(index_exports, {
|
|
|
73
73
|
decryptNoteRecord: () => decryptNoteRecord,
|
|
74
74
|
deriveMasterKeyBytes: () => deriveMasterKeyBytes,
|
|
75
75
|
deriveOwnerPk: () => deriveOwnerPk,
|
|
76
|
+
deriveSelfEphSk: () => deriveSelfEphSk,
|
|
76
77
|
deriveSpendingKeyFromSignature: () => deriveSpendingKeyFromSignature,
|
|
77
78
|
deriveSpendingKeyMessage: () => deriveSpendingKeyMessage,
|
|
78
79
|
deriveStealthOwnerPk: () => deriveStealthOwnerPk,
|
|
79
80
|
deriveStealthSk: () => deriveStealthSk,
|
|
80
81
|
deriveVaultBlindKey: () => deriveVaultBlindKey,
|
|
81
82
|
deriveVaultKey: () => deriveVaultKey,
|
|
83
|
+
deriveViewTag: () => deriveViewTag,
|
|
82
84
|
deriveViewingPublicKey: () => deriveViewingPublicKey,
|
|
83
85
|
deriveViewingSecretKey: () => deriveViewingSecretKey,
|
|
84
86
|
encryptJson: () => encryptJson,
|
|
@@ -116,6 +118,7 @@ __export(index_exports, {
|
|
|
116
118
|
randomBlinding: () => randomBlinding,
|
|
117
119
|
recoverOwnerPkPoint: () => recoverOwnerPkPoint,
|
|
118
120
|
selectNotes: () => selectNotes,
|
|
121
|
+
selfEphWindow: () => selfEphWindow,
|
|
119
122
|
shortHash: () => shortHash,
|
|
120
123
|
substrateSs58ToAccountIdHex: () => substrateSs58ToAccountIdHex,
|
|
121
124
|
substrateToEvm: () => substrateToEvm,
|
|
@@ -1207,6 +1210,32 @@ var import_chacha = require("@noble/ciphers/chacha.js");
|
|
|
1207
1210
|
var import_utils = require("@noble/ciphers/utils.js");
|
|
1208
1211
|
var import_baby_jubjub = require("@zk-kit/baby-jubjub");
|
|
1209
1212
|
|
|
1213
|
+
// src/utils/bjj-fast.ts
|
|
1214
|
+
var import_edwards = require("@noble/curves/abstract/edwards.js");
|
|
1215
|
+
var P = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
1216
|
+
var N = 2736030358979909402780800718157159386076813972158567259200215660948447373041n;
|
|
1217
|
+
var BjjPoint = (0, import_edwards.edwards)({
|
|
1218
|
+
p: P,
|
|
1219
|
+
n: N,
|
|
1220
|
+
h: 8n,
|
|
1221
|
+
a: 168700n,
|
|
1222
|
+
d: 168696n,
|
|
1223
|
+
Gx: 5299619240641551281634865583518297030282874472190772894086521144482721001553n,
|
|
1224
|
+
Gy: 16950150798460657717958625567821834550301663161624707787222815936182638968203n
|
|
1225
|
+
});
|
|
1226
|
+
function fastMulBase(scalar) {
|
|
1227
|
+
const s = scalar % N;
|
|
1228
|
+
if (s === 0n) return [0n, 1n];
|
|
1229
|
+
const { x, y } = BjjPoint.BASE.multiply(s).toAffine();
|
|
1230
|
+
return [x, y];
|
|
1231
|
+
}
|
|
1232
|
+
function fastMulPoint(point, scalar) {
|
|
1233
|
+
const s = scalar % N;
|
|
1234
|
+
if (s === 0n) return [0n, 1n];
|
|
1235
|
+
const { x, y } = BjjPoint.fromAffine({ x: point[0], y: point[1] }).multiplyUnsafe(s).toAffine();
|
|
1236
|
+
return [x, y];
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1210
1239
|
// src/utils/bytes.ts
|
|
1211
1240
|
function bigintTo32Le(n) {
|
|
1212
1241
|
const buf = new Uint8Array(32);
|
|
@@ -1262,6 +1291,7 @@ var BABYJUB_SUBORDER = 273603035897990940278080071815715938607681397215856725920
|
|
|
1262
1291
|
// src/shielded-pool/protocol/memo.ts
|
|
1263
1292
|
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
1264
1293
|
var KEY_DOMAIN = new TextEncoder().encode("orbinum-note-encryption-v1");
|
|
1294
|
+
var VIEW_TAG_DOMAIN = new TextEncoder().encode("orbinum-view-tag-v1");
|
|
1265
1295
|
var MEMO_PLAINTEXT_SIZE = 120;
|
|
1266
1296
|
function serializeMemo(value, ownerPk, blinding, assetId, counterpartyPk, circuitVersion) {
|
|
1267
1297
|
const buf = new Uint8Array(MEMO_PLAINTEXT_SIZE);
|
|
@@ -1282,6 +1312,12 @@ function deriveEncryptionKey(sharedSecret, commitment) {
|
|
|
1282
1312
|
h.update(KEY_DOMAIN);
|
|
1283
1313
|
return h.digest();
|
|
1284
1314
|
}
|
|
1315
|
+
function deriveViewTag(sharedSecret) {
|
|
1316
|
+
const h = import_sha2.sha256.create();
|
|
1317
|
+
h.update(VIEW_TAG_DOMAIN);
|
|
1318
|
+
h.update(sharedSecret);
|
|
1319
|
+
return h.digest()[0];
|
|
1320
|
+
}
|
|
1285
1321
|
|
|
1286
1322
|
// src/shielded-pool/protocol/EncryptedMemo.ts
|
|
1287
1323
|
var NONCE_SIZE = 12;
|
|
@@ -1349,15 +1385,16 @@ var EncryptedMemo = {
|
|
|
1349
1385
|
if (ephSkBytes.length !== 32)
|
|
1350
1386
|
throw new Error("EncryptedMemo.encrypt: ephSkOverride must be 32 bytes");
|
|
1351
1387
|
const ephSkScalar = bytesToBjjScalar(ephSkBytes);
|
|
1352
|
-
const ephPkPoint = (
|
|
1388
|
+
const ephPkPoint = fastMulBase(ephSkScalar);
|
|
1353
1389
|
ephPkPackedBytes = bigintTo32Le((0, import_baby_jubjub.packPoint)(ephPkPoint));
|
|
1354
1390
|
const ivkPackedBigint = bytesToBigintLE(recipientIvkPacked);
|
|
1355
1391
|
const ivkPoint = (0, import_baby_jubjub.unpackPoint)(ivkPackedBigint);
|
|
1356
1392
|
if (!ivkPoint)
|
|
1357
1393
|
throw new Error("EncryptedMemo.encrypt: invalid recipient viewing public key");
|
|
1358
|
-
const sharedPoint = (
|
|
1394
|
+
const sharedPoint = fastMulPoint(ivkPoint, ephSkScalar);
|
|
1359
1395
|
sharedSecret = bigintTo32Le(sharedPoint[0]);
|
|
1360
1396
|
}
|
|
1397
|
+
nonce[0] = deriveViewTag(sharedSecret);
|
|
1361
1398
|
const encKey = deriveEncryptionKey(sharedSecret, commitment);
|
|
1362
1399
|
const cipher = (0, import_chacha.chacha20poly1305)(encKey, nonce);
|
|
1363
1400
|
const ciphertext = cipher.encrypt(plaintext);
|
|
@@ -1444,27 +1481,38 @@ var EncryptedMemo = {
|
|
|
1444
1481
|
const ephPkPoint = (0, import_baby_jubjub.unpackPoint)(ephPkPackedBigint);
|
|
1445
1482
|
if (!ephPkPoint) return null;
|
|
1446
1483
|
const ivskScalar = bytesToBjjScalar(viewingSecretKey);
|
|
1447
|
-
const sharedPoint = (
|
|
1484
|
+
const sharedPoint = fastMulPoint(ephPkPoint, ivskScalar);
|
|
1448
1485
|
return bigintTo32Le(sharedPoint[0]);
|
|
1449
1486
|
},
|
|
1450
|
-
/**
|
|
1451
|
-
|
|
1487
|
+
/**
|
|
1488
|
+
* Cheap view-tag check: does memo nonce[0] match the tag derived from
|
|
1489
|
+
* `sharedSecret`? One SHA256 + one byte compare — no AEAD work.
|
|
1490
|
+
*
|
|
1491
|
+
* Only meaningful for memos built with view tags (commitments at/after
|
|
1492
|
+
* the wallet's tagActivationLeaf): a legacy memo carries a random byte
|
|
1493
|
+
* there and would false-negative 255/256 of the time.
|
|
1494
|
+
*/
|
|
1495
|
+
checkViewTag(memoBytes, sharedSecret) {
|
|
1496
|
+
if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return false;
|
|
1497
|
+
return memoBytes[0] === deriveViewTag(sharedSecret);
|
|
1498
|
+
},
|
|
1499
|
+
/**
|
|
1500
|
+
* Decrypt with an already-computed shared secret (from
|
|
1501
|
+
* extractSharedSecret), skipping the ECDH. Pair with checkViewTag for the
|
|
1502
|
+
* fast scan path: ECDH once → tag check → decrypt only on match.
|
|
1503
|
+
*/
|
|
1504
|
+
decryptWithSharedSecret(memoBytes, commitment, sharedSecret) {
|
|
1505
|
+
if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return null;
|
|
1452
1506
|
const nonce = memoBytes.slice(0, NONCE_SIZE);
|
|
1453
1507
|
const ciphertextWithMac = memoBytes.slice(NONCE_SIZE, NONCE_SIZE + CIPHERTEXT_SIZE);
|
|
1454
|
-
const ephPkPackedBytes = memoBytes.slice(NONCE_SIZE + CIPHERTEXT_SIZE);
|
|
1455
|
-
const ephPkPackedBigint = bytesToBigintLE(ephPkPackedBytes);
|
|
1456
|
-
let sharedSecret;
|
|
1457
|
-
if (ephPkPackedBigint === 0n) {
|
|
1458
|
-
sharedSecret = new Uint8Array(32);
|
|
1459
|
-
} else {
|
|
1460
|
-
const ephPkPoint = (0, import_baby_jubjub.unpackPoint)(ephPkPackedBigint);
|
|
1461
|
-
if (!ephPkPoint) return null;
|
|
1462
|
-
const ivskScalar = bytesToBjjScalar(viewingSecretKey);
|
|
1463
|
-
const sharedPoint = (0, import_baby_jubjub.mulPointEscalar)(ephPkPoint, ivskScalar);
|
|
1464
|
-
sharedSecret = bigintTo32Le(sharedPoint[0]);
|
|
1465
|
-
}
|
|
1466
1508
|
const encKey = deriveEncryptionKey(sharedSecret, commitment);
|
|
1467
1509
|
return parsePlaintext(nonce, ciphertextWithMac, encKey);
|
|
1510
|
+
},
|
|
1511
|
+
/** @internal */
|
|
1512
|
+
_decrypt(memoBytes, commitment, viewingSecretKey) {
|
|
1513
|
+
const sharedSecret = EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
1514
|
+
if (!sharedSecret) return null;
|
|
1515
|
+
return EncryptedMemo.decryptWithSharedSecret(memoBytes, commitment, sharedSecret);
|
|
1468
1516
|
}
|
|
1469
1517
|
};
|
|
1470
1518
|
|
|
@@ -3814,7 +3862,8 @@ var NoteBuilder = class {
|
|
|
3814
3862
|
commitmentBytes,
|
|
3815
3863
|
input.viewingPublicKey,
|
|
3816
3864
|
bigintTo32Le(counterpartyPk),
|
|
3817
|
-
circuitVersion
|
|
3865
|
+
circuitVersion,
|
|
3866
|
+
input.ephSkOverride
|
|
3818
3867
|
)
|
|
3819
3868
|
) : Array.from(EncryptedMemo.dummy());
|
|
3820
3869
|
if (memo.length !== ENCRYPTED_MEMO_SIZE)
|
|
@@ -3864,15 +3913,45 @@ var NoteBuilder = class {
|
|
|
3864
3913
|
}
|
|
3865
3914
|
};
|
|
3866
3915
|
|
|
3916
|
+
// src/shielded-pool/protocol/selfEph.ts
|
|
3917
|
+
var import_sha23 = require("@noble/hashes/sha2.js");
|
|
3918
|
+
var import_baby_jubjub5 = require("@zk-kit/baby-jubjub");
|
|
3919
|
+
var SELF_EPH_DOMAIN = new TextEncoder().encode("orbinum-self-eph-v1");
|
|
3920
|
+
function deriveSelfEphSk(spendingKey, index) {
|
|
3921
|
+
const h = import_sha23.sha256.create();
|
|
3922
|
+
h.update(SELF_EPH_DOMAIN);
|
|
3923
|
+
h.update(bigintTo32Le(spendingKey));
|
|
3924
|
+
const idx = new Uint8Array(4);
|
|
3925
|
+
new DataView(idx.buffer).setUint32(0, index >>> 0, true);
|
|
3926
|
+
h.update(idx);
|
|
3927
|
+
return h.digest();
|
|
3928
|
+
}
|
|
3929
|
+
function selfEphWindow(spendingKey, ivkPacked, from, count) {
|
|
3930
|
+
const ivkPoint = (0, import_baby_jubjub5.unpackPoint)(bytesToBigintLE(ivkPacked));
|
|
3931
|
+
if (!ivkPoint) throw new Error("selfEphWindow: invalid viewing public key");
|
|
3932
|
+
const entries = [];
|
|
3933
|
+
for (let i = from; i < from + count; i++) {
|
|
3934
|
+
const scalar = bytesToBjjScalar(deriveSelfEphSk(spendingKey, i));
|
|
3935
|
+
const ephPk = fastMulBase(scalar);
|
|
3936
|
+
const sharedPoint = fastMulPoint(ivkPoint, scalar);
|
|
3937
|
+
entries.push({
|
|
3938
|
+
index: i,
|
|
3939
|
+
ephPkHex: toHex(bigintTo32Le((0, import_baby_jubjub5.packPoint)(ephPk))),
|
|
3940
|
+
sharedSecret: bigintTo32Le(sharedPoint[0])
|
|
3941
|
+
});
|
|
3942
|
+
}
|
|
3943
|
+
return entries;
|
|
3944
|
+
}
|
|
3945
|
+
|
|
3867
3946
|
// src/shielded-pool/protocol/NoteDecryptor.ts
|
|
3868
3947
|
var import_poseidon_lite2 = require("poseidon-lite");
|
|
3869
3948
|
function computeNullifier(commitment, spendingKey) {
|
|
3870
3949
|
return (0, import_poseidon_lite2.poseidon2)([commitment, spendingKey]);
|
|
3871
3950
|
}
|
|
3872
|
-
function tryDecryptNote(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n) {
|
|
3873
|
-
return tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk).note;
|
|
3951
|
+
function tryDecryptNote(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n, opts) {
|
|
3952
|
+
return tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk, opts).note;
|
|
3874
3953
|
}
|
|
3875
|
-
function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n) {
|
|
3954
|
+
function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n, opts) {
|
|
3876
3955
|
if (!commitment.encryptedMemo) return { note: null, reason: "no_memo" };
|
|
3877
3956
|
let commitmentBytes;
|
|
3878
3957
|
let memoBytes;
|
|
@@ -3888,21 +3967,29 @@ function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwn
|
|
|
3888
3967
|
reason: `memo_size_mismatch:got_${memoBytes.length}_expected_${ENCRYPTED_MEMO_SIZE}`
|
|
3889
3968
|
};
|
|
3890
3969
|
}
|
|
3891
|
-
|
|
3970
|
+
let sharedSecret = opts?.sharedSecret ?? null;
|
|
3971
|
+
if (!sharedSecret && opts?.viewTag) {
|
|
3972
|
+
sharedSecret = EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
3973
|
+
if (!sharedSecret) return { note: null, reason: "stealth_shared_secret_failed" };
|
|
3974
|
+
if (!EncryptedMemo.checkViewTag(memoBytes, sharedSecret)) {
|
|
3975
|
+
return { note: null, reason: "view_tag_mismatch" };
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
const plaintext = sharedSecret ? EncryptedMemo.decryptWithSharedSecret(memoBytes, commitmentBytes, sharedSecret) : EncryptedMemo.decrypt(memoBytes, commitmentBytes, viewingSecretKey);
|
|
3892
3979
|
if (!plaintext) return { note: null, reason: "decrypt_failed:wrong_key_or_corrupt_mac" };
|
|
3893
3980
|
let effectiveOwnerPk = plaintext.ownerPk;
|
|
3894
3981
|
let effectiveSpendingKey = spendingKey;
|
|
3895
3982
|
if (ownOwnerPk !== 0n && plaintext.ownerPk !== ownOwnerPk) {
|
|
3896
|
-
const
|
|
3897
|
-
if (!
|
|
3983
|
+
const ss = sharedSecret ?? EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
3984
|
+
if (!ss) return { note: null, reason: "stealth_shared_secret_failed" };
|
|
3898
3985
|
const ownPkPoint = recoverOwnerPkPoint(ownOwnerPk);
|
|
3899
3986
|
if (!ownPkPoint) return { note: null, reason: "stealth_invalid_own_owner_pk" };
|
|
3900
|
-
const stealthOwnerPk = deriveStealthOwnerPk(
|
|
3987
|
+
const stealthOwnerPk = deriveStealthOwnerPk(ss, ownOwnerPk, ownPkPoint);
|
|
3901
3988
|
if (stealthOwnerPk !== plaintext.ownerPk) {
|
|
3902
3989
|
return { note: null, reason: "commitment_mismatch" };
|
|
3903
3990
|
}
|
|
3904
3991
|
effectiveOwnerPk = stealthOwnerPk;
|
|
3905
|
-
effectiveSpendingKey = deriveStealthSk(
|
|
3992
|
+
effectiveSpendingKey = deriveStealthSk(ss, ownOwnerPk, spendingKey);
|
|
3906
3993
|
}
|
|
3907
3994
|
const recomputed = (0, import_poseidon_lite2.poseidon4)([
|
|
3908
3995
|
plaintext.value,
|
|
@@ -4030,8 +4117,8 @@ function randomBlinding() {
|
|
|
4030
4117
|
|
|
4031
4118
|
// src/privacy-keys/PrivacyKeys.ts
|
|
4032
4119
|
var import_hkdf2 = require("@noble/hashes/hkdf.js");
|
|
4033
|
-
var
|
|
4034
|
-
var
|
|
4120
|
+
var import_sha24 = require("@noble/hashes/sha2.js");
|
|
4121
|
+
var import_baby_jubjub6 = require("@zk-kit/baby-jubjub");
|
|
4035
4122
|
var IVK_DOMAIN = new TextEncoder().encode("orbinum-ivk-v1");
|
|
4036
4123
|
function deriveSpendingKeyMessage(chainId, address) {
|
|
4037
4124
|
return `orbinum-spending-key-v1
|
|
@@ -4041,7 +4128,7 @@ ${address.toLowerCase()}`;
|
|
|
4041
4128
|
async function deriveMasterKeyBytes(signatureHex, chainId, address) {
|
|
4042
4129
|
const sigBytes = fromHex(signatureHex);
|
|
4043
4130
|
const info = new TextEncoder().encode(`orbinum-sk-v1:${chainId}:${address.toLowerCase()}`);
|
|
4044
|
-
return (0, import_hkdf2.hkdf)(
|
|
4131
|
+
return (0, import_hkdf2.hkdf)(import_sha24.sha256, sigBytes, new Uint8Array(0), info, 32);
|
|
4045
4132
|
}
|
|
4046
4133
|
async function deriveSpendingKeyFromSignature(signatureHex, chainId, address) {
|
|
4047
4134
|
const masterBytes = await deriveMasterKeyBytes(signatureHex, chainId, address);
|
|
@@ -4050,17 +4137,17 @@ async function deriveSpendingKeyFromSignature(signatureHex, chainId, address) {
|
|
|
4050
4137
|
}
|
|
4051
4138
|
function deriveViewingSecretKey(spendingKey) {
|
|
4052
4139
|
const ikm = bigintTo32Le(spendingKey);
|
|
4053
|
-
return (0, import_hkdf2.hkdf)(
|
|
4140
|
+
return (0, import_hkdf2.hkdf)(import_sha24.sha256, ikm, void 0, IVK_DOMAIN, 32);
|
|
4054
4141
|
}
|
|
4055
4142
|
function deriveViewingPublicKey(ivsk) {
|
|
4056
4143
|
const ivskScalar = BigInt(toHex(ivsk)) % BABYJUB_SUBORDER || 1n;
|
|
4057
|
-
const ivkPoint = (0,
|
|
4058
|
-
const packed = (0,
|
|
4144
|
+
const ivkPoint = (0, import_baby_jubjub6.mulPointEscalar)(import_baby_jubjub6.Base8, ivskScalar);
|
|
4145
|
+
const packed = (0, import_baby_jubjub6.packPoint)(ivkPoint);
|
|
4059
4146
|
return bigintTo32Le(packed);
|
|
4060
4147
|
}
|
|
4061
4148
|
function deriveOwnerPk(spendingKey) {
|
|
4062
4149
|
try {
|
|
4063
|
-
const pubPoint = (0,
|
|
4150
|
+
const pubPoint = (0, import_baby_jubjub6.mulPointEscalar)(import_baby_jubjub6.Base8, spendingKey);
|
|
4064
4151
|
return pubPoint[0];
|
|
4065
4152
|
} catch {
|
|
4066
4153
|
return 0n;
|
|
@@ -4369,7 +4456,7 @@ async function noteBlindTag(blindKey, hex) {
|
|
|
4369
4456
|
// src/proof-generator/unshield.ts
|
|
4370
4457
|
var import_proof_generator2 = require("@orbinum/proof-generator");
|
|
4371
4458
|
var import_utils3 = require("@noble/ciphers/utils.js");
|
|
4372
|
-
var
|
|
4459
|
+
var import_baby_jubjub7 = require("@zk-kit/baby-jubjub");
|
|
4373
4460
|
var import_poseidon_lite4 = require("poseidon-lite");
|
|
4374
4461
|
|
|
4375
4462
|
// src/proof-generator/merkle.ts
|
|
@@ -4392,7 +4479,7 @@ async function generateUnshieldProof(inputs, options = {}) {
|
|
|
4392
4479
|
if (changeValue < 0n) {
|
|
4393
4480
|
throw new Error("changeValue must be >= 0.");
|
|
4394
4481
|
}
|
|
4395
|
-
const changeOwnerPubkey = inputs.changeOwnerPubkey ?? (0,
|
|
4482
|
+
const changeOwnerPubkey = inputs.changeOwnerPubkey ?? (0, import_baby_jubjub7.mulPointEscalar)(import_baby_jubjub7.Base8, inputs.spendingKey)[0];
|
|
4396
4483
|
const changeBlinding = inputs.changeBlinding ?? (changeValue > 0n ? bytesToBigintLE((0, import_utils3.randomBytes)(32)) : 0n);
|
|
4397
4484
|
const changeCommitment = changeValue > 0n ? (0, import_poseidon_lite4.poseidon4)([changeValue, inputs.assetId, changeOwnerPubkey, changeBlinding]) : 0n;
|
|
4398
4485
|
const circuitInputs = {
|
|
@@ -5297,12 +5384,14 @@ var import_polkadot_api4 = require("polkadot-api");
|
|
|
5297
5384
|
decryptNoteRecord,
|
|
5298
5385
|
deriveMasterKeyBytes,
|
|
5299
5386
|
deriveOwnerPk,
|
|
5387
|
+
deriveSelfEphSk,
|
|
5300
5388
|
deriveSpendingKeyFromSignature,
|
|
5301
5389
|
deriveSpendingKeyMessage,
|
|
5302
5390
|
deriveStealthOwnerPk,
|
|
5303
5391
|
deriveStealthSk,
|
|
5304
5392
|
deriveVaultBlindKey,
|
|
5305
5393
|
deriveVaultKey,
|
|
5394
|
+
deriveViewTag,
|
|
5306
5395
|
deriveViewingPublicKey,
|
|
5307
5396
|
deriveViewingSecretKey,
|
|
5308
5397
|
encryptJson,
|
|
@@ -5340,6 +5429,7 @@ var import_polkadot_api4 = require("polkadot-api");
|
|
|
5340
5429
|
randomBlinding,
|
|
5341
5430
|
recoverOwnerPkPoint,
|
|
5342
5431
|
selectNotes,
|
|
5432
|
+
selfEphWindow,
|
|
5343
5433
|
shortHash,
|
|
5344
5434
|
substrateSs58ToAccountIdHex,
|
|
5345
5435
|
substrateToEvm,
|
package/dist/index.mjs
CHANGED
|
@@ -1074,7 +1074,33 @@ function resolveTx(unsafe, pallet, call) {
|
|
|
1074
1074
|
// src/shielded-pool/protocol/EncryptedMemo.ts
|
|
1075
1075
|
import { chacha20poly1305 } from "@noble/ciphers/chacha.js";
|
|
1076
1076
|
import { randomBytes } from "@noble/ciphers/utils.js";
|
|
1077
|
-
import {
|
|
1077
|
+
import { packPoint, unpackPoint } from "@zk-kit/baby-jubjub";
|
|
1078
|
+
|
|
1079
|
+
// src/utils/bjj-fast.ts
|
|
1080
|
+
import { edwards } from "@noble/curves/abstract/edwards.js";
|
|
1081
|
+
var P = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
1082
|
+
var N = 2736030358979909402780800718157159386076813972158567259200215660948447373041n;
|
|
1083
|
+
var BjjPoint = edwards({
|
|
1084
|
+
p: P,
|
|
1085
|
+
n: N,
|
|
1086
|
+
h: 8n,
|
|
1087
|
+
a: 168700n,
|
|
1088
|
+
d: 168696n,
|
|
1089
|
+
Gx: 5299619240641551281634865583518297030282874472190772894086521144482721001553n,
|
|
1090
|
+
Gy: 16950150798460657717958625567821834550301663161624707787222815936182638968203n
|
|
1091
|
+
});
|
|
1092
|
+
function fastMulBase(scalar) {
|
|
1093
|
+
const s = scalar % N;
|
|
1094
|
+
if (s === 0n) return [0n, 1n];
|
|
1095
|
+
const { x, y } = BjjPoint.BASE.multiply(s).toAffine();
|
|
1096
|
+
return [x, y];
|
|
1097
|
+
}
|
|
1098
|
+
function fastMulPoint(point, scalar) {
|
|
1099
|
+
const s = scalar % N;
|
|
1100
|
+
if (s === 0n) return [0n, 1n];
|
|
1101
|
+
const { x, y } = BjjPoint.fromAffine({ x: point[0], y: point[1] }).multiplyUnsafe(s).toAffine();
|
|
1102
|
+
return [x, y];
|
|
1103
|
+
}
|
|
1078
1104
|
|
|
1079
1105
|
// src/utils/bytes.ts
|
|
1080
1106
|
function bigintTo32Le(n) {
|
|
@@ -1131,6 +1157,7 @@ var BABYJUB_SUBORDER = 273603035897990940278080071815715938607681397215856725920
|
|
|
1131
1157
|
// src/shielded-pool/protocol/memo.ts
|
|
1132
1158
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
1133
1159
|
var KEY_DOMAIN = new TextEncoder().encode("orbinum-note-encryption-v1");
|
|
1160
|
+
var VIEW_TAG_DOMAIN = new TextEncoder().encode("orbinum-view-tag-v1");
|
|
1134
1161
|
var MEMO_PLAINTEXT_SIZE = 120;
|
|
1135
1162
|
function serializeMemo(value, ownerPk, blinding, assetId, counterpartyPk, circuitVersion) {
|
|
1136
1163
|
const buf = new Uint8Array(MEMO_PLAINTEXT_SIZE);
|
|
@@ -1151,6 +1178,12 @@ function deriveEncryptionKey(sharedSecret, commitment) {
|
|
|
1151
1178
|
h.update(KEY_DOMAIN);
|
|
1152
1179
|
return h.digest();
|
|
1153
1180
|
}
|
|
1181
|
+
function deriveViewTag(sharedSecret) {
|
|
1182
|
+
const h = sha256.create();
|
|
1183
|
+
h.update(VIEW_TAG_DOMAIN);
|
|
1184
|
+
h.update(sharedSecret);
|
|
1185
|
+
return h.digest()[0];
|
|
1186
|
+
}
|
|
1154
1187
|
|
|
1155
1188
|
// src/shielded-pool/protocol/EncryptedMemo.ts
|
|
1156
1189
|
var NONCE_SIZE = 12;
|
|
@@ -1218,15 +1251,16 @@ var EncryptedMemo = {
|
|
|
1218
1251
|
if (ephSkBytes.length !== 32)
|
|
1219
1252
|
throw new Error("EncryptedMemo.encrypt: ephSkOverride must be 32 bytes");
|
|
1220
1253
|
const ephSkScalar = bytesToBjjScalar(ephSkBytes);
|
|
1221
|
-
const ephPkPoint =
|
|
1254
|
+
const ephPkPoint = fastMulBase(ephSkScalar);
|
|
1222
1255
|
ephPkPackedBytes = bigintTo32Le(packPoint(ephPkPoint));
|
|
1223
1256
|
const ivkPackedBigint = bytesToBigintLE(recipientIvkPacked);
|
|
1224
1257
|
const ivkPoint = unpackPoint(ivkPackedBigint);
|
|
1225
1258
|
if (!ivkPoint)
|
|
1226
1259
|
throw new Error("EncryptedMemo.encrypt: invalid recipient viewing public key");
|
|
1227
|
-
const sharedPoint =
|
|
1260
|
+
const sharedPoint = fastMulPoint(ivkPoint, ephSkScalar);
|
|
1228
1261
|
sharedSecret = bigintTo32Le(sharedPoint[0]);
|
|
1229
1262
|
}
|
|
1263
|
+
nonce[0] = deriveViewTag(sharedSecret);
|
|
1230
1264
|
const encKey = deriveEncryptionKey(sharedSecret, commitment);
|
|
1231
1265
|
const cipher = chacha20poly1305(encKey, nonce);
|
|
1232
1266
|
const ciphertext = cipher.encrypt(plaintext);
|
|
@@ -1313,27 +1347,38 @@ var EncryptedMemo = {
|
|
|
1313
1347
|
const ephPkPoint = unpackPoint(ephPkPackedBigint);
|
|
1314
1348
|
if (!ephPkPoint) return null;
|
|
1315
1349
|
const ivskScalar = bytesToBjjScalar(viewingSecretKey);
|
|
1316
|
-
const sharedPoint =
|
|
1350
|
+
const sharedPoint = fastMulPoint(ephPkPoint, ivskScalar);
|
|
1317
1351
|
return bigintTo32Le(sharedPoint[0]);
|
|
1318
1352
|
},
|
|
1319
|
-
/**
|
|
1320
|
-
|
|
1353
|
+
/**
|
|
1354
|
+
* Cheap view-tag check: does memo nonce[0] match the tag derived from
|
|
1355
|
+
* `sharedSecret`? One SHA256 + one byte compare — no AEAD work.
|
|
1356
|
+
*
|
|
1357
|
+
* Only meaningful for memos built with view tags (commitments at/after
|
|
1358
|
+
* the wallet's tagActivationLeaf): a legacy memo carries a random byte
|
|
1359
|
+
* there and would false-negative 255/256 of the time.
|
|
1360
|
+
*/
|
|
1361
|
+
checkViewTag(memoBytes, sharedSecret) {
|
|
1362
|
+
if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return false;
|
|
1363
|
+
return memoBytes[0] === deriveViewTag(sharedSecret);
|
|
1364
|
+
},
|
|
1365
|
+
/**
|
|
1366
|
+
* Decrypt with an already-computed shared secret (from
|
|
1367
|
+
* extractSharedSecret), skipping the ECDH. Pair with checkViewTag for the
|
|
1368
|
+
* fast scan path: ECDH once → tag check → decrypt only on match.
|
|
1369
|
+
*/
|
|
1370
|
+
decryptWithSharedSecret(memoBytes, commitment, sharedSecret) {
|
|
1371
|
+
if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return null;
|
|
1321
1372
|
const nonce = memoBytes.slice(0, NONCE_SIZE);
|
|
1322
1373
|
const ciphertextWithMac = memoBytes.slice(NONCE_SIZE, NONCE_SIZE + CIPHERTEXT_SIZE);
|
|
1323
|
-
const ephPkPackedBytes = memoBytes.slice(NONCE_SIZE + CIPHERTEXT_SIZE);
|
|
1324
|
-
const ephPkPackedBigint = bytesToBigintLE(ephPkPackedBytes);
|
|
1325
|
-
let sharedSecret;
|
|
1326
|
-
if (ephPkPackedBigint === 0n) {
|
|
1327
|
-
sharedSecret = new Uint8Array(32);
|
|
1328
|
-
} else {
|
|
1329
|
-
const ephPkPoint = unpackPoint(ephPkPackedBigint);
|
|
1330
|
-
if (!ephPkPoint) return null;
|
|
1331
|
-
const ivskScalar = bytesToBjjScalar(viewingSecretKey);
|
|
1332
|
-
const sharedPoint = mulPointEscalar(ephPkPoint, ivskScalar);
|
|
1333
|
-
sharedSecret = bigintTo32Le(sharedPoint[0]);
|
|
1334
|
-
}
|
|
1335
1374
|
const encKey = deriveEncryptionKey(sharedSecret, commitment);
|
|
1336
1375
|
return parsePlaintext(nonce, ciphertextWithMac, encKey);
|
|
1376
|
+
},
|
|
1377
|
+
/** @internal */
|
|
1378
|
+
_decrypt(memoBytes, commitment, viewingSecretKey) {
|
|
1379
|
+
const sharedSecret = EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
1380
|
+
if (!sharedSecret) return null;
|
|
1381
|
+
return EncryptedMemo.decryptWithSharedSecret(memoBytes, commitment, sharedSecret);
|
|
1337
1382
|
}
|
|
1338
1383
|
};
|
|
1339
1384
|
|
|
@@ -3504,7 +3549,7 @@ var CURRENT_CIRCUIT_VERSION = 1;
|
|
|
3504
3549
|
// src/utils/stealth.ts
|
|
3505
3550
|
import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
|
|
3506
3551
|
import { hkdf } from "@noble/hashes/hkdf.js";
|
|
3507
|
-
import { mulPointEscalar
|
|
3552
|
+
import { mulPointEscalar, Base8, addPoint } from "@zk-kit/baby-jubjub";
|
|
3508
3553
|
var STEALTH_INFO = new TextEncoder().encode("orbinum-stealth-v1");
|
|
3509
3554
|
function deriveStealthScalar(sharedSecret, ownerPkBigint) {
|
|
3510
3555
|
const salt = bigintTo32Le(ownerPkBigint);
|
|
@@ -3513,7 +3558,7 @@ function deriveStealthScalar(sharedSecret, ownerPkBigint) {
|
|
|
3513
3558
|
}
|
|
3514
3559
|
function deriveStealthOwnerPk(sharedSecret, ownerPkBigint, ownerPkPoint) {
|
|
3515
3560
|
const stealthScalar = deriveStealthScalar(sharedSecret, ownerPkBigint);
|
|
3516
|
-
const stealthPt = addPoint(
|
|
3561
|
+
const stealthPt = addPoint(mulPointEscalar(Base8, stealthScalar), ownerPkPoint);
|
|
3517
3562
|
return stealthPt[0];
|
|
3518
3563
|
}
|
|
3519
3564
|
function deriveStealthSk(sharedSecret, ownerPkBigint, spendingKey) {
|
|
@@ -3522,7 +3567,7 @@ function deriveStealthSk(sharedSecret, ownerPkBigint, spendingKey) {
|
|
|
3522
3567
|
}
|
|
3523
3568
|
|
|
3524
3569
|
// src/utils/bjj.ts
|
|
3525
|
-
import { mulPointEscalar as
|
|
3570
|
+
import { mulPointEscalar as mulPointEscalar2 } from "@zk-kit/baby-jubjub";
|
|
3526
3571
|
var BJJ_A = 168700n;
|
|
3527
3572
|
var BJJ_D = 168696n;
|
|
3528
3573
|
function _modpow(base, exp, mod) {
|
|
@@ -3577,7 +3622,7 @@ function recoverOwnerPkPoint(ax) {
|
|
|
3577
3622
|
if (y === null) return null;
|
|
3578
3623
|
const yAlt = BN254_R - y;
|
|
3579
3624
|
try {
|
|
3580
|
-
const check =
|
|
3625
|
+
const check = mulPointEscalar2([ax, y], BABYJUB_SUBORDER);
|
|
3581
3626
|
return check[0] === 0n && check[1] === 1n ? [ax, y] : [ax, yAlt];
|
|
3582
3627
|
} catch {
|
|
3583
3628
|
return [ax, yAlt];
|
|
@@ -3585,7 +3630,7 @@ function recoverOwnerPkPoint(ax) {
|
|
|
3585
3630
|
}
|
|
3586
3631
|
|
|
3587
3632
|
// src/shielded-pool/protocol/NoteBuilder.ts
|
|
3588
|
-
import { mulPointEscalar as
|
|
3633
|
+
import { mulPointEscalar as mulPointEscalar3, unpackPoint as unpackPoint2 } from "@zk-kit/baby-jubjub";
|
|
3589
3634
|
import { randomBytes as randomBytes2 } from "@noble/ciphers/utils.js";
|
|
3590
3635
|
import { poseidon2, poseidon4 } from "poseidon-lite";
|
|
3591
3636
|
var NoteBuilder = class {
|
|
@@ -3621,7 +3666,7 @@ var NoteBuilder = class {
|
|
|
3621
3666
|
if (!ivkPoint)
|
|
3622
3667
|
throw new Error("NoteBuilder.build: invalid recipient viewing public key");
|
|
3623
3668
|
const ephSkScalar = BigInt(toHex(ephSk)) % BABYJUB_SUBORDER || 1n;
|
|
3624
|
-
const sharedPoint =
|
|
3669
|
+
const sharedPoint = mulPointEscalar3(ivkPoint, ephSkScalar);
|
|
3625
3670
|
const sharedSecret = bigintTo32Le(sharedPoint[0]);
|
|
3626
3671
|
const recipientPkPoint = recoverOwnerPkPoint(recipientOwnerPk);
|
|
3627
3672
|
if (!recipientPkPoint)
|
|
@@ -3686,7 +3731,8 @@ var NoteBuilder = class {
|
|
|
3686
3731
|
commitmentBytes,
|
|
3687
3732
|
input.viewingPublicKey,
|
|
3688
3733
|
bigintTo32Le(counterpartyPk),
|
|
3689
|
-
circuitVersion
|
|
3734
|
+
circuitVersion,
|
|
3735
|
+
input.ephSkOverride
|
|
3690
3736
|
)
|
|
3691
3737
|
) : Array.from(EncryptedMemo.dummy());
|
|
3692
3738
|
if (memo.length !== ENCRYPTED_MEMO_SIZE)
|
|
@@ -3736,15 +3782,45 @@ var NoteBuilder = class {
|
|
|
3736
3782
|
}
|
|
3737
3783
|
};
|
|
3738
3784
|
|
|
3785
|
+
// src/shielded-pool/protocol/selfEph.ts
|
|
3786
|
+
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
3787
|
+
import { packPoint as packPoint2, unpackPoint as unpackPoint3 } from "@zk-kit/baby-jubjub";
|
|
3788
|
+
var SELF_EPH_DOMAIN = new TextEncoder().encode("orbinum-self-eph-v1");
|
|
3789
|
+
function deriveSelfEphSk(spendingKey, index) {
|
|
3790
|
+
const h = sha2563.create();
|
|
3791
|
+
h.update(SELF_EPH_DOMAIN);
|
|
3792
|
+
h.update(bigintTo32Le(spendingKey));
|
|
3793
|
+
const idx = new Uint8Array(4);
|
|
3794
|
+
new DataView(idx.buffer).setUint32(0, index >>> 0, true);
|
|
3795
|
+
h.update(idx);
|
|
3796
|
+
return h.digest();
|
|
3797
|
+
}
|
|
3798
|
+
function selfEphWindow(spendingKey, ivkPacked, from, count) {
|
|
3799
|
+
const ivkPoint = unpackPoint3(bytesToBigintLE(ivkPacked));
|
|
3800
|
+
if (!ivkPoint) throw new Error("selfEphWindow: invalid viewing public key");
|
|
3801
|
+
const entries = [];
|
|
3802
|
+
for (let i = from; i < from + count; i++) {
|
|
3803
|
+
const scalar = bytesToBjjScalar(deriveSelfEphSk(spendingKey, i));
|
|
3804
|
+
const ephPk = fastMulBase(scalar);
|
|
3805
|
+
const sharedPoint = fastMulPoint(ivkPoint, scalar);
|
|
3806
|
+
entries.push({
|
|
3807
|
+
index: i,
|
|
3808
|
+
ephPkHex: toHex(bigintTo32Le(packPoint2(ephPk))),
|
|
3809
|
+
sharedSecret: bigintTo32Le(sharedPoint[0])
|
|
3810
|
+
});
|
|
3811
|
+
}
|
|
3812
|
+
return entries;
|
|
3813
|
+
}
|
|
3814
|
+
|
|
3739
3815
|
// src/shielded-pool/protocol/NoteDecryptor.ts
|
|
3740
3816
|
import { poseidon2 as poseidon22, poseidon4 as poseidon42 } from "poseidon-lite";
|
|
3741
3817
|
function computeNullifier(commitment, spendingKey) {
|
|
3742
3818
|
return poseidon22([commitment, spendingKey]);
|
|
3743
3819
|
}
|
|
3744
|
-
function tryDecryptNote(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n) {
|
|
3745
|
-
return tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk).note;
|
|
3820
|
+
function tryDecryptNote(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n, opts) {
|
|
3821
|
+
return tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk, opts).note;
|
|
3746
3822
|
}
|
|
3747
|
-
function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n) {
|
|
3823
|
+
function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n, opts) {
|
|
3748
3824
|
if (!commitment.encryptedMemo) return { note: null, reason: "no_memo" };
|
|
3749
3825
|
let commitmentBytes;
|
|
3750
3826
|
let memoBytes;
|
|
@@ -3760,21 +3836,29 @@ function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwn
|
|
|
3760
3836
|
reason: `memo_size_mismatch:got_${memoBytes.length}_expected_${ENCRYPTED_MEMO_SIZE}`
|
|
3761
3837
|
};
|
|
3762
3838
|
}
|
|
3763
|
-
|
|
3839
|
+
let sharedSecret = opts?.sharedSecret ?? null;
|
|
3840
|
+
if (!sharedSecret && opts?.viewTag) {
|
|
3841
|
+
sharedSecret = EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
3842
|
+
if (!sharedSecret) return { note: null, reason: "stealth_shared_secret_failed" };
|
|
3843
|
+
if (!EncryptedMemo.checkViewTag(memoBytes, sharedSecret)) {
|
|
3844
|
+
return { note: null, reason: "view_tag_mismatch" };
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
const plaintext = sharedSecret ? EncryptedMemo.decryptWithSharedSecret(memoBytes, commitmentBytes, sharedSecret) : EncryptedMemo.decrypt(memoBytes, commitmentBytes, viewingSecretKey);
|
|
3764
3848
|
if (!plaintext) return { note: null, reason: "decrypt_failed:wrong_key_or_corrupt_mac" };
|
|
3765
3849
|
let effectiveOwnerPk = plaintext.ownerPk;
|
|
3766
3850
|
let effectiveSpendingKey = spendingKey;
|
|
3767
3851
|
if (ownOwnerPk !== 0n && plaintext.ownerPk !== ownOwnerPk) {
|
|
3768
|
-
const
|
|
3769
|
-
if (!
|
|
3852
|
+
const ss = sharedSecret ?? EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
3853
|
+
if (!ss) return { note: null, reason: "stealth_shared_secret_failed" };
|
|
3770
3854
|
const ownPkPoint = recoverOwnerPkPoint(ownOwnerPk);
|
|
3771
3855
|
if (!ownPkPoint) return { note: null, reason: "stealth_invalid_own_owner_pk" };
|
|
3772
|
-
const stealthOwnerPk = deriveStealthOwnerPk(
|
|
3856
|
+
const stealthOwnerPk = deriveStealthOwnerPk(ss, ownOwnerPk, ownPkPoint);
|
|
3773
3857
|
if (stealthOwnerPk !== plaintext.ownerPk) {
|
|
3774
3858
|
return { note: null, reason: "commitment_mismatch" };
|
|
3775
3859
|
}
|
|
3776
3860
|
effectiveOwnerPk = stealthOwnerPk;
|
|
3777
|
-
effectiveSpendingKey = deriveStealthSk(
|
|
3861
|
+
effectiveSpendingKey = deriveStealthSk(ss, ownOwnerPk, spendingKey);
|
|
3778
3862
|
}
|
|
3779
3863
|
const recomputed = poseidon42([
|
|
3780
3864
|
plaintext.value,
|
|
@@ -3902,8 +3986,8 @@ function randomBlinding() {
|
|
|
3902
3986
|
|
|
3903
3987
|
// src/privacy-keys/PrivacyKeys.ts
|
|
3904
3988
|
import { hkdf as hkdf2 } from "@noble/hashes/hkdf.js";
|
|
3905
|
-
import { sha256 as
|
|
3906
|
-
import { mulPointEscalar as
|
|
3989
|
+
import { sha256 as sha2564 } from "@noble/hashes/sha2.js";
|
|
3990
|
+
import { mulPointEscalar as mulPointEscalar4, Base8 as Base82, packPoint as packPoint3 } from "@zk-kit/baby-jubjub";
|
|
3907
3991
|
var IVK_DOMAIN = new TextEncoder().encode("orbinum-ivk-v1");
|
|
3908
3992
|
function deriveSpendingKeyMessage(chainId, address) {
|
|
3909
3993
|
return `orbinum-spending-key-v1
|
|
@@ -3913,7 +3997,7 @@ ${address.toLowerCase()}`;
|
|
|
3913
3997
|
async function deriveMasterKeyBytes(signatureHex, chainId, address) {
|
|
3914
3998
|
const sigBytes = fromHex(signatureHex);
|
|
3915
3999
|
const info = new TextEncoder().encode(`orbinum-sk-v1:${chainId}:${address.toLowerCase()}`);
|
|
3916
|
-
return hkdf2(
|
|
4000
|
+
return hkdf2(sha2564, sigBytes, new Uint8Array(0), info, 32);
|
|
3917
4001
|
}
|
|
3918
4002
|
async function deriveSpendingKeyFromSignature(signatureHex, chainId, address) {
|
|
3919
4003
|
const masterBytes = await deriveMasterKeyBytes(signatureHex, chainId, address);
|
|
@@ -3922,17 +4006,17 @@ async function deriveSpendingKeyFromSignature(signatureHex, chainId, address) {
|
|
|
3922
4006
|
}
|
|
3923
4007
|
function deriveViewingSecretKey(spendingKey) {
|
|
3924
4008
|
const ikm = bigintTo32Le(spendingKey);
|
|
3925
|
-
return hkdf2(
|
|
4009
|
+
return hkdf2(sha2564, ikm, void 0, IVK_DOMAIN, 32);
|
|
3926
4010
|
}
|
|
3927
4011
|
function deriveViewingPublicKey(ivsk) {
|
|
3928
4012
|
const ivskScalar = BigInt(toHex(ivsk)) % BABYJUB_SUBORDER || 1n;
|
|
3929
|
-
const ivkPoint =
|
|
3930
|
-
const packed =
|
|
4013
|
+
const ivkPoint = mulPointEscalar4(Base82, ivskScalar);
|
|
4014
|
+
const packed = packPoint3(ivkPoint);
|
|
3931
4015
|
return bigintTo32Le(packed);
|
|
3932
4016
|
}
|
|
3933
4017
|
function deriveOwnerPk(spendingKey) {
|
|
3934
4018
|
try {
|
|
3935
|
-
const pubPoint =
|
|
4019
|
+
const pubPoint = mulPointEscalar4(Base82, spendingKey);
|
|
3936
4020
|
return pubPoint[0];
|
|
3937
4021
|
} catch {
|
|
3938
4022
|
return 0n;
|
|
@@ -4245,7 +4329,7 @@ import {
|
|
|
4245
4329
|
WebArtifactProvider as WebArtifactProvider2
|
|
4246
4330
|
} from "@orbinum/proof-generator";
|
|
4247
4331
|
import { randomBytes as randomBytes3 } from "@noble/ciphers/utils.js";
|
|
4248
|
-
import { mulPointEscalar as
|
|
4332
|
+
import { mulPointEscalar as mulPointEscalar5, Base8 as Base83 } from "@zk-kit/baby-jubjub";
|
|
4249
4333
|
import { poseidon4 as poseidon44 } from "poseidon-lite";
|
|
4250
4334
|
|
|
4251
4335
|
// src/proof-generator/merkle.ts
|
|
@@ -4268,7 +4352,7 @@ async function generateUnshieldProof(inputs, options = {}) {
|
|
|
4268
4352
|
if (changeValue < 0n) {
|
|
4269
4353
|
throw new Error("changeValue must be >= 0.");
|
|
4270
4354
|
}
|
|
4271
|
-
const changeOwnerPubkey = inputs.changeOwnerPubkey ??
|
|
4355
|
+
const changeOwnerPubkey = inputs.changeOwnerPubkey ?? mulPointEscalar5(Base83, inputs.spendingKey)[0];
|
|
4272
4356
|
const changeBlinding = inputs.changeBlinding ?? (changeValue > 0n ? bytesToBigintLE(randomBytes3(32)) : 0n);
|
|
4273
4357
|
const changeCommitment = changeValue > 0n ? poseidon44([changeValue, inputs.assetId, changeOwnerPubkey, changeBlinding]) : 0n;
|
|
4274
4358
|
const circuitInputs = {
|
|
@@ -5191,12 +5275,14 @@ export {
|
|
|
5191
5275
|
decryptNoteRecord,
|
|
5192
5276
|
deriveMasterKeyBytes,
|
|
5193
5277
|
deriveOwnerPk,
|
|
5278
|
+
deriveSelfEphSk,
|
|
5194
5279
|
deriveSpendingKeyFromSignature,
|
|
5195
5280
|
deriveSpendingKeyMessage,
|
|
5196
5281
|
deriveStealthOwnerPk,
|
|
5197
5282
|
deriveStealthSk,
|
|
5198
5283
|
deriveVaultBlindKey,
|
|
5199
5284
|
deriveVaultKey,
|
|
5285
|
+
deriveViewTag,
|
|
5200
5286
|
deriveViewingPublicKey,
|
|
5201
5287
|
deriveViewingSecretKey,
|
|
5202
5288
|
encryptJson,
|
|
@@ -5234,6 +5320,7 @@ export {
|
|
|
5234
5320
|
randomBlinding,
|
|
5235
5321
|
recoverOwnerPkPoint,
|
|
5236
5322
|
selectNotes,
|
|
5323
|
+
selfEphWindow,
|
|
5237
5324
|
shortHash,
|
|
5238
5325
|
substrateSs58ToAccountIdHex,
|
|
5239
5326
|
substrateToEvm,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbinum/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Official TypeScript SDK for Orbinum.",
|
|
5
5
|
"author": "Orbinum",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@noble/ciphers": "2.2.0",
|
|
49
|
+
"@noble/curves": "^2.2.0",
|
|
49
50
|
"@noble/hashes": "2.2.0",
|
|
50
51
|
"@orbinum/proof-generator": "4.0.0",
|
|
51
52
|
"@polkadot-api/metadata-builders": "0.14.2",
|