机密资产(CA)
你可以使用Aptos
客户端的confidentialCoin
属性来与CA
进行交互
CA中的操作需要生成零知识证明(ZKPs),根据你的运行环境,需要定义范围证明
的计算方式.
对于Web环境,可以使用confidential-asset-wasm-bindings/confidential-asset-wasm-bindings
:
让我们准备范围证明生成并配置SDK使用它:
import initWasm, { batch_range_proof as batchRangeProof, batch_verify_proof as batchVerifyProof, range_proof as rangeProof, verify_proof as verifyProof,} from '@aptos-labs/confidential-asset-wasm-bindings/range-proofs'import { BatchRangeProofInputs, BatchVerifyRangeProofInputs, RangeProofInputs, VerifyRangeProofInputs,} from '@lukachi/aptos-labs-ts-sdk'
const RANGE_PROOF_WASM_URL = 'https://unpkg.com/@aptos-labs/confidential-asset-wasm-bindings@0.3.16/range-proofs/aptos_rp_wasm_bg.wasm'
export async function genBatchRangeZKP( opts: BatchRangeProofInputs,): Promise<{ proof: Uint8Array; commitments: Uint8Array[] }> { await initWasm({ module_or_path: RANGE_PROOF_WASM_URL })
const proof = batchRangeProof( new BigUint64Array(opts.v), opts.rs, opts.val_base, opts.rand_base, opts.num_bits, )
return { proof: proof.proof(), commitments: proof.comms(), }}
export async function verifyBatchRangeZKP( opts: BatchVerifyRangeProofInputs,): Promise<boolean> { await initWasm({ module_or_path: RANGE_PROOF_WASM_URL })
return batchVerifyProof( opts.proof, opts.comm, opts.val_base, opts.rand_base, opts.num_bits, )}
然后,只需将其放在应用的最顶部:
import { RangeProofExecutor } from '@aptos-labs/ts-sdk'
RangeProofExecutor.setGenBatchRangeZKP(genBatchRangeZKP);RangeProofExecutor.setVerifyBatchRangeZKP(verifyBatchRangeZKP);RangeProofExecutor.setGenerateRangeZKP(generateRangeZKP);RangeProofExecutor.setVerifyRangeZKP(verifyRangeZKP);
对于原生应用:
从这里生成android
和ios
绑定,并按需集成到你的应用中.
最后但同样重要的是:
要获取机密资产的”数值”余额,还需要解决离散对数问题(DLP). CA实现了Pollard’s Kangaroo方法来解决Ristretto曲线上的DLP. 来源
因此我们还需要初始化解密函数:
// Copyright © Aptos Foundation// SPDX-License-Identifier: Apache-2.0
import initWasm, { create_kangaroo, WASMKangaroo,} from '@aptos-labs/confidential-asset-wasm-bindings/pollard-kangaroo'import { ConfidentialAmount, TwistedEd25519PrivateKey, TwistedElGamal, TwistedElGamalCiphertext,} from '@lukachi/aptos-labs-ts-sdk'import { bytesToNumberLE } from '@noble/curves/abstract/utils'
const POLLARD_KANGAROO_WASM_URL = 'https://unpkg.com/@aptos-labs/confidential-asset-wasm-bindings@0.3.15/pollard-kangaroo/aptos_pollard_kangaroo_wasm_bg.wasm'
export async function createKangaroo(secret_size: number) { await initWasm({ module_or_path: POLLARD_KANGAROO_WASM_URL })
return create_kangaroo(secret_size)}
export const preloadTables = async () => { const kangaroo16 = await createKangaroo(16) const kangaroo32 = await createKangaroo(32) const kangaroo48 = await createKangaroo(48)
TwistedElGamal.setDecryptionFn(async pk => { if (bytesToNumberLE(pk) === 0n) return 0n
let result = kangaroo16.solve_dlp(pk, 500n)
if (!result) { result = kangaroo32.solve_dlp(pk, 1500n) }
if (!result) { result = kangaroo48.solve_dlp(pk) }
if (!result) throw new TypeError('Decryption failed')
return result })}
现在,将以下代码放在你的应用顶部:
const init = async () => { await preloadTables();}
对于原生应用,你可以在此生成android
和ios
绑定来代替WASM使用.
现在我们准备就绪.让我们定义Aptos客户端:
const APTOS_NETWORK: Network = NetworkToNetworkName[Network.TESTNET];const config = new AptosConfig({ network: APTOS_NETWORK });export const aptos = new Aptos(config);
创建解密密钥(DK)
Section titled “创建解密密钥(DK)”要与保密资产交互,首先需要创建一个唯一的密钥对.
生成新密钥:
const dk = TwistedEd25519PrivateKey.generate();
或导入现有密钥:
const dk = new TwistedEd25519PrivateKey("0x...");
你也可以使用签名
派生密钥(仅用于测试目的,勿在生产环境使用):
const user = Account.generate()
const signature = user.sign(TwistedEd25519PrivateKey.decryptionKeyDerivationMessage);
const dk = TwistedEd25519PrivateKey.fromSignature(signature);
接下来,你需要在合约中注册之前生成的加密密钥(EK):
export const registerConfidentialBalance = async ( account: Account, publicKeyHex: string, tokenAddress = "0x...",) => { const txBody = await aptos.confidentialAsset.deposit({ sender: account.accountAddress, to: AccountAddress.from(to), tokenAddress: tokenAddress, amount: amount, })
const txResponse = await aptos.signAndSubmitTransaction({ signer: user, transaction: userRegisterCBTxBody });
const txReceipt = await aptos.waitForTransaction({ transactionHash: txResponse.hash });
return txReceipt;}
检查用户是否已注册特定代币:
export const getIsAccountRegisteredWithToken = async ( account: Account, tokenAddress = "0x...",) => { const isRegistered = await aptos.confidentialAsset.hasUserRegistered({ accountAddress: account.accountAddress, tokenAddress: tokenAddress, })
return isRegistered}
假设你已经拥有代币.
以下代码会将代币存入你的保密余额:
export const depositConfidentialBalance = async ( account: Account, amount: bigint, to: string, tokenAddress = "0x...",) => { const txBody = await aptos.confidentialAsset.deposit({ sender: account.accountAddress, to: AccountAddress.from(to), tokenAddress: tokenAddress, amount: amount, }) // 签名并发送交易}
获取用户余额
Section titled “获取用户余额”存款后,让我们检查用户的余额.
const userConfidentialBalance = await aptos.confidentialAsset.getBalance({ accountAddress: user.accountAddress, tokenAddress: TOKEN_ADDRESS });```该方法返回用户的[`pending`和`actual`](confidential-asset#confidential-asset-store)保密余额,要[解密](confidential-asset#encryption-and-decryption)这些余额,可以使用`ConfidentialAmount`类
```typescriptexport const getConfidentialBalances = async ( account: Account, decryptionKeyHex: string, tokenAddress = "0x...",) => { const decryptionKey = new TwistedEd25519PrivateKey(decryptionKeyHex)
const { pending, actual } = await aptos.confidentialAsset.getBalance({ accountAddress: account.accountAddress, tokenAddress, })
try { const [confidentialAmountPending, confidentialAmountActual] = await Promise.all([ ConfidentialAmount.fromEncrypted(pending, decryptionKey), ConfidentialAmount.fromEncrypted(actual, decryptionKey), ])
return { pending: confidentialAmountPending, actual: confidentialAmountActual, } } catch (error) { return { pending: ConfidentialAmount.fromAmount(0n), actual: ConfidentialAmount.fromAmount(0n), } }}
当您向用户的保密余额存款后,可以看到例如pending
余额中有5n
,而actual
余额为0n
.
用户无法操作pending
余额,因此您可以将其结转到actual
余额.
为此,请使用aptos.confidentialAsset.rolloverPendingBalance
.
要同时处理标准化和rollover
操作,可以使用aptos.confidentialAsset.safeRolloverPendingCB
.
export const safelyRolloverConfidentialBalance = async ( account: Account, decryptionKeyHex: string, tokenAddress = "0x...",) => { const rolloverTxPayloads = await aptos.confidentialAsset.safeRolloverPendingCB({ sender: account.accountAddress, tokenAddress, decryptionKey: new TwistedEd25519PrivateKey(decryptionKeyHex), })
// 签名并发送批量交易}
通常您不需要显式调用标准化操作
如果您需要手动操作:
export const getIsBalanceNormalized = async ( account: Account, tokenAddress = "0x...",) => { const isNormalized = await aptos.confidentialAsset.isUserBalanceNormalized({ accountAddress: account.accountAddress, tokenAddress: tokenAddress, })
return isNormalized}
获取余额后,最终调用aptos.confidentialAsset.normalizeUserBalance
方法:
export const normalizeConfidentialBalance = async ( account: Account, decryptionKeyHex: string, encryptedPendingBalance: TwistedElGamalCiphertext[], amount: bigint, tokenAddress = "0x...",) => { const normalizeTx = await aptos.confidentialAsset.normalizeUserBalance({ tokenAddress, decryptionKey: new TwistedEd25519PrivateKey(decryptionKeyHex), unnormalizedEncryptedBalance: encryptedPendingBalance, balanceAmount: amount,
sender: account.accountAddress, })
// 签名并发送交易}
要将资产从机密余额中提现:
export const withdrawConfidentialBalance = async ( account: Account, receiver: string, decryptionKeyHex: string, withdrawAmount: bigint, encryptedActualBalance: TwistedElGamalCiphertext[], tokenAddress = '0x...',) => { const withdrawTx = await aptos.confidentialAsset.withdraw({ sender: account.accountAddress, to: receiver, tokenAddress, decryptionKey: decryptionKey, encryptedActualBalance, amountToWithdraw: withdrawAmount, })
// 签名并发送交易}
进行机密转账需要知道接收方的加密密钥和aptos
账户地址
假设您已有接收方账户地址,让我们获取其加密密钥:
export const getEkByAddr = async (addrHex: string, tokenAddress: string) => { return aptos.confidentialAsset.getEncryptionByAddr({ accountAddress: AccountAddress.from(addrHex), tokenAddress, })}
现在将所有步骤整合并进行转账:
export const transferConfidentialCoin = async ( account: Account, decryptionKeyHex: string, encryptedActualBalance: TwistedElGamalCiphertext[], amountToTransfer: bigint, recipientAddressHex: string, auditorsEncryptionKeyHexList: string[], tokenAddress = "0x...",) => { const decryptionKey = new TwistedEd25519PrivateKey(decryptionKeyHex)
const recipientEncryptionKeyHex = await getEkByAddr( recipientAddressHex, tokenAddress, )
const transferTx = await aptos.confidentialAsset.transferCoin({ senderDecryptionKey: decryptionKey, recipientEncryptionKey: new TwistedEd25519PublicKey( recipientEncryptionKeyHex, ), encryptedActualBalance: encryptedActualBalance, amountToTransfer, sender: account.accountAddress, tokenAddress, recipientAddress: recipientAddressHex, auditorEncryptionKeys: auditorsEncryptionKeyHexList.map( hex => new TwistedEd25519PublicKey(hex), ), })
// 签名并发送交易}
要进行密钥轮换,您需要创建新的解密密钥并使用aptos.confidentialAsset.rotateCBKey
现在让我们创建新的解密密钥并轮换加密密钥:
const balances = await getBalances(user.accountAddress.toString(), myDecryptionKey, TOKEN_ADDRESS);
const NEW_DECRYPTION_KEY = TwistedEd25519PrivateKey.generate();const keyRotationAndUnfreezeTxResponse = await ConfidentialCoin.safeRotateCBKey(aptos, user, { sender: user.accountAddress,
currDecryptionKey: currentDecryptionKey, newDecryptionKey: NEW_DECRYPTION_KEY,
currEncryptedBalance: balances.actual.amountEncrypted,
withUnfreezeBalance: true, // 如果您想在之后解冻余额 tokenAddress: TOKEN_ADDRESS,});
// 保存:新的解密密钥console.log(NEW_DECRYPTION_KEY.toString());
// 检查新的余额const newBalance = await getBalances(user.accountAddress.toString(), NEW_DECRYPTION_KEY, TOKEN_ADDRESS);
console.log(newBalance.pending.amount);console.log(newBalance.actual.amount);