تست بلاکچین و dApp فقط Unit Test یک Smart Contract یا اندازهگیری TPS نیست. محصول واقعی از Wallet/Signer، Frontend و Backend، RPC/Node، Mempool، Consensus/Finality، Contract و Proxy، Event indexer، Oracle/Bridge، پایگاهداده خارج زنجیره و Governance ساخته میشود. تراکنش ممکن است Signed ولی Broadcastنشده، Pending، Dropped، Replaced، Reverted، Included، Reorgشده یا Finalized باشد؛ اگر Oracle تست این حالتها را یکی بداند، نتیجه سبز میتواند سیستم مالی نادرستی را پنهان کند.
این صفحه مالک چرخه تست سیستمهای Blockchain/dApp است: Chain/Threat/Trust Contract → Transaction state → Contract invariants → Wallet/RPC/Indexer → Oracle/Bridge/Upgrade → Performance/Operations → Off-chain reconciliation. الگوهای عمومی سیستم توزیعشده در تست سیستمهای توزیعشده، اصول امنیت در راهنمای تست امنیت و دفترکل/تراکنش مالی در تست فینتک مالکیت جدا دارند؛ اینجا همان مفاهیم را روی مرزهای Chain اعمال میکنیم.
پاسخ کوتاه: تست بلاکچین چیست؟
فرایند آزمون System و Protocol Contract یک برنامه مبتنی بر دفترکل توزیعشده است: آیا تراکنش، State transition، Event، امضا، مجوز، دارایی، Fee، Finality، Upgrade و هماهنگی On-chain/Off-chain طبق Specification و Threat model رفتار میکنند؟ «Blockchain» یک محصول واحد نیست؛ Public/Permissioned، Account/UTXO، L1/L2، EVM/non-EVM و Finality modelهای مختلف Oracle متفاوت دارند.
اصل QA: هش معتبر فقط میگوید Bytes مورد بررسی با Commitment برابرند؛ نمیگوید داده ابتدا درست، کامل، قانونی، مجاز یا متعلق به Run صحیح بوده است. Consensus نیز توافق Participantها بر State transition است، نه Oracle حقیقت جهان بیرون.
اول Chain Contract را بنویسید
Blockchain System Test Contract network/protocol: chain ID, client(s), version/fork, L1/L2, consensus/finality deployment: contract/proxy/implementation addresses + bytecode/source/compiler assets/units: native/token, decimals, rounding, max/min, zero-address rules actors/trust: user, signer, relayer, admin, guardian, oracle, bridge, validator transaction states: created→signed→broadcast→pending→included→safe/finalized replacement/reorg: nonce, fee bump, dropped, reverted, removed log, replay contract invariants: supply/balance/authorization/state-machine/conservation off-chain boundary: indexer, DB, queue, cache, ledger, notification, reconciliation external dependencies: RPC, wallet, oracle, bridge, explorer, sequencer upgrade/governance: proxy pattern, storage layout, timelock, quorum, pause/rollback security/privacy: keys, signing intent, metadata, front-running/MEV assumptions performance/cost: workload, gas/fee, block limit, rate/quota, finality latency environment/data: local/fork/testnet, snapshot, funded accounts, reset and faucet evidence: tx/receipt/log/block/state roots + app correlation + redaction limits: exactly what local/fork/testnet cannot prove
مدلهای Blockchain را قاطی نکنید
| مدل | سؤال ویژه | چیزی که تعمیم نمییابد |
|---|---|---|
| Public permissionless L1 | fee، mempool، reorg/finality، adversarial participants | Governance و identity شبکه خصوصی |
| Permissioned DLT | membership، endorsement، channel/privacy، node policy | Gas/MEV/public validator assumptions |
| L2/Rollup | sequencer، batch، proof/challenge، L1 settlement، withdrawal | L1 finality مستقیم |
| Bridge/Cross-chain | message identity، source/destination finality، replay، relayer | Atomicity یک Chain |
| Account-based/EVM | nonce، gas، contract call/storage/log | UTXO selection/change rules |
| UTXO | input ownership، double-spend، change، script | Account nonce/storage semantics |
معماری dApp را انتهابهانتها ببینید
User intent → Frontend / wallet connect / chain selection → transaction construction / simulation / approval → signer / key / hardware / signature → RPC / relayer / bundler / mempool → block inclusion / execution / receipt / logs → safe/finalized or removed/reorged → indexer / queue / off-chain DB & ledger → notification / UI status / reconciliation → oracle / bridge / governance / upgrade paths
Unit contract میتواند Pass باشد ولی Frontend Address یا chain ID اشتباه امضا کند؛ Receipt موفق باشد ولی Indexer Event را دوبار مصرف کند؛ Contract Event درست باشد ولی Backend مقدار decimal را غلط تبدیل کند. هر Arrow یک Interface، identity و failure mode مستقل دارد.
چرخه تراکنش را State machine کنید
مستند رسمی Ethereum درباره Transactions تراکنش را Instruction امضاشده و مسیر آن را از Hash/Broadcast/Pool تا Inclusion و سپس Justified/Finalized شرح میدهد. این منبع برای Ethereum است و به همه Chainها تعمیم مستقیم ندارد؛ Stateها و Finality دقیق Network هدف را از Specification همان Protocol بگیرید.
| State | Oracle | UI/Backend رفتار |
|---|---|---|
| Draft/Unsigned | intent، recipient، amount، chain، calldata | هیچ اثر مالی/ثبت نهایی |
| Signed | signature/signer/nonce/chain replay domain | هنوز Broadcast تضمین نیست |
| Broadcast | RPC accepted + local request identity | Submitted، نه Success |
| Pending | pool/nonce/status با timeout | Retry کور ممنوع |
| Replaced/Dropped | same nonce/new hash یا absence policy | پیوند و resolution روشن |
| Included success | receipt status + block/hash + state/log effects | Provisional طبق risk/finality |
| Included revert | receipt failure/revert reason/zero intended effect | Fail؛ Fee ممکن است مصرف شود |
| Removed/Reorged | block/log no longer canonical؛ removed event | Compensate/revert provisional state |
| Safe/Finalized | Network-specific tag/checkpoint | Final business transition طبق Contract |
Transaction identity فقط Hash نیست
برای EVM-style flow، Identity عملی شامل chainId + sender + nonce برای Intent/Replacement، txHash برای نسخه امضاشده، و blockHash + transactionIndex برای Inclusion است. Event identity معمولاً chainId + txHash + logIndex است، اما Reorg میتواند همان Logical event را در Block دیگری دوباره ظاهر کند. Correlation تجاری Order/Payment/Withdrawal را جدا نگه دارید.
JSON-RPC Latest، Safe و Finalized یکسان نیستند
Ethereum JSON-RPC API برای Queryهای State، Block tagهای latest، safe، finalized و pending را تفکیک میکند؛ Log حذفشده در Reorg نیز میتواند removed=true داشته باشد. Test double و Indexer شما باید این تفاوت را بسازند؛ Mockی که همه Queryها را یک State ثابت برمیگرداند، Reorg/Finality logic را آزمایش نمیکند.
Oracle چندلایه تراکنش
| لایه | Evidence | خطای قابلکشف |
|---|---|---|
| Intent | user-visible recipient/amount/unit/chain/action | blind signing و wrong chain |
| Envelope | sender/nonce/fee/data/signature domain | replay/replacement/encoding |
| Receipt | status، gas used، block/tx identity | revert یا wrong inclusion |
| Contract state | storage/view queries در block مشخص | Event درست، State غلط |
| Events | address/topic/data/log index/removed | missing/duplicate/reorg |
| Asset invariant | balance/supply/conservation/rounding | mint/burn/decimal loss |
| Off-chain | DB/ledger/queue/indexer idempotency | double credit/stale UI |
| Finality | canonical safe/finalized checkpoint | premature settlement |
| Reconciliation | On-chain vs business ledger and exceptions | silent divergence |
آزمایش بازتولیدپذیر: Duplicate + Reorg + Finality
یک Fixture نویسندهساخته و بدون Dependency با Node.js ۲۴.۱۸.۰ اجرا کردیم. Stream شامل Event با ۱۲۰ واحد ساختگی، Delivery تکراری همان Log، سپس removed=true در Reorg، Inclusion دوباره در Block جدید و Signal Finalized بود. مصرفکننده ساده هر Log غیرRemoved را نهایی شمرد؛ مصرفکننده دوم با Event identity، وضعیت Provisional/Removed/Finalized و Idempotency کار کرد.
eventCount = 6 NAIVE CONSUMER credited = 360 reason = duplicate delivery + old inclusion + re-inclusion counted as final REORG-AWARE CONSUMER identity = 31337:0xaaa:0 old block 0xb100 → removed new block 0xb102 → provisional → finalized finalized = 120 provisional = 0 expected canonical finalized amount = 120
این برنامه Client اتریوم، شبیهسازی Consensus، Wallet، Contract، RPC Provider یا Trace واقعی Chain نیست. Hashها، Eventها، Finality signal و Token unitها کاملاً ساختگیاند و Fork، Validator، Fee، Signature، Nonce replacement، Bridge و Economic security را مدل نمیکنند. فقط مکانیک Delivery تکراری، State موقت، Reverse کردن Removed log و Finalization صریح را نشان میدهد.
Smart Contract را با Example تنها تست نکنید
راهنمای رسمی Ethereum برای تست Smart Contract ترکیب Unit، Integration، Static، Property/Fuzz، Manual review، Audit و Bug bounty را مطرح میکند و صریحاً غیاب Bug را تضمینشده نمیداند. Tool suite را با Contract/language/chain/version خود Tailor کنید؛ فهرست ابزار، Strategy نیست.
| Technique | سؤال | محدودیت |
|---|---|---|
| Unit/Example | Function/transition برای موارد مشخص | Path/inputهای نانوشته |
| Integration/Fork | Cross-contract و State وابستگی | Fork، Production آینده/MEV/latency نیست |
| Property/Fuzz | Invariant زیر Sequence/Inputهای بسیار | Property/Generator ناقص |
| Stateful fuzz | Sequence role/action و interleaving | State-space و shrink/replay |
| Static analysis | Pattern/pathهای مشکوک | false positive/negative |
| Symbolic/Formal | Property روی Model/assumptions | Specification gap و محیط بیرونی |
| Manual review/Audit | Design/context/attack path | snapshot، scope و عدم تضمین |
| Bug bounty | تنوع adversarial پس از آمادگی | جایگزین tests/audit نیست |
Invariant از Test case مهمتر است
- جمع داراییهای حسابها و escrow طبق Rule با supply/mint/burn سازگار است.
- هیچ Actor بدون Role/Allowance/Signature مجاز State حساس را تغییر نمیدهد.
- یک Logical intent بیش از یک Business effect ایجاد نمیکند.
- Pause، limit و timelock فقط Actor/Scope/زمان تعریفشده را محدود میکنند.
- Sequence نامعتبر State machine رد و State/asset حفظ میشود.
- Rounding/decimals در مرز min/max/zero ارزش ایجاد یا نابود نمیکند.
- Failure در External call اثر جزئی ناخواسته باقی نمیگذارد.
- Upgrade، State موجود و Invariantها را حفظ یا Migration صریح دارد.
- Eventهای لازم با State واقعی سازگارند؛ Event خود State نیست.
- Reorg/duplicate/retry در Indexer و Business ledger اثر یکتا میسازد.
طراحی Generator، Shrink، Seed و Replay در راهنمای Property-Based Testing و سنجش قدرت Suite در راهنمای Mutation Testing تفصیل دارد.
Stateful Sequenceها را عمداً بسازید
Example stateful actions deploy / initialize / pause / unpause grant / revoke / renounce / rotate signer deposit / approve / transfer / withdraw / cancel repeat / reorder / front-run / same-block interleave oracle update stale/future/outlier bridge send / relay duplicate / relay late / source reorg upgrade valid / invalid storage / rollback / emergency pause RPC timeout / replacement / removed log / restart indexer After every action: assert authorization + state-machine + asset + event + off-chain invariants
Access Control را فقط با Happy path نسنجید
| Probe | Oracle |
|---|---|
| Unauthorized direct call | Revert و صفر State/asset effect |
| Call through proxy/fallback | همان authorization context مورد انتظار |
| Role grant/revoke/renounce | event + state + immediate/lag semantics |
| Multisig threshold/order | signer set، quorum، duplicate signature، expiry |
| Timelock | schedule→delay→execute/cancel و timestamp boundary |
| Pause/guardian | scope دقیق؛ read/withdraw/emergency paths |
| Admin key rotation | old key denied، new accepted، audit trace |
| Implementation direct init | initializer protection طبق pattern |
Reentrancy یک Pattern است، نه کل امنیت
Reentrancy را با Receiver مخرب، callbackهای تو در تو، cross-function/cross-contract path و state-before-external-call بررسی کنید؛ سپس authorization، arithmetic/rounding، signature replay/malleability assumptions، delegatecall/proxy، denial of service، forced asset، oracle manipulation، front-running/MEV، flash-loan composability و economic invariants را بر اساس Threat model پوشش دهید. OWASP Smart Contract Security Testing Guide یک مرجع Methodology است؛ Checklist آن Certification یا غیاب Vulnerability نیست.
Compiler، Bytecode و Deployment identity
Contract deployment manifest source commit + repository + reviewed tag compiler name/version + optimizer/viaIR/settings dependency/library versions + lockfile ABI + creation/runtime bytecode hashes network/chain ID + deployer + nonce + tx hash contract/proxy/implementation/admin/beacon addresses constructor/initializer args + salts/libraries verified-source status (if applicable) deployment block hash/number + finality state roles/owners/limits/oracles/bridges/upgrade policy artifact provenance + audit scope/report commit
«Source audited» کافی نیست اگر Bytecode دیگری Deploy شده، Compiler setting عوض شده یا Proxy به Implementation تازه اشاره میکند. Test report باید Code واقعی در Address و Block مشخص را به Source/Build متصل کند.
Upgradeability، Immutability را به Governance منتقل میکند
Proxy اجازه تغییر Logic پشت Address ثابت را میدهد؛ بنابراین سؤال از «کد تغییرناپذیر است؟» به «چه کسی، با چه Delay/Quorum و چه Compatibility میتواند Logic را عوض کند؟» منتقل میشود. راهنمای OpenZeppelin درباره Upgrade بر تست Implementation و تعامل از طریق Proxy و حفظ State بعد Upgrade تأکید میکند؛ آن را برای Pattern دقیق خود Tailor کنید.
| Upgrade test | Evidence/Oracle |
|---|---|
| Storage layout compatibility | slot/layout diff + state snapshot before/after |
| Initializer/reinitializer | یکبار، نسخه درست، unauthorized denied |
| Proxy/implementation identity | address/slot/event/code hash |
| Admin authorization | multisig/timelock/role negative tests |
| Old state/new behavior | invariants و historical positions |
| Pending operations | orders/withdrawals/votes across upgrade |
| Event/API compatibility | indexer/frontend old/new schemas |
| Rollback/emergency | امکان/محدودیت، state compatibility و decision rights |
Wallet و Signing Intent را E2E تست کنید
- Chain ID، account، recipient/contract، function، amount، decimals و fee برای کاربر روشن است.
- Network switch/reject، disconnect، locked wallet، unsupported chain و stale session رفتار امن دارند.
- User rejection هیچ Business state موفق ایجاد نمیکند.
- Signature نوع درست، domain/nonce/expiry و replay protection دارد.
- Blind/ambiguous calldata با simulation یا warning محدود میشود؛ UI نباید نتیجه را تضمین کند.
- Replacement/cancel با همان Nonce و Hash تازه به Intent اصلی وصل میشود.
- Multiple tabs/devices و concurrent nonce سبب double effect یا stuck state نمیشوند.
- Hardware wallet/mobile deep link/QR truncation/RTL و Address copy/paste آزمایش میشوند.
- Seed phrase/private key هرگز در Test log، screenshot، analytics یا support flow وارد نمیشود.
- Frontend compromise/DNS/dependency threat جدا از Contract audit دیده میشود.
Nonce، Replacement و Retry
| حالت | ریسک | انتظار |
|---|---|---|
| دو Request همزمان | Nonce collision | هماهنگی Signer/queue و identity |
| Fee پایین | Pending طولانی | status/expiry/bump policy؛ بدون Resubmit کور |
| Speed up | Hash تازه، همان Nonce | Replacement linkage و یک effect |
| Cancel | Race با تراکنش اصلی | فقط نتیجه Canonical، وضعیت صادقانه |
| RPC timeout پس از submit | Unknown commit | Probe by intent/sender+nonce/hash قبل Retry |
| Signer restart | local nonce stale | reconcile pending/latest policy |
| Chain reset/fork dev | nonce/state rewind | environment identity و reset consumers |
Event و Indexer را همانقدر جدی بگیرید که Contract را
Event ممکن است Duplicate، Late، Out-of-order یا Removed باشد؛ RPC range limit، pagination، provider inconsistency و indexer restart نیز Gap میسازند. Consumer باید checkpoint را با block hash نگه دارد، overlap/replay را idempotent مصرف کند، canonicality را بازبینی و Backfill را با Live stream هماهنگ کند.
Indexer correctness contract scope = chainId + contract addresses + topics + deployment block cursor = block number + block hash + log index identity = chainId:txHash:logIndex (plus canonical block tracking) read window = from/to with overlap and provider limit states = provisional | finalized | removed | disputed on reorg = rewind to common ancestor or bounded checkpoint on restart = replay idempotently; no gap/double business effect backfill/live handoff = explicit watermark completeness = compare sampled/raw RPC range and state reconciliation evidence = query/provider/version/timestamps/raw log hashes
RPC Provider را منبع حقیقت واحد فرض نکنید
Provider میتواند Lag، Rate limit، timeout، partial log range، archive limitation، wrong network، stale cache یا method difference داشته باشد. Chain ID/genesis/client sync head را در Health بسنجید؛ برای Critical query مقایسه چند endpoint یا local node تعریف کنید؛ disagreement را Unknown/Degraded نگه دارید و «اولین پاسخ ۲۰۰» را Truth ننامید.
Oracleها و Data feedها
Contract نمیتواند حقیقت بیرونی را از Consensus استخراج کند؛ Oracle یک Trust/dependency جدید است. Freshness، heartbeat، decimals، unit، source count/aggregation، outlier، zero/negative، future timestamp، stale-but-valid response، sequencer/down state، fallback و admin update را تست کنید. Manipulation resistance یک Claim اقتصادی/امنیتی مستقل است و با Mock price Pass نمیشود.
| Oracle probe | انتظار |
|---|---|
| Stale timestamp | reject/hold/fallback طبق max age |
| Decimal/unit mismatch | normalize درست یا fail closed |
| Outlier/zero/negative | domain guard و event |
| Future timestamp | clock/skew policy و reject |
| Feed unavailable | pause/bounded operation؛ نه last value نامحدود |
| Admin/feed switch | authorization/timelock/event و new-feed qualification |
| Rapid oscillation | business/economic invariant و rate control |
| Source disagreement | aggregation/uncertainty و alert |
Bridge و Cross-chain message
Bridge را «Transfer اتمیک» فرض نکنید. Source initiation، source finality، message proof/attestation، relay، destination execution، retry و refund/escape هرکدام State دارند. Reorg در Source، Duplicate relay، wrong destination/chain/domain، replay، partial outage، fee change و delayed finality را Fault-inject کنید؛ Supply/conservation را روی هر دو Chain و pending escrow reconcile کنید.
Cross-chain identity message_id + source_chain + source_tx/log + source_finality + bridge/version/domain + payload hash + nonce + relayer/attestation/proof identity + destination_chain + destination_tx/status/finality + asset/amount/decimals + escrow/mint/burn/release state + retry/refund/expiry and one-logical-effect invariant
Environment ladder: Local، Fork، Testnet، Mainnet
| محیط | خوب برای | اثبات نمیکند |
|---|---|---|
| Pure model/unit | منطق و Invariant سریع | EVM/client/RPC/network |
| Local single-node dev chain | execution، snapshot، time/block control | Consensus، public mempool، provider behavior |
| Local multi-client/network | client/RPC/peer/interoperability/fault | Public economics/validator diversity |
| Mainnet fork local | State/contract integration در block مشخص | آینده Mainnet، MEV، real finality/latency |
| Public testnet | wallet/RPC/deploy/operations shared | Mainnet liquidity/load/fee/adversary parity |
| Shadow/read-only Mainnet | real data/RPC/indexer observation | safe write behavior یا counterfactual |
| Bounded Mainnet canary | real end-to-end با limit و authority | غیاب Risk خارج bounds |
Environment identity و Reset
Chain test environment manifest chain ID + genesis hash + fork/source block hash client name/version/config + protocol fork rules node count/roles/keys + consensus/finality config RPC methods/limits/archive mode + provider identity block time/mining/time-travel/snapshot controls deployed address/bytecode/proxy/roles/oracle/bridge set funded accounts and synthetic asset balances indexer/database/queue versions and cursor fault controls: partition/restart/reorg/replacement/oracle/RPC seed/snapshot/reset proof + no real key/asset/effect created/expires owner + evidence retention
Fork testing؛ State واقعی، محیط واقعی نیست
Fork در Block مشخص، Balance/Code/Storage تاریخی را برای Integration فراهم میکند، اما Mempool، سایر کاربران، Oracle آینده، Validator/Sequencer، MEV، Public latency و Liquidity واقعی را بازسازی نمیکند. Block hash، RPC provider، archive completeness و impersonation را ثبت کنید؛ State fork بعد از Mutation دیگر History Mainnet نیست.
Gas، Fee و Performance را جدا کنید
| سنجه | معنا | دام |
|---|---|---|
| Gas used | کار محاسباتی/Storage طبق execution rules | قیمت پولی نیست |
| Gas/fee price | قیمت واحد در بازار/Protocol | با Code quality یکی نیست |
| Total fee | gas × price و اجزای Protocol | در زمان/شبکه متغیر |
| Block inclusion latency | submit تا inclusion | Finality latency نیست |
| Finality latency | inclusion تا status نهایی موردنیاز | Network-specific |
| RPC latency | Client↔Provider response | Chain throughput نیست |
| Indexer lag | canonical block تا searchable state | Contract execution نیست |
| TPS/throughput | workload پذیرفته/نهایی در زمان | بدون mix/state/validity بیمعناست |
Workload و Denominator برای Performance
Blockchain performance contract network/client/protocol/chain state and block limits transaction mix: read/write/functions/calldata/state warm-cold paths actor/account/nonce strategy and signer throughput submission rate vs accepted/included/finalized rates success/revert/drop/replace/reorg counts P50/P95/P99 submit→include→safe/finalized latency gas used / fee assumptions / state growth / log volume RPC rate limits/errors and indexer lag/backfill node CPU/memory/disk/network/peer/DB metrics duration/warmup/cooldown/repetitions/uncertainty no universal TPS claim outside this contract
Front-running، Ordering و MEV assumptions
اگر Outcome به ترتیب تراکنش حساس است، حالتهای same-block reorder، competing transaction، sandwich-like sequence، commit-reveal timing، deadline/slippage، nonce race و private/public submission را مدل کنید. Local miner با ترتیب دلخواه Scenario میسازد، اما ریسک اقتصادی واقعی یا محافظت قطعی را ثابت نمیکند. Property باید مستقل از ترتیب باشد یا Ordering assumption صریح و enforceشده داشته باشد.
Time و Block variables
- مرز دقیق قبل/برابر/بعد Deadline و Timelock را تست کنید.
- Timestamp را ساعت دیواری کاملاً دقیق فرض نکنید؛ Protocol assumption را بنویسید.
- Block number را Proxy زمان ثابت بین Chain/L2ها ندانید.
- Clock UI/Backend با Chain timestamp و timezone محلی جداست.
- Delayed inclusion ممکن است Transaction معتبر را بعد Deadline Revert کند.
- Time travel تست محلی باید Snapshot/Block identity و محدودیت را ثبت کند.
- Oracle timestamp، signed message expiry و nonce domain را با هم Boundary test کنید.
Off-chain Reconciliation آخرین Oracle است، نه Event
dApp معمولاً سفارش، کاربر، گزارش، Fiat ledger یا notification خارج Chain دارد. Transaction موفق بدون ثبت Business effect، و DB موفق بدون Finality Chain هر دو ناقصاند. Reconciliation باید Positionها را بر اساس Block/checkpoint و Asset/Decimals مقایسه، Missing/Duplicate/Removed/Unknown را دستهبندی و مسیر Repair با Authority روشن داشته باشد. اصول DB/Migration/Integrity در راهنمای تست پایگاه داده تکمیلکننده است.
| مغایرت | Probe | Repair ایمن |
|---|---|---|
| On-chain finalized، DB missing | replay raw canonical range | idempotent backfill |
| DB effect، log removed | canonicality/checkpoint | compensate/revert provisional |
| Duplicate DB effect | event/business identity | deduplicate با audit |
| Wrong decimals/unit | raw amount/token metadata/version | controlled correction، نه overwrite خاموش |
| RPC disagreement | multi-endpoint/local node | hold Unknown تا resolution |
| Indexer gap | block/hash cursor continuity | rewind/backfill bounded |
| Bridge pending too long | source/destination state/finality | protocol-defined retry/refund/escalation |
سناریوی ایرانی: تسویه Voucher آزمایشی، نه رمزارز واقعی
یک بازارگاه خیالی ایرانی برای محیط آزمایش از Voucher کاملاً ساختگی روی Chain محلی با Chain ID خیالی ۳۱۳۳۷ استفاده میکند. Voucher پول، رمزارز، دارایی قابلخرید یا توصیه سرمایهگذاری نیست. Backend پس از Finality آن را با Ledger سفارش Reconcile میکند؛ هیچ Mainnet، کیف پول شخصی، کلید واقعی یا انتقال مالی وجود ندارد. هدف صرفاً آزمون State/Indexer/Reconciliation است و هیچ ادعای حقوقی/رگولاتوری درباره ایران ندارد.
Fictional voucher settlement contract business identity = tenant/order/settlement-attempt/idempotency chain identity = chainId/contract/sender/nonce/txHash/logIndex/blockHash amount = canonical IRR in business ledger; voucher test units mapped explicitly display = labelled toman; Persian/Arabic/Latin digits; RTL/address handling time = UTC business event + Asia/Tehran/Jalali display + chain block time states = unsigned/signed/pending/replaced/reverted/included/removed/finalized faults = RPC timeout-after-submit, duplicate log, reorg, indexer restart, stale oracle oracle = Contract state + receipt/log + Order/Ledger/Outbox/Reconciliation data = synthetic; no PAN/CVV2/OTP/token/seed/private key effects = fake SMS/email/webhook; no real PSP/wallet/exchange/mainnet prohibited = auto-trust, legal/compliance/investment/real-money claims
فارسی، RTL، Address و Amount
- Address/Hash لاتین در RTL نباید visually reorder یا truncate خطرناک شود؛ copy value کامل و verification affordance بدهید.
- Token/Voucher decimals را با Integer raw amount نگه دارید؛ Floating point ممنوع.
- ریال/تومان از Token unit جدا و Conversion source/time/rounding آشکار است.
- ارقام فارسی/عربی/لاتین و Unicode normalization فقط در Display/Input، نه Hash/Address canonical، آزموده شوند.
- Explorer/Wallet deep link باید Chain/Address/Tx درست داشته باشد و Unknown network را باز نکند.
- Warning/Confirmation با Screen reader، keyboard و رنگ مستقل قابلفهم باشد.
- Finalized، Pending، Failed، Replaced و Reorged ترجمههای متمایز و غیرگمراهکننده دارند.
Key management و Test safety
- Test mnemonic/keys فقط برای Network تست و با Label واضح؛ هرگز Reuse در Mainnet/Production.
- CI log، Artifact، screenshot، crash report و analytics برای Secret scan آزموده شوند.
- Faucet/funded accounts limit، expiry، rotation و abuse control دارند.
- Signer service least privilege، chain/contract/function/value allowlist و audit دارد.
- High-value/admin path با hardware/multisig/timelock fidelity مناسب آزمایش میشود.
- Lost/compromised key drill، revoke/rotate/transfer authority و communication دارد.
- Test environment از Mainnet RPC/write و real wallets بهصورت Network/Policy مسدود است.
آیا Blockchain برای ثبت شواهد QA لازم است؟
معمولاً خیر. Signed manifest، immutable/object-lock storage، access log، append-only audit، artifact attestation و separation of duties اغلب سادهتر و کمهزینهترند. Blockchain زمانی Candidate است که چند سازمان با Authority مشترکنداشته، قواعد Membership/Governance روشن و نیاز واقعی به replicated shared log دارند. حتی آنگاه فقط Commitment/Hash و Metadata حداقلی On-chain بگذارید؛ Evidence اصلی، PII، Secret و داده قابلحذف Off-chain بماند.
| سؤال Build/Don’t-build | اگر پاسخ منفی است |
|---|---|
| چند Writer مستقل و کماعتماد داریم؟ | DB/Audit log متمرکز کافیتر است |
| Consensus بر ترتیب/State مشترک لازم است؟ | Signed event stream/attestation |
| Governance، membership و dispute process داریم؟ | Ledger فقط اختلاف را دائمی میکند |
| Privacy/erasure/retention با replication سازگار است؟ | On-chain storage نامناسب |
| Oracle ورود داده قابلاعتماد است؟ | Hash، داده غلط را درست نمیکند |
| TCO/latency/operations/exit پذیرفته است؟ | راهحل سادهتر |
| Verifier Artifact اصلی را دارد؟ | Hash تنها Evidence را بازسازی نمیکند |
Hash timestamped چه چیزی را ثابت میکند؟
| میتواند پشتیبانی کند | بهتنهایی ثابت نمیکند |
|---|---|
| Bytes ارائهشده با Commitment برابرند | Bytes هنگام Capture درست/کامل بودند |
| Commitment تا زمان مشخص وجود داشته | Event واقعاً در همان زمان رخ داده |
| رکورد On-chain طبق Protocol تغییر نکرده | Storage/Key/Client/Oracle خارج Chain امن بود |
| Signer/Account تراکنش را امضا کرده | رضایت/Authority/قصد انسانی معتبر بوده |
| Participantها State را پذیرفتهاند | انطباق ISO/GDPR/قانون یا کیفیت محصول |
| ترتیب Ledger قابلبررسی است | Single source of truth جهان بیرون |
Crowdsourced bug bounty را Contract خودکار داوری نمیکند
Validity، Severity، Duplicate، Scope، Safe harbor، Disclosure و Reproduction غالباً نیاز به Context انسانی دارند. Smart Contract فقط میتواند Escrow/Payment را پس از یک Oracle/Authority تصمیمگیر اجرا کند؛ خودش حقیقت Bug را از Report متن آزاد تشخیص نمیدهد. Payment واقعی، تحریم، مالیات، ارز، هویت و dispute نیز مسائل حقوقی/مالی جدا هستند. این مقاله توصیه ساخت پلتفرم Bounty یا پرداخت رمزارزی نیست.
Privacy و حق حذف؛ Public ledger انبار داده آزمایش نیست
PII، ایمیل، شماره موبایل، IP، شناسه دستگاه، سند، Screenshot، Log خام، Prompt، کلید، Seed، Token دسترسی و Evidence کامل را روی Chain عمومی ننویسید. Replication و Permanence با Data minimization، Retention و Erasure tension ایجاد میکند. Hashکردن داده کمآنتروپی مانند شماره موبایل، آن را لزوماً ناشناس نمیکند؛ مهاجم میتواند فضای کوچک ورودی را حدس بزند. Salt/Keyed commitment نیز باید Threat model، custody و rotation داشته باشد.
| ریسک | تست لازم | کنترل ترجیحی |
|---|---|---|
| Linkability تراکنشها | آیا Address، زمان و Amount کاربر را قابلپیوند میکند؟ | Pseudonymous را Anonymous ننامید؛ Metadata را کم کنید |
| Low-entropy hash | Dictionary attack با داده مصنوعی | داده را On-chain نگذارید؛ keyed commitment محدود |
| Deletion request | حذف Off-chain و باقیماندن Commitment چه افشا میکند؟ | Retention map و tombstone بدون PII |
| Event leakage | ABI/Eventها Secret یا Business detail نشت میدهند؟ | Minimal event schema |
| Explorer/indexer copies | داده در Replicaها و cacheها چقدر ماندگار است؟ | فرض کنید Public data قابلپسگرفتن نیست |
| Test data reuse | آیا Production snapshot/real wallet وارد Test شده؟ | Synthetic data و egress guard |
ارزیابی حریم خصوصی و قوانین محل فعالیت باید توسط نقشهای مسئول انجام شود؛ این متن نظر حقوقی نیست. تست فقط نشان میدهد Control طراحیشده در Scenario مشخص چگونه رفتار کرده است.
Compliance؛ Ledger یک جزء Evidence است، نه گواهی انطباق
رکورد On-chain نه ISO، نه Privacy law، نه Financial regulation و نه Audit readiness را خودکار تأمین میکند. Auditor هنوز باید Scope، Control objective، مالک، approval، population، sampling، exception و remediation را ببیند. برای ارائه خوانا و قابلردیابی نتایج، الگوی داشبورد و شواهد نتایج تست را نیز در نظر بگیرید؛ Hash جای Evidence package را نمیگیرد.
Minimum evidence manifest system/release/environment/chain/client/compiler/proxy identities requirement-risk-control-test-case mapping + owner/approver synthetic input fixture and deterministic seed transaction hash + chainId + blockHash + logIndex + finality policy raw receipt/log/trace when permitted + canonicality verification time contract address/bytecode/ABI/storage layout/role/oracle/bridge versions expected/actual/oracle/verdict + uncertainty and known limitations artifact digest/signature/storage URI/retention/access log exceptions/reruns/manual interventions/remediation links privacy classification/redaction/deletion and independent review
Monitoring؛ Finalized سبز بهتنهایی کافی نیست
| سطح | Signalهای کلیدی | هشدار معنادار |
|---|---|---|
| Chain/Node | head/safe/finalized، sync، peers، client/version، reorg depth | Finality lag یا اختلاف canonical head |
| RPC | latency/error/rate limit، method coverage، endpoint disagreement | Quorum read اختلاف دارد یا archive query ناقص است |
| Transaction | pending age، replacement، drop، revert reason، inclusion/finality | Age نسبت به SLO، نه هر Pending کوتاه |
| Contract | paused، role/admin change، upgrade، invariant sentinel | تغییر Authority یا Implementation خارج Change window |
| Oracle/Bridge | freshness، deviation، signer/source quorum، queue/backlog | Stale/disagree/pending beyond protocol timeout |
| Indexer | cursor، block/hash continuity، removed logs، lag/backfill | Gap، duplicate effect یا cursor روی Fork قدیمی |
| Off-chain | reconciliation mismatch، outbox/queue، business status | Finalized effect بدون DB یا DB effect بدون canonical log |
| Signer/Key | availability، deny/audit، nonce، rotation/expiry | Policy violation یا unexplained signing burst |
| Cost/Capacity | gas/fee، state/log growth، disk/CPU/network | Budget burn یا headroom کمتر از Release contract |
Dashboard باید Network و Finality policy را روی هر عدد نمایش دهد. «موفقیت ۹۹٪» بدون Denominator، status boundary و بازه زمانی قابلتفسیر نیست. Synthetic probe هم باید با Account/Amount علامتگذاریشده اجرا شود تا بهاشتباه Business transaction حساب نشود.
Runbook رخداد Blockchain/dApp
- Declare و Scope: Chain، Contract، Proxy implementation، Wallet/RPC، Oracle/Bridge، Indexer و Business effect آسیبدیده را مشخص کنید.
- حفظ شواهد: head/safe/finalized، block/hash، receipt/log/trace، removed flag، RPC responses، deployment/role/oracle/admin state، cursor و Timeline را Append-only ثبت کنید.
- Contain: اگر اختیار و Runbook تأییدشده وجود دارد، UI write یا Route معیوب را محدود کنید؛ Pause/Key revoke/Provider switch خودشان ریسک و approval دارند.
- Classify: Chain/consensus، RPC/provider، contract، upgrade، signer/key، wallet، oracle، bridge، indexer، backend یا presentation را با Probe مستقل تفکیک کنید.
- Canonical reconcile: Range محدود را از checkpoint معتبر replay و provisional/removed/finalized را جدا کنید؛ داده Unknown را Success/Failure حدس نزنید.
- Recover: مسیر repair، compensation، retry، upgrade یا rollback فقط با governance، idempotency و dry run اجرا شود.
- Verify: Invariantها، access، transaction lifecycle، reorg، reconciliation و monitoring را در محیط متناظر دوباره آزمایش کنید.
- Communicate: Network/asset/status/impact و uncertainty را بدون وعده Finality یا Recovery نادرست بیان کنید.
- Learn: Detection gap، authority، blast radius، test escape، زمان بازیابی و Action owner/due date را ثبت کنید.
Rollback در Blockchain معادل پاککردن History نیست. Upgrade یا قرارداد جایگزین ممکن است رفتار آینده را عوض کند، اما Effect گذشته، دارایی، Event و Replicaهای Off-chain نیازمند Migration/Compensation صریحاند.
Release Gate؛ چه چیزی باید مانع انتشار شود؟
| Gate | شاهد عبور | نمونه Stop condition |
|---|---|---|
| Identity/Build | source→compiler→bytecode→address/proxy traceable | bytecode یا storage layout نامعلوم |
| Invariant/State | example + property/fuzz/stateful suites | نقض conservation/authorization |
| Security/Access | threat tests، static/dynamic/manual review | critical open finding یا admin bypass |
| Transaction | revert/drop/replace/reorg/finality paths | Success UI قبل از policy finality |
| Wallet/Intent | chain/domain/function/value simulation | signing ambiguity یا wrong-chain path |
| RPC/Indexer | provider fault + rewind/replay/idempotency | duplicate business effect یا gap repair نامشخص |
| Oracle/Bridge | stale/deviation/quorum/pause/recovery | fail-open ناخواسته یا double completion |
| Upgrade/Governance | storage/access/timelock/migration rehearsal | state corruption یا unowned emergency action |
| Reconciliation | zero unexplained mismatch در bounded range | finalized vs ledger discrepancy بیمالک |
| Performance/Cost | workload-defined tail latency/gas/headroom | SLO یا cost budget نقضشده |
| Operations | alert، runbook، drill، key recovery و exit | critical alert بیمالک یا recovery آزمودهنشده |
| Evidence/Privacy | manifest، retention، redaction، approvals | secret/PII در Chain یا artifact عمومی |
Gate باید Risk-based، از پیش توافقشده و دارای Exception owner/expiry باشد. Audit یا Formal verification ارزشمند است اما اثبات نبود همه خطاها نیست؛ برای مرزبندی Proof و implementation، راهنمای روشهای رسمی در تست نرمافزار را ببینید.
نقشها و Decision rightها
| نقش | مالک تصمیم | شاهد لازم |
|---|---|---|
| Product/Business | State و Finality قابلقبول برای اثر کسبوکار | state model، compensation و user wording |
| Protocol/Contract engineer | Invariant، ABI/Event، upgrade/storage | spec، deployment manifest و migration |
| QA/Test architect | Risk model، environment، oracle و coverage | traceability، test result و limitations |
| Security | Threat، finding severity و key/signing controls | review، retest و accepted residual risk |
| Platform/SRE | Node/RPC/indexer، SLO، alert و recovery | telemetry، capacity، drill و runbook |
| Data/Backend | Indexer cursor، schema و reconciliation | continuity، idempotency و mismatch report |
| Governance/Operations | admin، pause، upgrade، oracle/bridge و incident action | multisig/timelock/approval audit |
| Privacy/Compliance/Legal | data classification، retention و jurisdictional assessment | review و exception؛ نه صرفاً Chain record |
| Release owner | Go/No-go و exception expiry | Gate summary و sign-offهای مستقل |
یک نفر نباید هم Contract را Deploy کند، هم Oracle تست را تعریف کند و هم نتیجه را بدون Review تأیید کند. برای Emergency action نیز نام فرد کافی نیست: Threshold، جانشین، زمان پاسخ، Scope اختیار و مسیر Audit باید قبل از Incident تمرین شوند.
برنامه ۳۰روزه برای ساخت Baseline تست dApp
| بازه | خروجی | Exit criteria |
|---|---|---|
| روز ۱–۵ | Chain/Trust contract، component map، asset/role/invariant و transaction state model | Network/finality و Business effects مبهم نیست |
| روز ۶–۱۰ | Local deterministic environment، deployment identity، unit/property/stateful suites | Reset/reproduce و seed/artifact ممکن است |
| روز ۱۱–۱۵ | Wallet/RPC fault، revert/replace/reorg، event indexer replay | هیچ Duplicate business effect و silent gap نداریم |
| روز ۱۶–۲۰ | Oracle/Bridge/upgrade/access/security scenarios | Stale/failover/pause/migration authority روشن است |
| روز ۲۱–۲۵ | Workload performance، gas/cost، off-chain reconciliation و privacy review | SLO/budget/retention با Denominator تأیید شده |
| روز ۲۶–۳۰ | Monitoring، incident drill، release gate و signed evidence manifest | Go/No-go simulation و Action owner/due date ثبت شده |
این برنامه نسخه تضمینی یا زمانبندی همه پروژهها نیست. دامنه یک Contract/Flow پرریسک را انتخاب کنید، Baseline را بسازید و فقط پس از مشاهده Gapها Scale دهید. معیار موفقیت «تعداد تست» نیست؛ کاهش حالت Unknown، قابلیت بازسازی Failure و جلوگیری از اثر تکراری/گمشده است.
۲۰ ضدالگوی رایج در Blockchain Testing
- یکیدانستن Broadcast، Inclusion و Finality.
- نمایش Success فقط با داشتن Tx hash.
- شمردن هر Event delivery بهعنوان Business effect جدید.
- نادیدهگرفتن
removed=trueو Block hash در Indexer. - استفاده از Tx hash بهعنوان تنها Business idempotency key.
- تست فقط Happy path قرارداد و حذف Sequenceهای Stateful.
- اعتماد به Exampleها بدون Invariant و Boundary.
- نامیدن Fork محلی بهعنوان رفتار واقعی Mainnet.
- گزارش TPS بدون workload، validity و Finality boundary.
- یکیدانستن Gas used، Fee و Performance.
- اعتماد به یک RPC endpoint بهعنوان حقیقت مستقل.
- نادیدهگرفتن Wallet intent، Chain ID و signing domain.
- تست Upgrade فقط با Deployشدن Implementation جدید.
- فرض اینکه Oracle/Bridge جزئی خارجی و خارج Scope است.
- Pause یا Admin key بدون drill، threshold و جانشین.
- قرار دادن PII، Secret یا Evidence خام روی Public chain.
- نامیدن Hash یا Immutability بهعنوان اثبات صحت داده.
- فرض اینکه Audit یا Formal proof نبود همه Bugها را تضمین میکند.
- Repair با overwrite خاموش DB بهجای reconciliation قابلردیابی.
- اتصال محیط تست به Wallet، Asset، PSP یا Mainnet واقعی.
چکلیست نهایی تست بلاکچین و dApp
- □ Chain ID، Protocol/client version و Finality policy ثبت شده است.
- □ Trust boundary و Writer/Admin/Oracle/Bridge authority روشن است.
- □ Asset، unit، decimals، conservation و authorization invariant داریم.
- □ Source/compiler/bytecode/address/proxy/storage identity قابلردیابی است.
- □ Unit، integration، property/fuzz، stateful و manual security review ترکیب شدهاند.
- □ Pending، dropped، replaced، reverted، included، removed و finalized آزموده شدهاند.
- □ Wallet متن امضا، Domain، Chain، Contract، Function و Value درست نشان میدهد.
- □ RPC timeout-after-submit و endpoint disagreement نتیجه Unknown ایمن دارند.
- □ Event identity، duplicate delivery، rewind/replay و indexer gap پوشش داده شدهاند.
- □ Oracle stale/deviation/quorum/failure و recovery تست شده است.
- □ Bridge source/destination/retry/replay/refund و double completion پوشش دارد.
- □ Upgrade access، initializer، storage layout، event و rollback/exit rehearsal دارد.
- □ Workload، tail latency، Finality، gas/fee و resource headroom تعریف شدهاند.
- □ Front-running/order/deadline/time assumptions صریحاند.
- □ On-chain و Off-chain با checkpoint canonical Reconcile میشوند.
- □ فارسی/RTL، Address، عدد، ریال/تومان و timezone گمراهکننده نیست.
- □ Test data/keys/accounts مصنوعیاند و مسیر Production/Mainnet مسدود است.
- □ PII/Secret/Evidence کامل On-chain یا عمومی نشده است.
- □ Alert/Runbook/authority/incident drill و repair idempotent داریم.
- □ Release gate، exception owner/expiry و evidence manifest تأیید شدهاند.
جمعبندی؛ Oracle را از Chain تا کسبوکار دنبال کنید
کیفیت dApp از «تغییرناپذیری» یا سبزشدن Unit Test بهدست نمیآید. تست بلاکچین زمانی قابلاتکاست که Network و Finality تعریف شده، تراکنش یک State machine باشد، Invariantهای قرارداد و دارایی سنجیده شوند، Wallet/RPC/Indexer خطاپذیر فرض شوند، Oracle/Bridge/Upgrade تحت Fault قرار گیرند و Effect نهایی با Ledger خارج Chain Reconcile شود. نتیجه باید دقیقاً بگوید در کدام Chain، Block، Build، State و محدودیت معتبر است.
از یک Flow پرریسک شروع کنید: Contract تست، State transition و Event identity را بنویسید؛ یک Reorg و timeout-after-submit قطعی بسازید؛ سپس Release gate و runbook را با Evidence قابلبازتولید تمرین کنید. این مسیر از ادعای کلی «Blockchain اعتماد میسازد» به سؤال مهندسی قابلآزمون میرسد: چه کسی، به کدام State، با کدام Finality و کدام Oracle اعتماد میکند؟
پرسشهای متداول تست بلاکچین
۱. آیا Unit Test قرارداد هوشمند برای تست dApp کافی است؟
خیر. Unit Test منطق Function را سریع بررسی میکند، اما Wallet و امضا، RPC، lifecycle تراکنش، Reorg/Finality، Indexer، Oracle/Bridge، Upgrade و Reconciliation خارج Chain را پوشش نمیدهد. ترکیب تستهای واحد، Integration، Property/Fuzz، Stateful، Security، Performance و Operational drill لازم است؛ دامنه ترکیب به Risk بستگی دارد.
۲. Confirmation و Finality چه تفاوتی دارند؟
Confirmation معمولاً عمق یا مشاهده Block پس از Inclusion است؛ Finality معنای Protocol-specific درباره احتمال/امکان بازگشت State دارد. عدد ثابت Confirmation را بدون نام Network، Protocol، Block tag و Risk policy «نهایی» ننامید. UI و Backend باید statusهای provisional و finalized را متمایز کنند.
۳. Reorg را چگونه تست کنیم؟
در Node/Devnet یا Harness قطعی، Log اولیه را provisional ingest کنید، همان Log را با block identity قدیمی removed کنید، شاخه canonical جدید را ingest و سپس Finality را اعمال کنید. انتظار این است که اثر موقت معکوس، Duplicate delivery بیاثر و اثر canonical فقط یکبار ثبت شود. شبیهسازی Local اثبات احتمال یا عمق Reorg شبکه واقعی نیست.
۴. بهترین ابزار Blockchain Testing کدام است؟
ابزار واحدی بهترین نیست. Runner قرارداد، local node/devnet، property fuzzer، static analyzer، Wallet/RPC stub، indexer replay harness، load generator و observability هرکدام Oracle متفاوتی میدهند. ابتدا Chain/Threat contract و Failure موردنظر را تعریف کنید، سپس ابزاری انتخاب کنید که همان State و Evidence را بهصورت تکرارپذیر کنترل کند.
۵. آیا ثبت نتیجه تست روی Blockchain اعتماد کامل ایجاد میکند؟
خیر. Commitment میتواند تطابق Bytes و وجود یک رکورد را پشتیبانی کند، اما صحت Capture، کاملبودن Evidence، صلاحیت Signer، کیفیت Oracle، حریم خصوصی یا انطباق را تضمین نمیکند. برای بیشتر تیمها signed manifest و storage دارای Object lock/access audit سادهتر است؛ Blockchain فقط با مسئله واقعی چند Writer مستقل و Governance روشن توجیه میشود.

