0xMiden / 0xMiden/wallet-adapter
Sending a note bricks the wallet if NoteMetadata sender is not the wallet account itself
- 主要语言
- TypeScript
- 星标
- 2
- 派生
- 9
- 平均合并
- 25 分钟
- 30 天内合并 PR
- 1
描述
### Packages versions
"@miden-sdk/miden-sdk": "0.14.10",
"@miden-sdk/miden-wallet-adapter": "0.14.3",
"@miden-sdk/react": "0.14.10",
### Bug description
Sending a note bricks the wallet if NoteMetadata sender is not the wallet account itself.
For example on p2ide like this:
```tsx
const noteBuilt = createP2IDENote({
from: notWalletAccountId,
to: whomeverAccountId,
assets: { token: fungibleFaucetId, amount: fungibleAmount },
type: NoteVisibility.Public,
reclaimAfter: P2IDE_RECLAIM_AFTER,
timelockUntil: P2IDE_TIMELOCK_UNTIL,
});
```
Closing / restarting browser does not help. Only reinstalling the wallet helps recover the account.
### How can this be reproduced?
Run the below example or run/take the code from here: https://github.com/0x0-mico/miden_consumable_notes/blob/another-sender/src/main.tsx
It will create a P2IDE note and try to send it to the network
Observe that this will brick the wallet:
It will be executing forever:
And wallet will "lose connection" to the node
```tsx
import {
AccountId,
createP2IDENote,
Note,
NoteArray,
NoteVisibility,
TransactionRequestBuilder,
} from '@miden-sdk/miden-sdk';
import {
ConsumeTransaction,
CustomTransaction,
MidenWalletAdapter,
MidenWalletName,
PrivateDataPermission,
Transaction,
TransactionType,
useWallet,
WalletAdapterNetwork,
WalletModalProvider,
WalletMultiButton,
WalletProvider,
} from '@miden-sdk/miden-wallet-adapter';
import '@miden-sdk/miden-wallet-adapter/styles.css';
import { MidenProvider, useMiden } from '@miden-sdk/react';
import { useEffect, useState } from 'react';
import { createRoot } from 'react-dom/client';
const midenWalletAdapters = [new MidenWalletAdapter({ appName: 'position-consume' })];
const poolAccountId = AccountId.fromBech32('mtst1azplz9r5fyw36grz8s92cenuns80075k');
/** Reclaim enabled (non-zero); timelock 0 = unlocked at any block height. */
const P2IDE_RECLAIM_AFTER = 1;
const P2IDE_TIMELOCK_UNTIL = 0;
function App() {
const { isReady } = useMiden();
const { connected, address, select, requestTransaction, requestAssets, requestConsume } = useWallet();
const [p2ideNote, setP2ideNote] = useState(null);
const [message, setMessage] = useState('');
useEffect(() => {
select(MidenWalletName);
}, [select]);
async function p2ideMain(step: 'open' | 'reclaim') {
if (!isReady || !connected || !address || !requestTransaction) {
setMessage('connect wallet first');
return;
}
try {
setMessage('');
if (step === 'open') {
if (!requestAssets) return;
const walletAssets = await requestAssets();
const firstWalletAsset = walletAssets[0];
if (!firstWalletAsset) {
setMessage('wallet has no assets');
return;
}
const fungibleFaucetId = AccountId.fromBech32(firstWalletAsset.faucetId);
const fungibleAmount = BigInt(firstWalletAsset.amount) / BigInt(10);
const noteBuilt = createP2IDENote({
from: poolAccountId,
to: poolAccountId,
assets: { token: fungibleFaucetId, amount: fungibleAmount },
type: NoteVisibility.Public,
reclaimAfter: P2IDE_RECLAIM_AFTER,
timelockUntil: P2IDE_TIMELOCK_UNTIL,
});
console.log("Note created.")
const openRequest = new TransactionRequestBuilder()
.withOwnOutputNotes(new NoteArray([noteBuilt]))
.build();
await requestTransaction(
new Transaction(
TransactionType.Custom,
new CustomTransaction(address, address, openRequest),
),
);
console.log("Note sent.")
setP2ideNote(noteBuilt);
setMessage(`sent P2IDE ${noteBuilt.id()} → pool`);
return;
}
if (!p2ideNote) {
setMessage('send P2IDE note first');
return;
}
const noteAsset = p2ideNote.assets().fungibleAssets()[0];
if (!noteAsset) {
setMessage('note has no fungible asset');
return;
}
await requestConsume?.(
new ConsumeTransaction(
noteAsset.faucetId().toString(),
p2ideNote.id().toString(),
'public',
Number(noteAsset.amount()),
p2ideNote.serialize(),
),
);
setMessage(`reclaimed ${p2ideNote.id()}`);
setP2ideNote(null);
} catch (error) {
setMessage(String(error));
}
}
return (
P2IDE repro — pool target {poolAccountId.toString()}
{connected && address &&
wallet: {address}
}p2ideMain('open')}>
send P2IDE note
p2ideMain('reclaim')}>
reclaim (ConsumeTransaction)
{p2ideNote &&
note: {p2ideNote.id().toString()}
}{p2ideNote &&
script root: {p2ideNote.script().root().toHex()}
}{message &&
{message}
});
}
createRoot(document.getElementById('root')!).render(
,
);
```
### Relevant log output
wallet logs out this:
```shell
INDEX.JS: Error in executeTransaction: Error: failed to execute transaction: invalid transaction request: account interface error: invalid sender account: 0x83f11474491d1d20623c0aac667c9c
at __wbg_Error_8c4e43fe74559d73 (Cargo-DKB2aRX-.js:23077:20)
at miden_client_web.wasm.wasm_bindgen[cb32f6f48015412b]::__wbindgen_error_new::__wbg_Error_8c4e43fe74559d73 externref shim (miden_client_web.d-qyt3-n.wasm:0xc1a487)
at miden_client_web.wasm.miden_client_web[8b5bfd558e02b233]::js_error_with_context:: (miden_client_web.d-qyt3-n.wasm:0xa4ee6c)
at miden_client_web.wasm.::execute_transaction::{closure#0} (miden_client_web.d-qyt3-n.wasm:0xaf47df)
at miden_client_web.wasm.wasm_bindgen_futures[203ad115dbfdc77c]::future_to_promise::<::execute_transaction::{closure#0}::_::__wasm_bindgen_generated_WebClient_executeTransaction::{closure#0}>::{closure#0}::{closure#0} (miden_client_web.d-qyt3-n.wasm:0x93423b)
at miden_client_web.wasm.::run (miden_client_web.d-qyt3-n.wasm:0xa8ae5c)
at miden_client_web.wasm.::spawn::::pull::{closure#0}>, ::pull::{closure#1}>>>::{closure#0}::{closure#0}>::{closure#0} (miden_client_web.d-qyt3-n.wasm:0xbb64a8)
at miden_client_web.wasm.wasm_bindgen[cb32f6f48015412b]::convert::closures::_::invoke:: (miden_client_web.d-qyt3-n.wasm:0xc19131)
at miden_client_web.wasm.wasm_bindgen[cb32f6f48015412b]::convert::closures::_::invoke:: externref shim (miden_client_web.d-qyt3-n.wasm:0xc1c4a3)
```
贡献指南
调研方向
The bug occurs when NoteMetadata sender differs from the wallet account. Examine the createP2IDENote function and the transaction execution flow in the wallet adapter. Look at the error 'invalid sender account' in the logs. Start by tracing the note creation and validation in the SDK, then check how the wallet adapter handles transaction requests with mismatched senders.
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- nodejs, react, typescript
- 领域
- blockchain
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 描述清楚
- 新手友好度
- 35/100