Add composite crypto functions to provider and rewire remaining imports
Add 17 new provider-level functions (derivationToScalar, deriveViewTag, ecdhDecodeFull, computeCarrotSpendPubkey, randomScalar, etc.) that compose backend primitives. Rewire all consumer files to import through the crypto provider. Only internal JS point serialization (pointFromBytes/ pointToBytes) and source implementation files retain direct imports.
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
|
||||
import { hexToBytes, bytesToHex } from './address.js';
|
||||
import { pointFromBytes, pointToBytes } from './ed25519.js';
|
||||
import { blake2b, keccak256, scalarMultPoint } from './crypto/index.js';
|
||||
import { blake2b, keccak256, scalarMultBase, scalarMultPoint, pointAddCompressed, hashToPoint } from './crypto/index.js';
|
||||
|
||||
// Group order L for scalar reduction
|
||||
const L = (1n << 252n) + 27742317777372353535851937790883648493n;
|
||||
@@ -697,8 +697,6 @@ export function scanCarrotOutput(output, viewIncomingKey, accountSpendPubkey, in
|
||||
// Import additional ed25519 functions
|
||||
// ============================================================================
|
||||
|
||||
import { scalarMultBase, pointAddCompressed, hashToPoint } from './crypto/index.js';
|
||||
|
||||
// Group order L for scalar reduction (also defined at top for clarity)
|
||||
const L_ORDER = (1n << 252n) + 27742317777372353535851937790883648493n;
|
||||
|
||||
|
||||
+4
-2
@@ -4,8 +4,10 @@
|
||||
*/
|
||||
|
||||
import { hexToBytes, bytesToHex } from './address.js';
|
||||
import { computeCarrotSpendPubkey, computeCarrotMainAddressViewPubkey, computeCarrotAccountViewPubkey } from './ed25519.js';
|
||||
import { blake2b, keccak256, scalarMultBase } from './crypto/index.js';
|
||||
import {
|
||||
blake2b, keccak256, scalarMultBase,
|
||||
computeCarrotSpendPubkey, computeCarrotMainAddressViewPubkey, computeCarrotAccountViewPubkey,
|
||||
} from './crypto/index.js';
|
||||
|
||||
// Group order L for scalar reduction
|
||||
const L = (1n << 252n) + 27742317777372353535851937790883648493n;
|
||||
|
||||
+19
-1
@@ -12,15 +12,33 @@ export {
|
||||
setCryptoBackend,
|
||||
getCryptoBackend,
|
||||
getCurrentBackendType,
|
||||
keccak256,
|
||||
// Hashing
|
||||
keccak256, keccak256Hex, cnFastHash,
|
||||
blake2b,
|
||||
// Scalar ops
|
||||
scAdd, scSub, scMul, scMulAdd, scMulSub,
|
||||
scReduce32, scReduce64, scInvert, scCheck, scIsZero,
|
||||
scalarAdd,
|
||||
// Point ops
|
||||
scalarMultBase, scalarMultPoint, pointAddCompressed,
|
||||
pointSubCompressed, pointNegate, doubleScalarMultBase,
|
||||
isIdentity,
|
||||
// Constants
|
||||
getGeneratorG, getGeneratorT,
|
||||
// Random
|
||||
randomScalar,
|
||||
// Hash-to-point & key derivation
|
||||
hashToPoint, generateKeyImage, generateKeyDerivation,
|
||||
derivePublicKey, deriveSecretKey,
|
||||
derivationToScalar, deriveViewTag, deriveSubaddressPublicKey,
|
||||
computeSharedSecret,
|
||||
// Amount encryption/decryption
|
||||
ecdhDecode, ecdhDecodeFull, ecdhEncode,
|
||||
// Pedersen commitments
|
||||
commit, zeroCommit, genCommitmentMask,
|
||||
// CARROT key derivation
|
||||
computeCarrotSpendPubkey, computeCarrotAccountViewPubkey,
|
||||
computeCarrotMainAddressViewPubkey,
|
||||
} from './provider.js';
|
||||
|
||||
// Backends (for direct access / testing)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
import { JsCryptoBackend } from './backend-js.js';
|
||||
import { hexToBytes } from '../address.js';
|
||||
|
||||
let currentBackend = null;
|
||||
let backendType = 'js';
|
||||
@@ -100,3 +101,159 @@ export function deriveSecretKey(derivation, outputIndex, baseSec) { return getCr
|
||||
export function commit(amount, mask) { return getCryptoBackend().commit(amount, mask); }
|
||||
export function zeroCommit(amount) { return getCryptoBackend().zeroCommit(amount); }
|
||||
export function genCommitmentMask(sharedSecret) { return getCryptoBackend().genCommitmentMask(sharedSecret); }
|
||||
|
||||
// =============================================================================
|
||||
// Composite functions — built on top of backend primitives
|
||||
// =============================================================================
|
||||
|
||||
// Aliases
|
||||
export const cnFastHash = keccak256;
|
||||
|
||||
export function keccak256Hex(input) {
|
||||
const hash = keccak256(input);
|
||||
return Array.from(hash).map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
|
||||
// Constants
|
||||
const G_BYTES = new Uint8Array([
|
||||
0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
]);
|
||||
|
||||
const T_BYTES = new Uint8Array([
|
||||
0x96, 0x6f, 0xc6, 0x6b, 0x82, 0xcd, 0x56, 0xcf,
|
||||
0x85, 0xea, 0xec, 0x80, 0x1c, 0x42, 0x84, 0x5f,
|
||||
0x5f, 0x40, 0x88, 0x78, 0xd1, 0x56, 0x1e, 0x00,
|
||||
0xd3, 0xd7, 0xde, 0xd2, 0x79, 0x4d, 0x09, 0x4f,
|
||||
]);
|
||||
|
||||
export function getGeneratorG() { return new Uint8Array(G_BYTES); }
|
||||
export function getGeneratorT() { return new Uint8Array(T_BYTES); }
|
||||
|
||||
export function isIdentity(p) {
|
||||
if (p[0] !== 1) return false;
|
||||
for (let i = 1; i < 32; i++) {
|
||||
if (p[i] !== 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Random scalar: generate 64 random bytes, reduce mod L
|
||||
export function randomScalar() {
|
||||
let bytes64;
|
||||
if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.getRandomValues) {
|
||||
bytes64 = new Uint8Array(64);
|
||||
globalThis.crypto.getRandomValues(bytes64);
|
||||
} else {
|
||||
const { randomBytes } = require('crypto');
|
||||
bytes64 = new Uint8Array(randomBytes(64));
|
||||
}
|
||||
return scReduce64(bytes64);
|
||||
}
|
||||
|
||||
// Varint encoding (internal helper)
|
||||
function encodeVarint(n) {
|
||||
const bytes = [];
|
||||
while (n >= 0x80) {
|
||||
bytes.push((n & 0x7f) | 0x80);
|
||||
n >>>= 7;
|
||||
}
|
||||
bytes.push(n);
|
||||
return new Uint8Array(bytes);
|
||||
}
|
||||
|
||||
// Key derivation composites
|
||||
export function derivationToScalar(derivation, outputIndex) {
|
||||
if (typeof derivation === 'string') {
|
||||
derivation = hexToBytes(derivation);
|
||||
}
|
||||
const indexBytes = encodeVarint(outputIndex);
|
||||
const input = new Uint8Array(derivation.length + indexBytes.length);
|
||||
input.set(derivation);
|
||||
input.set(indexBytes, derivation.length);
|
||||
return scReduce32(keccak256(input));
|
||||
}
|
||||
|
||||
export function computeSharedSecret(derivation, outputIndex) {
|
||||
return derivationToScalar(derivation, outputIndex);
|
||||
}
|
||||
|
||||
export function deriveViewTag(derivation, outputIndex) {
|
||||
if (typeof derivation === 'string') {
|
||||
derivation = hexToBytes(derivation);
|
||||
}
|
||||
const salt = new TextEncoder().encode('view_tag');
|
||||
const indexBytes = encodeVarint(outputIndex);
|
||||
const input = new Uint8Array(salt.length + derivation.length + indexBytes.length);
|
||||
input.set(salt);
|
||||
input.set(derivation, salt.length);
|
||||
input.set(indexBytes, salt.length + derivation.length);
|
||||
return keccak256(input)[0];
|
||||
}
|
||||
|
||||
export function deriveSubaddressPublicKey(outputKey, derivation, outputIndex) {
|
||||
if (typeof outputKey === 'string') outputKey = hexToBytes(outputKey);
|
||||
if (typeof derivation === 'string') derivation = hexToBytes(derivation);
|
||||
const scalar = derivationToScalar(derivation, outputIndex);
|
||||
const scalarG = scalarMultBase(scalar);
|
||||
const scalarGNeg = new Uint8Array(scalarG);
|
||||
scalarGNeg[31] ^= 0x80;
|
||||
return pointAddCompressed(outputKey, scalarGNeg);
|
||||
}
|
||||
|
||||
// Amount decryption
|
||||
function genAmountEncodingFactor(sharedSecret) {
|
||||
const prefix = new TextEncoder().encode('amount');
|
||||
const input = new Uint8Array(prefix.length + sharedSecret.length);
|
||||
input.set(prefix);
|
||||
input.set(sharedSecret, prefix.length);
|
||||
return keccak256(input);
|
||||
}
|
||||
|
||||
export function ecdhDecode(encryptedAmount, sharedSecret) {
|
||||
if (typeof sharedSecret === 'string') sharedSecret = hexToBytes(sharedSecret);
|
||||
const encodingFactor = genAmountEncodingFactor(sharedSecret);
|
||||
const decrypted = new Uint8Array(8);
|
||||
for (let i = 0; i < 8; i++) decrypted[i] = encryptedAmount[i] ^ encodingFactor[i];
|
||||
let amount = 0n;
|
||||
for (let i = 7; i >= 0; i--) amount = (amount << 8n) | BigInt(decrypted[i]);
|
||||
return amount;
|
||||
}
|
||||
|
||||
export function ecdhDecodeFull(encryptedAmount, sharedSecret) {
|
||||
if (typeof sharedSecret === 'string') sharedSecret = hexToBytes(sharedSecret);
|
||||
const amount = ecdhDecode(encryptedAmount, sharedSecret);
|
||||
const mask = genCommitmentMask(sharedSecret);
|
||||
return { amount, mask };
|
||||
}
|
||||
|
||||
export function ecdhEncode(amount, sharedSecret) {
|
||||
if (typeof sharedSecret === 'string') sharedSecret = hexToBytes(sharedSecret);
|
||||
const encodingFactor = genAmountEncodingFactor(sharedSecret);
|
||||
const amountBytes = new Uint8Array(8);
|
||||
let n = BigInt(amount);
|
||||
for (let i = 0; i < 8; i++) { amountBytes[i] = Number(n & 0xffn); n >>= 8n; }
|
||||
const encrypted = new Uint8Array(8);
|
||||
for (let i = 0; i < 8; i++) encrypted[i] = amountBytes[i] ^ encodingFactor[i];
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
// CARROT key composites
|
||||
export function computeCarrotSpendPubkey(k_gi, k_ps) {
|
||||
const giG = scalarMultBase(k_gi);
|
||||
const psT = scalarMultPoint(k_ps, T_BYTES);
|
||||
return pointAddCompressed(giG, psT);
|
||||
}
|
||||
|
||||
export function computeCarrotAccountViewPubkey(k_vi, K_s) {
|
||||
return scalarMultPoint(k_vi, K_s);
|
||||
}
|
||||
|
||||
export function computeCarrotMainAddressViewPubkey(k_vi) {
|
||||
return scalarMultBase(k_vi);
|
||||
}
|
||||
|
||||
// Scalar add (simple wrapper around scAdd)
|
||||
export function scalarAdd(a, b) { return scAdd(a, b); }
|
||||
|
||||
+1
-2
@@ -8,8 +8,7 @@
|
||||
* Reference: cryptonote_basic/miner.cpp, cryptonote_basic/difficulty.cpp
|
||||
*/
|
||||
|
||||
import { cnFastHash } from './keccak.js';
|
||||
import { keccak256 } from './crypto/index.js';
|
||||
import { keccak256, cnFastHash } from './crypto/index.js';
|
||||
import { encodeVarint, serializeBlockHeader, HF_VERSION_ENABLE_ORACLE } from './transaction.js';
|
||||
|
||||
// =============================================================================
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
*/
|
||||
|
||||
import { bytesToHex, hexToBytes } from './address.js';
|
||||
import { computeCarrotSpendPubkey, computeCarrotMainAddressViewPubkey, computeCarrotAccountViewPubkey } from './ed25519.js';
|
||||
import { keccak256, scalarMultBase, scalarMultPoint, pointAddCompressed } from './crypto/index.js';
|
||||
import { scAdd } from './transaction.js';
|
||||
import {
|
||||
keccak256, scalarMultBase, scalarMultPoint, pointAddCompressed, scAdd,
|
||||
computeCarrotSpendPubkey, computeCarrotMainAddressViewPubkey, computeCarrotAccountViewPubkey,
|
||||
} from './crypto/index.js';
|
||||
import { MultisigAccount } from './multisig.js';
|
||||
import {
|
||||
makeViewBalanceSecret,
|
||||
|
||||
+1
-3
@@ -18,9 +18,7 @@
|
||||
*/
|
||||
|
||||
import { bytesToHex, hexToBytes } from './address.js';
|
||||
import { randomScalar } from './ed25519.js';
|
||||
import { keccak256, scalarMultBase, scalarMultPoint, pointAddCompressed } from './crypto/index.js';
|
||||
import { scReduce32, scAdd, scMul, scMulAdd } from './transaction.js';
|
||||
import { keccak256, scalarMultBase, scalarMultPoint, pointAddCompressed, randomScalar, scReduce32, scAdd, scMul, scMulAdd } from './crypto/index.js';
|
||||
import { encode as base58Encode, decode as base58Decode } from './base58.js';
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
* @module testnet/miner-tx
|
||||
*/
|
||||
|
||||
import { randomScalar } from '../ed25519.js';
|
||||
import { deriveViewTag } from '../scanning.js';
|
||||
import { scalarMultBase, generateKeyDerivation, derivePublicKey } from '../crypto/index.js';
|
||||
import { cnFastHash } from '../keccak.js';
|
||||
import {
|
||||
scalarMultBase, generateKeyDerivation, derivePublicKey,
|
||||
randomScalar, deriveViewTag, cnFastHash,
|
||||
} from '../crypto/index.js';
|
||||
import { serializeTxPrefix, encodeVarint } from '../transaction/serialization.js';
|
||||
import { bytesToHex, hexToBytes } from '../address.js';
|
||||
import { TX_TYPE, RCT_TYPE } from '../transaction/constants.js';
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import { RandomXContext } from '../randomx/index.js';
|
||||
import { constructBlockHashingBlob, findNonceOffset, setNonce, checkHash } from '../mining.js';
|
||||
import { getBlockHash, serializeBlockHeader } from '../block/serialization.js';
|
||||
import { cnFastHash } from '../keccak.js';
|
||||
import { cnFastHash } from '../crypto/index.js';
|
||||
import { serializeTxPrefix } from '../transaction/serialization.js';
|
||||
import { bytesToHex, hexToBytes } from '../address.js';
|
||||
import { createMinerTransaction, createEmptyProtocolTransaction } from './miner-tx.js';
|
||||
|
||||
+3
-4
@@ -10,12 +10,11 @@
|
||||
* Reference: Salvium/Monero src/ringct/rctOps.cpp, src/ringct/rctSigs.cpp
|
||||
*/
|
||||
|
||||
import { keccak256Hex } from './keccak.js';
|
||||
import { getGeneratorG, getGeneratorT } from './ed25519.js';
|
||||
import { derivationToScalar } from './scanning.js';
|
||||
import {
|
||||
keccak256, scalarMultBase, scalarMultPoint, pointAddCompressed,
|
||||
keccak256, keccak256Hex, scalarMultBase, scalarMultPoint, pointAddCompressed,
|
||||
getGeneratorG, getGeneratorT,
|
||||
generateKeyDerivation, derivePublicKey, deriveSecretKey,
|
||||
derivationToScalar,
|
||||
hashToPoint, generateKeyImage,
|
||||
} from './crypto/index.js';
|
||||
import { bytesToHex, hexToBytes } from './address.js';
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
*/
|
||||
|
||||
import { hexToBytes, bytesToHex } from '../address.js';
|
||||
import { getGeneratorT } from '../ed25519.js';
|
||||
import { edwardsToMontgomeryU, x25519ScalarMult } from '../carrot-scanning.js';
|
||||
import {
|
||||
blake2b, scalarMultBase, scalarMultPoint, pointAddCompressed,
|
||||
scReduce32, commit,
|
||||
scReduce32, commit, getGeneratorT,
|
||||
} from '../crypto/index.js';
|
||||
|
||||
import { CARROT_DOMAIN, CARROT_ENOTE_TYPE } from './constants.js';
|
||||
|
||||
+2
-7
@@ -11,13 +11,6 @@
|
||||
*/
|
||||
|
||||
import { WalletOutput, WalletTransaction } from './wallet-store.js';
|
||||
import {
|
||||
deriveViewTag,
|
||||
computeSharedSecret,
|
||||
ecdhDecodeFull,
|
||||
deriveSubaddressPublicKey,
|
||||
scalarAdd
|
||||
} from './scanning.js';
|
||||
import { cnSubaddressSecretKey, carrotIndexExtensionGenerator, carrotSubaddressScalar } from './subaddress.js';
|
||||
import { scanCarrotOutput, makeInputContext, makeInputContextCoinbase, generateCarrotKeyImage } from './carrot-scanning.js';
|
||||
import { parseTransaction, extractTxPubKey, extractPaymentId } from './transaction.js';
|
||||
@@ -26,6 +19,8 @@ import { TX_TYPE } from './wallet.js';
|
||||
import {
|
||||
generateKeyDerivation, derivePublicKey, deriveSecretKey,
|
||||
generateKeyImage, commit as pedersonCommit,
|
||||
deriveViewTag, computeSharedSecret, ecdhDecodeFull,
|
||||
deriveSubaddressPublicKey, scalarAdd,
|
||||
} from './crypto/index.js';
|
||||
|
||||
// ============================================================================
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@
|
||||
import { generateSeed, deriveKeys, deriveCarrotKeys } from './carrot.js';
|
||||
import { createAddress, parseAddress, hexToBytes, bytesToHex } from './address.js';
|
||||
import { cnSubaddress } from './subaddress.js';
|
||||
import { derivationToScalar, scanTransaction } from './scanning.js';
|
||||
import { generateKeyDerivation, deriveSecretKey, generateKeyImage, scalarMultBase } from './crypto/index.js';
|
||||
import { scanTransaction } from './scanning.js';
|
||||
import { generateKeyDerivation, deriveSecretKey, generateKeyImage, scalarMultBase, derivationToScalar } from './crypto/index.js';
|
||||
import {
|
||||
buildTransaction,
|
||||
buildStakeTransaction,
|
||||
|
||||
Reference in New Issue
Block a user