@orbinum/sdk 0.14.0 → 0.15.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 +52 -3
- package/dist/index.d.ts +52 -3
- package/dist/index.js +52 -23
- package/dist/index.mjs +51 -23
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1925,6 +1925,11 @@ declare class NoteBuilder {
|
|
|
1925
1925
|
* Layout (180 bytes, ECDH):
|
|
1926
1926
|
* nonce(12) || ciphertext+MAC(136) || ephPk_packed(32) = 180
|
|
1927
1927
|
*
|
|
1928
|
+
* View tag (memos built by SDK ≥ 0.15): nonce[0] = deriveViewTag(sharedSecret)
|
|
1929
|
+
* — see memo.ts. Layout and size are unchanged; legacy memos carry a random
|
|
1930
|
+
* byte there instead, so the filter is only sound at/after the wallet's
|
|
1931
|
+
* tagActivationLeaf.
|
|
1932
|
+
*
|
|
1928
1933
|
* Plaintext layout (120 bytes):
|
|
1929
1934
|
* 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
1935
|
*
|
|
@@ -2007,10 +2012,42 @@ declare const EncryptedMemo: {
|
|
|
2007
2012
|
* @param viewingSecretKey 32-byte HKDF viewing secret key from deriveViewingSecretKey().
|
|
2008
2013
|
*/
|
|
2009
2014
|
extractSharedSecret(memoBytes: Uint8Array, viewingSecretKey: Uint8Array): Uint8Array | null;
|
|
2015
|
+
/**
|
|
2016
|
+
* Cheap view-tag check: does memo nonce[0] match the tag derived from
|
|
2017
|
+
* `sharedSecret`? One SHA256 + one byte compare — no AEAD work.
|
|
2018
|
+
*
|
|
2019
|
+
* Only meaningful for memos built with view tags (commitments at/after
|
|
2020
|
+
* the wallet's tagActivationLeaf): a legacy memo carries a random byte
|
|
2021
|
+
* there and would false-negative 255/256 of the time.
|
|
2022
|
+
*/
|
|
2023
|
+
checkViewTag(memoBytes: Uint8Array, sharedSecret: Uint8Array): boolean;
|
|
2024
|
+
/**
|
|
2025
|
+
* Decrypt with an already-computed shared secret (from
|
|
2026
|
+
* extractSharedSecret), skipping the ECDH. Pair with checkViewTag for the
|
|
2027
|
+
* fast scan path: ECDH once → tag check → decrypt only on match.
|
|
2028
|
+
*/
|
|
2029
|
+
decryptWithSharedSecret(memoBytes: Uint8Array, commitment: Uint8Array, sharedSecret: Uint8Array): DecryptedMemo | null;
|
|
2010
2030
|
/** @internal */
|
|
2011
2031
|
_decrypt(memoBytes: Uint8Array, commitment: Uint8Array, viewingSecretKey: Uint8Array): DecryptedMemo | null;
|
|
2012
2032
|
};
|
|
2013
2033
|
|
|
2034
|
+
/**
|
|
2035
|
+
* Derive the 1-byte view tag (Monero-style fast-scan filter) from the ECDH
|
|
2036
|
+
* shared secret:
|
|
2037
|
+
* view_tag = SHA256("orbinum-view-tag-v1" || sharedSecret)[0]
|
|
2038
|
+
*
|
|
2039
|
+
* The sender embeds it as the memo's first nonce byte (nonce[0]); a scanner
|
|
2040
|
+
* that has computed the shared secret compares one byte and skips the AEAD
|
|
2041
|
+
* decrypt on mismatch — 255/256 of foreign notes. Safe to publish: without
|
|
2042
|
+
* the viewing key the shared secret is unknowable, so the byte reads as
|
|
2043
|
+
* uniform noise to any observer.
|
|
2044
|
+
*
|
|
2045
|
+
* Nonce safety: the encryption key is unique per note (see
|
|
2046
|
+
* deriveEncryptionKey), so each key encrypts exactly one message and the
|
|
2047
|
+
* remaining 11 random nonce bytes are more than enough.
|
|
2048
|
+
*/
|
|
2049
|
+
declare function deriveViewTag(sharedSecret: Uint8Array): number;
|
|
2050
|
+
|
|
2014
2051
|
/**
|
|
2015
2052
|
* NoteDecryptor
|
|
2016
2053
|
*
|
|
@@ -2034,6 +2071,17 @@ declare const EncryptedMemo: {
|
|
|
2034
2071
|
* deriveSpendingKeyFromSignature.
|
|
2035
2072
|
*/
|
|
2036
2073
|
declare function computeNullifier(commitment: bigint, spendingKey: bigint): bigint;
|
|
2074
|
+
interface TryDecryptOptions {
|
|
2075
|
+
/**
|
|
2076
|
+
* View-tag fast path: compute the ECDH shared secret once, compare the
|
|
2077
|
+
* 1-byte tag in memo nonce[0], and skip the AEAD decrypt on mismatch
|
|
2078
|
+
* (255/256 of foreign notes; `reason: 'view_tag_mismatch'`).
|
|
2079
|
+
*
|
|
2080
|
+
* Only enable for commitments at/after the wallet's tagActivationLeaf —
|
|
2081
|
+
* legacy memos carry a random byte there and would be silently dropped.
|
|
2082
|
+
*/
|
|
2083
|
+
viewTag?: boolean;
|
|
2084
|
+
}
|
|
2037
2085
|
/**
|
|
2038
2086
|
* Attempt to decrypt an on-chain commitment using the recipient's viewing secret key.
|
|
2039
2087
|
*
|
|
@@ -2047,13 +2095,14 @@ declare function computeNullifier(commitment: bigint, spendingKey: bigint): bigi
|
|
|
2047
2095
|
* @param spendingKey Spending key bigint (for nullifier computation).
|
|
2048
2096
|
* @param ownOwnerPk The viewer's global BabyJubJub Ax (ownerPk). Required for stealth detection.
|
|
2049
2097
|
* Pass 0n to disable stealth detection (legacy/own-note-only scanning).
|
|
2098
|
+
* @param opts See TryDecryptOptions (view-tag fast path).
|
|
2050
2099
|
*/
|
|
2051
|
-
declare function tryDecryptNote(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint): ZkNote | null;
|
|
2100
|
+
declare function tryDecryptNote(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint, opts?: TryDecryptOptions): ZkNote | null;
|
|
2052
2101
|
/**
|
|
2053
2102
|
* Like tryDecryptNote but also returns a human-readable reason for failure.
|
|
2054
2103
|
* Useful for debugging scan issues (wrong key, corrupted memo, commitment mismatch).
|
|
2055
2104
|
*/
|
|
2056
|
-
declare function tryDecryptNoteVerbose(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint): {
|
|
2105
|
+
declare function tryDecryptNoteVerbose(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint, opts?: TryDecryptOptions): {
|
|
2057
2106
|
note: ZkNote | null;
|
|
2058
2107
|
reason?: string;
|
|
2059
2108
|
};
|
|
@@ -4172,4 +4221,4 @@ interface ExtrinsicFailedData {
|
|
|
4172
4221
|
dispatch_info: DispatchInfo;
|
|
4173
4222
|
}
|
|
4174
4223
|
|
|
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 };
|
|
4224
|
+
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 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, 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, shortHash, substrateSs58ToAccountIdHex, substrateToEvm, toBase64, toHex, toTxResult, truncateMiddle, tryDecryptNote, tryDecryptNoteVerbose, vaultReplacer, vaultReviver };
|
package/dist/index.d.ts
CHANGED
|
@@ -1925,6 +1925,11 @@ declare class NoteBuilder {
|
|
|
1925
1925
|
* Layout (180 bytes, ECDH):
|
|
1926
1926
|
* nonce(12) || ciphertext+MAC(136) || ephPk_packed(32) = 180
|
|
1927
1927
|
*
|
|
1928
|
+
* View tag (memos built by SDK ≥ 0.15): nonce[0] = deriveViewTag(sharedSecret)
|
|
1929
|
+
* — see memo.ts. Layout and size are unchanged; legacy memos carry a random
|
|
1930
|
+
* byte there instead, so the filter is only sound at/after the wallet's
|
|
1931
|
+
* tagActivationLeaf.
|
|
1932
|
+
*
|
|
1928
1933
|
* Plaintext layout (120 bytes):
|
|
1929
1934
|
* 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
1935
|
*
|
|
@@ -2007,10 +2012,42 @@ declare const EncryptedMemo: {
|
|
|
2007
2012
|
* @param viewingSecretKey 32-byte HKDF viewing secret key from deriveViewingSecretKey().
|
|
2008
2013
|
*/
|
|
2009
2014
|
extractSharedSecret(memoBytes: Uint8Array, viewingSecretKey: Uint8Array): Uint8Array | null;
|
|
2015
|
+
/**
|
|
2016
|
+
* Cheap view-tag check: does memo nonce[0] match the tag derived from
|
|
2017
|
+
* `sharedSecret`? One SHA256 + one byte compare — no AEAD work.
|
|
2018
|
+
*
|
|
2019
|
+
* Only meaningful for memos built with view tags (commitments at/after
|
|
2020
|
+
* the wallet's tagActivationLeaf): a legacy memo carries a random byte
|
|
2021
|
+
* there and would false-negative 255/256 of the time.
|
|
2022
|
+
*/
|
|
2023
|
+
checkViewTag(memoBytes: Uint8Array, sharedSecret: Uint8Array): boolean;
|
|
2024
|
+
/**
|
|
2025
|
+
* Decrypt with an already-computed shared secret (from
|
|
2026
|
+
* extractSharedSecret), skipping the ECDH. Pair with checkViewTag for the
|
|
2027
|
+
* fast scan path: ECDH once → tag check → decrypt only on match.
|
|
2028
|
+
*/
|
|
2029
|
+
decryptWithSharedSecret(memoBytes: Uint8Array, commitment: Uint8Array, sharedSecret: Uint8Array): DecryptedMemo | null;
|
|
2010
2030
|
/** @internal */
|
|
2011
2031
|
_decrypt(memoBytes: Uint8Array, commitment: Uint8Array, viewingSecretKey: Uint8Array): DecryptedMemo | null;
|
|
2012
2032
|
};
|
|
2013
2033
|
|
|
2034
|
+
/**
|
|
2035
|
+
* Derive the 1-byte view tag (Monero-style fast-scan filter) from the ECDH
|
|
2036
|
+
* shared secret:
|
|
2037
|
+
* view_tag = SHA256("orbinum-view-tag-v1" || sharedSecret)[0]
|
|
2038
|
+
*
|
|
2039
|
+
* The sender embeds it as the memo's first nonce byte (nonce[0]); a scanner
|
|
2040
|
+
* that has computed the shared secret compares one byte and skips the AEAD
|
|
2041
|
+
* decrypt on mismatch — 255/256 of foreign notes. Safe to publish: without
|
|
2042
|
+
* the viewing key the shared secret is unknowable, so the byte reads as
|
|
2043
|
+
* uniform noise to any observer.
|
|
2044
|
+
*
|
|
2045
|
+
* Nonce safety: the encryption key is unique per note (see
|
|
2046
|
+
* deriveEncryptionKey), so each key encrypts exactly one message and the
|
|
2047
|
+
* remaining 11 random nonce bytes are more than enough.
|
|
2048
|
+
*/
|
|
2049
|
+
declare function deriveViewTag(sharedSecret: Uint8Array): number;
|
|
2050
|
+
|
|
2014
2051
|
/**
|
|
2015
2052
|
* NoteDecryptor
|
|
2016
2053
|
*
|
|
@@ -2034,6 +2071,17 @@ declare const EncryptedMemo: {
|
|
|
2034
2071
|
* deriveSpendingKeyFromSignature.
|
|
2035
2072
|
*/
|
|
2036
2073
|
declare function computeNullifier(commitment: bigint, spendingKey: bigint): bigint;
|
|
2074
|
+
interface TryDecryptOptions {
|
|
2075
|
+
/**
|
|
2076
|
+
* View-tag fast path: compute the ECDH shared secret once, compare the
|
|
2077
|
+
* 1-byte tag in memo nonce[0], and skip the AEAD decrypt on mismatch
|
|
2078
|
+
* (255/256 of foreign notes; `reason: 'view_tag_mismatch'`).
|
|
2079
|
+
*
|
|
2080
|
+
* Only enable for commitments at/after the wallet's tagActivationLeaf —
|
|
2081
|
+
* legacy memos carry a random byte there and would be silently dropped.
|
|
2082
|
+
*/
|
|
2083
|
+
viewTag?: boolean;
|
|
2084
|
+
}
|
|
2037
2085
|
/**
|
|
2038
2086
|
* Attempt to decrypt an on-chain commitment using the recipient's viewing secret key.
|
|
2039
2087
|
*
|
|
@@ -2047,13 +2095,14 @@ declare function computeNullifier(commitment: bigint, spendingKey: bigint): bigi
|
|
|
2047
2095
|
* @param spendingKey Spending key bigint (for nullifier computation).
|
|
2048
2096
|
* @param ownOwnerPk The viewer's global BabyJubJub Ax (ownerPk). Required for stealth detection.
|
|
2049
2097
|
* Pass 0n to disable stealth detection (legacy/own-note-only scanning).
|
|
2098
|
+
* @param opts See TryDecryptOptions (view-tag fast path).
|
|
2050
2099
|
*/
|
|
2051
|
-
declare function tryDecryptNote(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint): ZkNote | null;
|
|
2100
|
+
declare function tryDecryptNote(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint, opts?: TryDecryptOptions): ZkNote | null;
|
|
2052
2101
|
/**
|
|
2053
2102
|
* Like tryDecryptNote but also returns a human-readable reason for failure.
|
|
2054
2103
|
* Useful for debugging scan issues (wrong key, corrupted memo, commitment mismatch).
|
|
2055
2104
|
*/
|
|
2056
|
-
declare function tryDecryptNoteVerbose(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint): {
|
|
2105
|
+
declare function tryDecryptNoteVerbose(commitment: ScanCommitment, viewingSecretKey: Uint8Array, spendingKey: bigint, ownOwnerPk?: bigint, opts?: TryDecryptOptions): {
|
|
2057
2106
|
note: ZkNote | null;
|
|
2058
2107
|
reason?: string;
|
|
2059
2108
|
};
|
|
@@ -4172,4 +4221,4 @@ interface ExtrinsicFailedData {
|
|
|
4172
4221
|
dispatch_info: DispatchInfo;
|
|
4173
4222
|
}
|
|
4174
4223
|
|
|
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 };
|
|
4224
|
+
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 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, 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, shortHash, substrateSs58ToAccountIdHex, substrateToEvm, toBase64, toHex, toTxResult, truncateMiddle, tryDecryptNote, tryDecryptNoteVerbose, vaultReplacer, vaultReviver };
|
package/dist/index.js
CHANGED
|
@@ -79,6 +79,7 @@ __export(index_exports, {
|
|
|
79
79
|
deriveStealthSk: () => deriveStealthSk,
|
|
80
80
|
deriveVaultBlindKey: () => deriveVaultBlindKey,
|
|
81
81
|
deriveVaultKey: () => deriveVaultKey,
|
|
82
|
+
deriveViewTag: () => deriveViewTag,
|
|
82
83
|
deriveViewingPublicKey: () => deriveViewingPublicKey,
|
|
83
84
|
deriveViewingSecretKey: () => deriveViewingSecretKey,
|
|
84
85
|
encryptJson: () => encryptJson,
|
|
@@ -226,7 +227,7 @@ var SubstrateClient = class _SubstrateClient {
|
|
|
226
227
|
* Throws if the node does not respond within `timeoutMs`.
|
|
227
228
|
*/
|
|
228
229
|
static async connect(wsUrl, timeoutMs = 15e3) {
|
|
229
|
-
const provider = (0, import_ws.getWsProvider)(wsUrl);
|
|
230
|
+
const provider = (0, import_ws.getWsProvider)(wsUrl, { heartbeatTimeout: 3e4 });
|
|
230
231
|
const papi = (0, import_polkadot_api.createClient)(provider);
|
|
231
232
|
let timer;
|
|
232
233
|
try {
|
|
@@ -1262,6 +1263,7 @@ var BABYJUB_SUBORDER = 273603035897990940278080071815715938607681397215856725920
|
|
|
1262
1263
|
// src/shielded-pool/protocol/memo.ts
|
|
1263
1264
|
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
1264
1265
|
var KEY_DOMAIN = new TextEncoder().encode("orbinum-note-encryption-v1");
|
|
1266
|
+
var VIEW_TAG_DOMAIN = new TextEncoder().encode("orbinum-view-tag-v1");
|
|
1265
1267
|
var MEMO_PLAINTEXT_SIZE = 120;
|
|
1266
1268
|
function serializeMemo(value, ownerPk, blinding, assetId, counterpartyPk, circuitVersion) {
|
|
1267
1269
|
const buf = new Uint8Array(MEMO_PLAINTEXT_SIZE);
|
|
@@ -1282,6 +1284,12 @@ function deriveEncryptionKey(sharedSecret, commitment) {
|
|
|
1282
1284
|
h.update(KEY_DOMAIN);
|
|
1283
1285
|
return h.digest();
|
|
1284
1286
|
}
|
|
1287
|
+
function deriveViewTag(sharedSecret) {
|
|
1288
|
+
const h = import_sha2.sha256.create();
|
|
1289
|
+
h.update(VIEW_TAG_DOMAIN);
|
|
1290
|
+
h.update(sharedSecret);
|
|
1291
|
+
return h.digest()[0];
|
|
1292
|
+
}
|
|
1285
1293
|
|
|
1286
1294
|
// src/shielded-pool/protocol/EncryptedMemo.ts
|
|
1287
1295
|
var NONCE_SIZE = 12;
|
|
@@ -1358,6 +1366,7 @@ var EncryptedMemo = {
|
|
|
1358
1366
|
const sharedPoint = (0, import_baby_jubjub.mulPointEscalar)(ivkPoint, ephSkScalar);
|
|
1359
1367
|
sharedSecret = bigintTo32Le(sharedPoint[0]);
|
|
1360
1368
|
}
|
|
1369
|
+
nonce[0] = deriveViewTag(sharedSecret);
|
|
1361
1370
|
const encKey = deriveEncryptionKey(sharedSecret, commitment);
|
|
1362
1371
|
const cipher = (0, import_chacha.chacha20poly1305)(encKey, nonce);
|
|
1363
1372
|
const ciphertext = cipher.encrypt(plaintext);
|
|
@@ -1447,24 +1456,35 @@ var EncryptedMemo = {
|
|
|
1447
1456
|
const sharedPoint = (0, import_baby_jubjub.mulPointEscalar)(ephPkPoint, ivskScalar);
|
|
1448
1457
|
return bigintTo32Le(sharedPoint[0]);
|
|
1449
1458
|
},
|
|
1450
|
-
/**
|
|
1451
|
-
|
|
1459
|
+
/**
|
|
1460
|
+
* Cheap view-tag check: does memo nonce[0] match the tag derived from
|
|
1461
|
+
* `sharedSecret`? One SHA256 + one byte compare — no AEAD work.
|
|
1462
|
+
*
|
|
1463
|
+
* Only meaningful for memos built with view tags (commitments at/after
|
|
1464
|
+
* the wallet's tagActivationLeaf): a legacy memo carries a random byte
|
|
1465
|
+
* there and would false-negative 255/256 of the time.
|
|
1466
|
+
*/
|
|
1467
|
+
checkViewTag(memoBytes, sharedSecret) {
|
|
1468
|
+
if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return false;
|
|
1469
|
+
return memoBytes[0] === deriveViewTag(sharedSecret);
|
|
1470
|
+
},
|
|
1471
|
+
/**
|
|
1472
|
+
* Decrypt with an already-computed shared secret (from
|
|
1473
|
+
* extractSharedSecret), skipping the ECDH. Pair with checkViewTag for the
|
|
1474
|
+
* fast scan path: ECDH once → tag check → decrypt only on match.
|
|
1475
|
+
*/
|
|
1476
|
+
decryptWithSharedSecret(memoBytes, commitment, sharedSecret) {
|
|
1477
|
+
if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return null;
|
|
1452
1478
|
const nonce = memoBytes.slice(0, NONCE_SIZE);
|
|
1453
1479
|
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
1480
|
const encKey = deriveEncryptionKey(sharedSecret, commitment);
|
|
1467
1481
|
return parsePlaintext(nonce, ciphertextWithMac, encKey);
|
|
1482
|
+
},
|
|
1483
|
+
/** @internal */
|
|
1484
|
+
_decrypt(memoBytes, commitment, viewingSecretKey) {
|
|
1485
|
+
const sharedSecret = EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
1486
|
+
if (!sharedSecret) return null;
|
|
1487
|
+
return EncryptedMemo.decryptWithSharedSecret(memoBytes, commitment, sharedSecret);
|
|
1468
1488
|
}
|
|
1469
1489
|
};
|
|
1470
1490
|
|
|
@@ -3869,10 +3889,10 @@ var import_poseidon_lite2 = require("poseidon-lite");
|
|
|
3869
3889
|
function computeNullifier(commitment, spendingKey) {
|
|
3870
3890
|
return (0, import_poseidon_lite2.poseidon2)([commitment, spendingKey]);
|
|
3871
3891
|
}
|
|
3872
|
-
function tryDecryptNote(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n) {
|
|
3873
|
-
return tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk).note;
|
|
3892
|
+
function tryDecryptNote(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n, opts) {
|
|
3893
|
+
return tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk, opts).note;
|
|
3874
3894
|
}
|
|
3875
|
-
function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n) {
|
|
3895
|
+
function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n, opts) {
|
|
3876
3896
|
if (!commitment.encryptedMemo) return { note: null, reason: "no_memo" };
|
|
3877
3897
|
let commitmentBytes;
|
|
3878
3898
|
let memoBytes;
|
|
@@ -3888,21 +3908,29 @@ function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwn
|
|
|
3888
3908
|
reason: `memo_size_mismatch:got_${memoBytes.length}_expected_${ENCRYPTED_MEMO_SIZE}`
|
|
3889
3909
|
};
|
|
3890
3910
|
}
|
|
3891
|
-
|
|
3911
|
+
let sharedSecret = null;
|
|
3912
|
+
if (opts?.viewTag) {
|
|
3913
|
+
sharedSecret = EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
3914
|
+
if (!sharedSecret) return { note: null, reason: "stealth_shared_secret_failed" };
|
|
3915
|
+
if (!EncryptedMemo.checkViewTag(memoBytes, sharedSecret)) {
|
|
3916
|
+
return { note: null, reason: "view_tag_mismatch" };
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
const plaintext = sharedSecret ? EncryptedMemo.decryptWithSharedSecret(memoBytes, commitmentBytes, sharedSecret) : EncryptedMemo.decrypt(memoBytes, commitmentBytes, viewingSecretKey);
|
|
3892
3920
|
if (!plaintext) return { note: null, reason: "decrypt_failed:wrong_key_or_corrupt_mac" };
|
|
3893
3921
|
let effectiveOwnerPk = plaintext.ownerPk;
|
|
3894
3922
|
let effectiveSpendingKey = spendingKey;
|
|
3895
3923
|
if (ownOwnerPk !== 0n && plaintext.ownerPk !== ownOwnerPk) {
|
|
3896
|
-
const
|
|
3897
|
-
if (!
|
|
3924
|
+
const ss = sharedSecret ?? EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
3925
|
+
if (!ss) return { note: null, reason: "stealth_shared_secret_failed" };
|
|
3898
3926
|
const ownPkPoint = recoverOwnerPkPoint(ownOwnerPk);
|
|
3899
3927
|
if (!ownPkPoint) return { note: null, reason: "stealth_invalid_own_owner_pk" };
|
|
3900
|
-
const stealthOwnerPk = deriveStealthOwnerPk(
|
|
3928
|
+
const stealthOwnerPk = deriveStealthOwnerPk(ss, ownOwnerPk, ownPkPoint);
|
|
3901
3929
|
if (stealthOwnerPk !== plaintext.ownerPk) {
|
|
3902
3930
|
return { note: null, reason: "commitment_mismatch" };
|
|
3903
3931
|
}
|
|
3904
3932
|
effectiveOwnerPk = stealthOwnerPk;
|
|
3905
|
-
effectiveSpendingKey = deriveStealthSk(
|
|
3933
|
+
effectiveSpendingKey = deriveStealthSk(ss, ownOwnerPk, spendingKey);
|
|
3906
3934
|
}
|
|
3907
3935
|
const recomputed = (0, import_poseidon_lite2.poseidon4)([
|
|
3908
3936
|
plaintext.value,
|
|
@@ -5303,6 +5331,7 @@ var import_polkadot_api4 = require("polkadot-api");
|
|
|
5303
5331
|
deriveStealthSk,
|
|
5304
5332
|
deriveVaultBlindKey,
|
|
5305
5333
|
deriveVaultKey,
|
|
5334
|
+
deriveViewTag,
|
|
5306
5335
|
deriveViewingPublicKey,
|
|
5307
5336
|
deriveViewingSecretKey,
|
|
5308
5337
|
encryptJson,
|
package/dist/index.mjs
CHANGED
|
@@ -95,7 +95,7 @@ var SubstrateClient = class _SubstrateClient {
|
|
|
95
95
|
* Throws if the node does not respond within `timeoutMs`.
|
|
96
96
|
*/
|
|
97
97
|
static async connect(wsUrl, timeoutMs = 15e3) {
|
|
98
|
-
const provider = getWsProvider(wsUrl);
|
|
98
|
+
const provider = getWsProvider(wsUrl, { heartbeatTimeout: 3e4 });
|
|
99
99
|
const papi = createClient(provider);
|
|
100
100
|
let timer;
|
|
101
101
|
try {
|
|
@@ -1131,6 +1131,7 @@ var BABYJUB_SUBORDER = 273603035897990940278080071815715938607681397215856725920
|
|
|
1131
1131
|
// src/shielded-pool/protocol/memo.ts
|
|
1132
1132
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
1133
1133
|
var KEY_DOMAIN = new TextEncoder().encode("orbinum-note-encryption-v1");
|
|
1134
|
+
var VIEW_TAG_DOMAIN = new TextEncoder().encode("orbinum-view-tag-v1");
|
|
1134
1135
|
var MEMO_PLAINTEXT_SIZE = 120;
|
|
1135
1136
|
function serializeMemo(value, ownerPk, blinding, assetId, counterpartyPk, circuitVersion) {
|
|
1136
1137
|
const buf = new Uint8Array(MEMO_PLAINTEXT_SIZE);
|
|
@@ -1151,6 +1152,12 @@ function deriveEncryptionKey(sharedSecret, commitment) {
|
|
|
1151
1152
|
h.update(KEY_DOMAIN);
|
|
1152
1153
|
return h.digest();
|
|
1153
1154
|
}
|
|
1155
|
+
function deriveViewTag(sharedSecret) {
|
|
1156
|
+
const h = sha256.create();
|
|
1157
|
+
h.update(VIEW_TAG_DOMAIN);
|
|
1158
|
+
h.update(sharedSecret);
|
|
1159
|
+
return h.digest()[0];
|
|
1160
|
+
}
|
|
1154
1161
|
|
|
1155
1162
|
// src/shielded-pool/protocol/EncryptedMemo.ts
|
|
1156
1163
|
var NONCE_SIZE = 12;
|
|
@@ -1227,6 +1234,7 @@ var EncryptedMemo = {
|
|
|
1227
1234
|
const sharedPoint = mulPointEscalar(ivkPoint, ephSkScalar);
|
|
1228
1235
|
sharedSecret = bigintTo32Le(sharedPoint[0]);
|
|
1229
1236
|
}
|
|
1237
|
+
nonce[0] = deriveViewTag(sharedSecret);
|
|
1230
1238
|
const encKey = deriveEncryptionKey(sharedSecret, commitment);
|
|
1231
1239
|
const cipher = chacha20poly1305(encKey, nonce);
|
|
1232
1240
|
const ciphertext = cipher.encrypt(plaintext);
|
|
@@ -1316,24 +1324,35 @@ var EncryptedMemo = {
|
|
|
1316
1324
|
const sharedPoint = mulPointEscalar(ephPkPoint, ivskScalar);
|
|
1317
1325
|
return bigintTo32Le(sharedPoint[0]);
|
|
1318
1326
|
},
|
|
1319
|
-
/**
|
|
1320
|
-
|
|
1327
|
+
/**
|
|
1328
|
+
* Cheap view-tag check: does memo nonce[0] match the tag derived from
|
|
1329
|
+
* `sharedSecret`? One SHA256 + one byte compare — no AEAD work.
|
|
1330
|
+
*
|
|
1331
|
+
* Only meaningful for memos built with view tags (commitments at/after
|
|
1332
|
+
* the wallet's tagActivationLeaf): a legacy memo carries a random byte
|
|
1333
|
+
* there and would false-negative 255/256 of the time.
|
|
1334
|
+
*/
|
|
1335
|
+
checkViewTag(memoBytes, sharedSecret) {
|
|
1336
|
+
if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return false;
|
|
1337
|
+
return memoBytes[0] === deriveViewTag(sharedSecret);
|
|
1338
|
+
},
|
|
1339
|
+
/**
|
|
1340
|
+
* Decrypt with an already-computed shared secret (from
|
|
1341
|
+
* extractSharedSecret), skipping the ECDH. Pair with checkViewTag for the
|
|
1342
|
+
* fast scan path: ECDH once → tag check → decrypt only on match.
|
|
1343
|
+
*/
|
|
1344
|
+
decryptWithSharedSecret(memoBytes, commitment, sharedSecret) {
|
|
1345
|
+
if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return null;
|
|
1321
1346
|
const nonce = memoBytes.slice(0, NONCE_SIZE);
|
|
1322
1347
|
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
1348
|
const encKey = deriveEncryptionKey(sharedSecret, commitment);
|
|
1336
1349
|
return parsePlaintext(nonce, ciphertextWithMac, encKey);
|
|
1350
|
+
},
|
|
1351
|
+
/** @internal */
|
|
1352
|
+
_decrypt(memoBytes, commitment, viewingSecretKey) {
|
|
1353
|
+
const sharedSecret = EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
1354
|
+
if (!sharedSecret) return null;
|
|
1355
|
+
return EncryptedMemo.decryptWithSharedSecret(memoBytes, commitment, sharedSecret);
|
|
1337
1356
|
}
|
|
1338
1357
|
};
|
|
1339
1358
|
|
|
@@ -3741,10 +3760,10 @@ import { poseidon2 as poseidon22, poseidon4 as poseidon42 } from "poseidon-lite"
|
|
|
3741
3760
|
function computeNullifier(commitment, spendingKey) {
|
|
3742
3761
|
return poseidon22([commitment, spendingKey]);
|
|
3743
3762
|
}
|
|
3744
|
-
function tryDecryptNote(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n) {
|
|
3745
|
-
return tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk).note;
|
|
3763
|
+
function tryDecryptNote(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n, opts) {
|
|
3764
|
+
return tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk, opts).note;
|
|
3746
3765
|
}
|
|
3747
|
-
function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n) {
|
|
3766
|
+
function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwnerPk = 0n, opts) {
|
|
3748
3767
|
if (!commitment.encryptedMemo) return { note: null, reason: "no_memo" };
|
|
3749
3768
|
let commitmentBytes;
|
|
3750
3769
|
let memoBytes;
|
|
@@ -3760,21 +3779,29 @@ function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwn
|
|
|
3760
3779
|
reason: `memo_size_mismatch:got_${memoBytes.length}_expected_${ENCRYPTED_MEMO_SIZE}`
|
|
3761
3780
|
};
|
|
3762
3781
|
}
|
|
3763
|
-
|
|
3782
|
+
let sharedSecret = null;
|
|
3783
|
+
if (opts?.viewTag) {
|
|
3784
|
+
sharedSecret = EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
3785
|
+
if (!sharedSecret) return { note: null, reason: "stealth_shared_secret_failed" };
|
|
3786
|
+
if (!EncryptedMemo.checkViewTag(memoBytes, sharedSecret)) {
|
|
3787
|
+
return { note: null, reason: "view_tag_mismatch" };
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
const plaintext = sharedSecret ? EncryptedMemo.decryptWithSharedSecret(memoBytes, commitmentBytes, sharedSecret) : EncryptedMemo.decrypt(memoBytes, commitmentBytes, viewingSecretKey);
|
|
3764
3791
|
if (!plaintext) return { note: null, reason: "decrypt_failed:wrong_key_or_corrupt_mac" };
|
|
3765
3792
|
let effectiveOwnerPk = plaintext.ownerPk;
|
|
3766
3793
|
let effectiveSpendingKey = spendingKey;
|
|
3767
3794
|
if (ownOwnerPk !== 0n && plaintext.ownerPk !== ownOwnerPk) {
|
|
3768
|
-
const
|
|
3769
|
-
if (!
|
|
3795
|
+
const ss = sharedSecret ?? EncryptedMemo.extractSharedSecret(memoBytes, viewingSecretKey);
|
|
3796
|
+
if (!ss) return { note: null, reason: "stealth_shared_secret_failed" };
|
|
3770
3797
|
const ownPkPoint = recoverOwnerPkPoint(ownOwnerPk);
|
|
3771
3798
|
if (!ownPkPoint) return { note: null, reason: "stealth_invalid_own_owner_pk" };
|
|
3772
|
-
const stealthOwnerPk = deriveStealthOwnerPk(
|
|
3799
|
+
const stealthOwnerPk = deriveStealthOwnerPk(ss, ownOwnerPk, ownPkPoint);
|
|
3773
3800
|
if (stealthOwnerPk !== plaintext.ownerPk) {
|
|
3774
3801
|
return { note: null, reason: "commitment_mismatch" };
|
|
3775
3802
|
}
|
|
3776
3803
|
effectiveOwnerPk = stealthOwnerPk;
|
|
3777
|
-
effectiveSpendingKey = deriveStealthSk(
|
|
3804
|
+
effectiveSpendingKey = deriveStealthSk(ss, ownOwnerPk, spendingKey);
|
|
3778
3805
|
}
|
|
3779
3806
|
const recomputed = poseidon42([
|
|
3780
3807
|
plaintext.value,
|
|
@@ -5197,6 +5224,7 @@ export {
|
|
|
5197
5224
|
deriveStealthSk,
|
|
5198
5225
|
deriveVaultBlindKey,
|
|
5199
5226
|
deriveVaultKey,
|
|
5227
|
+
deriveViewTag,
|
|
5200
5228
|
deriveViewingPublicKey,
|
|
5201
5229
|
deriveViewingSecretKey,
|
|
5202
5230
|
encryptJson,
|